From 0bd14a4a155d6e6985aef1985366777d1e0544df Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Fri, 29 Jul 2022 16:55:09 +0100 Subject: [PATCH 01/31] Updates scaladocs throughout (WIP) --- .../com/workflowfm/proter/DiscreteEvent.scala | 65 +++++-- .../com/workflowfm/proter/Distributions.scala | 4 +- .../com/workflowfm/proter/cases/Case.scala | 32 ++++ .../com/workflowfm/proter/cases/CaseRef.scala | 159 ++++++++++++---- .../com/workflowfm/proter/events/Event.scala | 39 ++-- .../proter/events/EventHandler.scala | 34 ++-- .../proter/events/JsonHandler.scala | 9 + .../workflowfm/proter/events/Publisher.scala | 25 ++- .../proter/events/StringHandler.scala | 7 +- .../proter/events/TimedHandler.scala | 12 +- .../com/workflowfm/proter/flows/Flow.scala | 69 ++++--- .../proter/metrics/CaseMetrics.scala | 31 ++-- .../workflowfm/proter/metrics/Metrics.scala | 169 +++++++++++------- .../proter/metrics/MetricsOutput.scala | 102 ++++++----- .../proter/metrics/MetricsSubscriber.scala | 16 ++ .../proter/metrics/ResourceMetrics.scala | 31 ++-- .../proter/metrics/TaskMetrics.scala | 26 +-- .../workflowfm/proter/schedule/Schedule.scala | 15 -- .../proter/schedule/Scheduler.scala | 17 +- .../proter/schedule/WeightedSchedule.scala | 35 +++- .../com/workflowfm/proter/cases/Case.scala | 4 +- 21 files changed, 598 insertions(+), 303 deletions(-) diff --git a/proter/src/main/scala/com/workflowfm/proter/DiscreteEvent.scala b/proter/src/main/scala/com/workflowfm/proter/DiscreteEvent.scala index c4f3462..e0ae729 100644 --- a/proter/src/main/scala/com/workflowfm/proter/DiscreteEvent.scala +++ b/proter/src/main/scala/com/workflowfm/proter/DiscreteEvent.scala @@ -9,7 +9,7 @@ import cats.implicits.* import java.util.UUID /** - * Discrete Events that need to be handled by the [[Coordinator]].. + * Discrete Events occurring during simulation. */ sealed trait DiscreteEvent extends Ordered[DiscreteEvent] { /** The virtual timestamp of the event */ @@ -57,12 +57,12 @@ sealed trait DiscreteEvent extends Ordered[DiscreteEvent] { } /** - * Event fired when a [[Task]] has finished. + * Event fired when a [[TaskInstance]] has finished. * * @param time * The timestamp of the event * @param task - * The [[Task]] that was finished. + * The [[TaskInstance]] that was finished. */ case class FinishingTask(override val time: Long, task: TaskInstance) extends DiscreteEvent { override val classOrder: Short = 5 @@ -74,12 +74,12 @@ case class FinishingTask(override val time: Long, task: TaskInstance) extends Di } /** - * Event fired when a simulation needs to start. + * Event fired when a case needs to start. * * @param time * The timestamp of the event - * @param simulation - * The [[Simulation]] that needs to start. + * @param caseRef + * The [[CaseRef]] that needs to start. */ case class StartingCase[F[_]](override val time: Long, caseRef: CaseRef[F]) extends DiscreteEvent { override val classOrder: Short = 10 @@ -105,17 +105,22 @@ case class TimeLimit(override val time: Long) extends DiscreteEvent { /** * Event used to model a repeating process. * - * An arrival rate is used to indicate when new instances of a simulation should be added to the - * coordinator. + * An arrival rate is used to indicate when new instances of a case should be added. * + * @tparam T + * The type of the object to use in the case. * @param time - * The timestamp of the event + * The timestamp of the event. + * @param name + * A unique name prefix to give to all arriving cases. + * @param t + * The object to use to construct the cases. * @param rate - * The arrival rate of the simulation - * @param simulationGenerator - * The simulation generator for getting new instances of a simulation + * The arrival rate of the case. + * @param limit + * An optional limit to the number of cases to generate. * @param count - * A counter of the next simulation instance that will be generated + * A counter of the number of cases generated. */ case class Arrival[F[_] : Monad : Random, T]( @@ -136,10 +141,10 @@ case class Arrival[F[_] : Monad : Random, T]( } /** - * Generates the next arrival event to be queued. + * Generates the next arrival event to be queued and [[CaseRef]] to add. * * @return - * The next arrival event. + * The next arrival event and [[CaseRef]], unless the limit is reached. */ def next(): Option[F[(Arrival[F, T], CaseRef[F])]] = limit.filter(_ <= count) match { case None => @@ -163,8 +168,22 @@ case class Arrival[F[_] : Monad : Random, T]( import collection.immutable.{ SortedMap, SortedSet } +/** + * A priority queue for [[DiscreteEvent]]s. + * + * @param events + * An underlying `SortedMap` of events, grouped by timestamp. + */ case class EventQueue(events: SortedMap[Long, SortedSet[DiscreteEvent]]) { + /** + * Adds a new event to the queue. + * + * @param event + * The [[DiscreteEvent]] to add. + * @return + * The updated event queue. + */ def +(event: DiscreteEvent): EventQueue = { copy(events = events.updatedWith(event.time) { case None => Some(SortedSet(event)) @@ -172,6 +191,12 @@ case class EventQueue(events: SortedMap[Long, SortedSet[DiscreteEvent]]) { }) } + /** + * Pops the next set of events in the queue, if any. + * + * @return + * The timestamp and set of events, and the updated event queue. + */ def next(): Option[(Long, SortedSet[DiscreteEvent], EventQueue)] = events.headOption.map { (k, v) => (k, v, copy(events = events - k)) @@ -181,6 +206,16 @@ case class EventQueue(events: SortedMap[Long, SortedSet[DiscreteEvent]]) { def isEmpty: Boolean = events.isEmpty + /** + * Returns the `UUID`s of all tasks of a given case that are scheduled to finish. + * + * This is used to find out which tasks need to be aborted if a case is aborted. + * + * @param caseName + * The name of the case whose tasks we are looking for. + * @return + * An `Iterable` of associated task `UUID`s. + */ def tasksOf(caseName: String): Iterable[UUID] = { def matchingTask(evt: DiscreteEvent): Option[UUID] = evt match { case FinishingTask(_, task) if task.caseName == caseName => Some(task.id) diff --git a/proter/src/main/scala/com/workflowfm/proter/Distributions.scala b/proter/src/main/scala/com/workflowfm/proter/Distributions.scala index 304cc6e..116fe7a 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Distributions.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Distributions.scala @@ -52,10 +52,10 @@ trait LongDistribution { trait Distribution extends LongDistribution { /** - * Provides a sample value. + * Provides a sample `Double` value. * * @return - * A sample value. + * A sample `Double` value. */ def get[F[_] : Applicative : Random]: F[Double] diff --git a/proter/src/main/scala/com/workflowfm/proter/cases/Case.scala b/proter/src/main/scala/com/workflowfm/proter/cases/Case.scala index fa6424d..1a06d09 100644 --- a/proter/src/main/scala/com/workflowfm/proter/cases/Case.scala +++ b/proter/src/main/scala/com/workflowfm/proter/cases/Case.scala @@ -10,10 +10,42 @@ import cats.effect.std.{ Random, UUIDGen } import java.util.UUID +/** + * Typeclass for the generation of simulation cases based on a custom object. + * + * This functions as a builder for new [[CaseRef]]s given a custom class that can describe the + * simulation logic. + * + * @tparam F + * The effect type for the case. + * @tparam T + * The object type / argument of the type class. + */ trait Case[F[_], T] { + /** + * Initialize a new [[CaseRef]]. + * + * This method provides the case count and simulation time as additional parameters. These can be + * useful in dynamic cases whose behaviour changes based on how many times the case has started + * or the current time (e.g. if timing is during a virtual weekend). + * + * @param name + * A (assumed unique) name to be given to the [[CaseRef]]. + * @param count + * The number of cases generated in this simulation (e.g. by an arrival). + * @param time + * The virtual time when this [[CaseRef]] is being generated during simulation. + * @param t + * The object to use in order to generate the [[CaseRef]]. + * @return + * The generated [[CaseRef]]. + */ def init(name: String, count: Int, time: Long, t: T): F[CaseRef[F]] } +/** + * Case consisting of a single task. + */ given [F[_]](using Monad[F], UUIDGen[F], Random[F]): Case[F, Task] with { override def init(name: String, count: Int, time: Long, t: Task): F[CaseRef[F]] = for { diff --git a/proter/src/main/scala/com/workflowfm/proter/cases/CaseRef.scala b/proter/src/main/scala/com/workflowfm/proter/cases/CaseRef.scala index 17c9367..24ba1f5 100644 --- a/proter/src/main/scala/com/workflowfm/proter/cases/CaseRef.scala +++ b/proter/src/main/scala/com/workflowfm/proter/cases/CaseRef.scala @@ -15,24 +15,25 @@ import scala.collection.immutable.{ HashSet, Queue } import scala.util.{ Try, Success, Failure } /** - * An abstract reference to simulation case logic. + * A single instance of a simulation case. * - * Includes the basic interface that we expect from a simulation case: - * 1. Starting the case. - * 1. Notifying when tasks complete. - * 1. Stopping/aborting the case. + * @tparam F + * The effect type. */ trait CaseRef[F[_] : Monad] extends CaseState { /** - * A unique name for the case. + * A unique name for the instance. * * @return - * The name of the case. + * The name of the instance. */ def caseName: String /** * Starts the case. + * + * @return + * The effect starting should have to the simulation state. */ def run(): F[SimState[F]] @@ -48,73 +49,166 @@ trait CaseRef[F[_] : Monad] extends CaseState { * The current virtual timestamp. * @param tasks * The [[TaskInstance]]s that completed. + * @return + * The effect this should have to the simulation state. */ def completed(time: Long, tasks: Seq[TaskInstance]): F[SimState[F]] /** - * Declares that the simulation completed. + * A simulation state where the case instance has completed. * - * @group act * @param result - * The result of the simulation. + * The final result of the case instance. + * @return + * The effect to the simulation state. */ def done(result: Try[Any]): SimState[F] = caseDone(caseName, result) /** - * Declares that the simulation completed successfully. + * A simulation state where the case instance has completed successfully. * - * @group act * @param result - * The successful result of the simulation. + * The successful result of the case instance. */ def succeed(result: Any): SimState[F] = done(Success(result)) /** - * Declares that the simulation has failed or has been aborted. + * A simulation state where the case instance has fail or was aborted. * - * @group act * @param exception * The `Throwable` that caused the failure. */ def fail(exception: Throwable): SimState[F] = done(Failure(exception)) + /** + * A simulation state that updates the instance itself in the simulation. + * + * @param c + * The updated case instance. + */ def update(c: CaseRef[F]): SimState[F] = updateCase(caseName, c) } +/** + * A [[CaseRef]] with an explicit state parameter. + * + * @tparam F + * The effect type. + * @param state + * The current state. + */ abstract class StatefulCaseRef[F[_] : Monad, S](val state: S) extends CaseRef[F] { + /** + * A copy constructor for this case instance. + * + * This is used to construct copies of subclasses of `StatefulCaseRef`. + * + * @param newState + * The new state to use in the copy. + * @return + * A copy of the instance with the new state. + */ def updateState(newState: S): StatefulCaseRef[F, S] + /** + * Computes the simulation and internal state update from a single completed task. + * + * @param task + * The [[TaskInstance]] that completed. + * @param time + * The current virtual timestamp. + * @return + * A `StateT` monad of the effect to the internal state and the resulting simulation state + * effect. + */ def complete(task: TaskInstance, time: Long): StateT[F, S, SimState[F]] + /** + * @inheritdoc + * + * Updates the internal state based on the effect from each individual completed task. + */ override def completed(time: Long, tasks: Seq[TaskInstance]): F[SimState[F]] = { val fold = tasks.foldLeft(StateT.pure[F, S, SimState[F]](StateT.pure(Seq()))) { (state, task) => composeStates(state, complete(task, time)) } - compose(fold) + applyState(fold) } + /** + * Shortcut to succeed directly within [[complete]]. + * + * @see + * [[succeed]] + * @param result + * The successful result of the case instance. + */ def succeedState(result: Any): StateT[F, S, SimState[F]] = StateT.pure(succeed(result)) + /** + * Shortcut to fail directly within [[complete]]. + * + * @see + * [[fail]] + * @param exception + * The `Throwable` that caused the failure. + */ def failState(exception: Throwable): StateT[F, S, SimState[F]] = StateT.pure(fail(exception)) + /** + * Compose 2 state updates together. + * + * State types are the ones returned by [[complete]]. + * + * @param s1 + * The first state. + * @param s2 + * The second state. + * @return + * The composed single state. + */ def composeStates( s1: StateT[F, S, SimState[F]], s2: StateT[F, S, SimState[F]] ): StateT[F, S, SimState[F]] = s1.flatMap { r1 => s2.map { r2 => Simulation.compose(r1, r2) } } + /** + * A state update that does nothing. + */ val idState: StateT[F, S, SimState[F]] = StateT.pure(StateT.pure(Seq())) - def compose(s: StateT[F, S, SimState[F]]): F[SimState[F]] = + /** + * Update the internal state and then the simulation state. + * + * @see + * [[update]] + * @param s + * The state update to use. + * @return + * The resulting simulation state update. + */ + def applyState(s: StateT[F, S, SimState[F]]): F[SimState[F]] = s.modify(s => update(updateState(s))).run(state).map((s1, s2) => Simulation.compose(s1, s2)) } +/** + * A [[CaseRef]] that can asynchronously react to completed tasks using callback functions. + * + * @tparam F + * The effect type. + * @param callbackMap + * A map of callback functions to be used. + */ abstract class AsyncCaseRef[F[_] : Monad : UUIDGen : Random](callbackMap: CallbackMap[F]) extends StatefulCaseRef[F, CallbackMap[F]](callbackMap) { + /** + * A shortcut to the type of a callback function. + */ type Callback = AsyncCaseRef.Callback[F, CallbackMap[F]] /** @@ -131,23 +225,12 @@ abstract class AsyncCaseRef[F[_] : Monad : UUIDGen : Random](callbackMap: Callba t => t.map { arg => f(arg._1, arg._2) }.getOrElse(StateT.pure(StateT.pure(Seq()))) /** - * Declare a new [[Task]] that needs to be sent to the [[Coordinator]] for simulation with a - * pre-determined ID. + * State update that adds a new [[Task]] for simulation and a corresponding callback. * * The provided callback function will be called when the corresponding [[Task]] is completed. * - * When it finishes executing, it must notify the [[Coordinator]] either by acknowledging the - * completed task using [[ack]] or by completing the simulation using [[done]], [[succeed]] or - * [[fail]]. - * - * The [[ready]] method can also be called if there is no need to acknowledge completed tasks - * individually. This is unlikely in the current scenario where each task has its own callback, - * but it's still worth mentioning. - * - * @group act - * * @param t - * The [[Task]] to send. + * The [[Task]] to add. * @param callback * The [[Callback]] function to be called when the corresponding [[Task]] completes. */ @@ -165,9 +248,7 @@ abstract class AsyncCaseRef[F[_] : Monad : UUIDGen : Random](callbackMap: Callba /** * @inheritdoc * - * Calls the corresponding [[Callback]] in the `tasks` map and then removes the entry. - * - * @group react + * Calls the corresponding [[Callback]] in the map and then removes the entry. * * @param task * The [[TaskInstance]] that completed. @@ -215,9 +296,21 @@ abstract class AsyncCaseRef[F[_] : Monad : UUIDGen : Random](callbackMap: Callba } object AsyncCaseRef { + /** + * The type for task callbacks. + * + * A callback is a function from a [[TaskInstance]] and its completion timestamp to a state + * update. + */ type Callback[F[_], S] = Monad[F] ?=> Try[(TaskInstance, Long)] => StateT[F, S, SimState[F]] } +/** + * Convenience wrapper for a map of callbacks. + * + * @param m + * The internal map. + */ case class CallbackMap[F[_]](m: Map[UUID, AsyncCaseRef.Callback[F, CallbackMap[F]]]) { type Callback = AsyncCaseRef.Callback[F, CallbackMap[F]] def +(kv: (UUID, Callback)): CallbackMap[F] = copy(m = m + kv) diff --git a/proter/src/main/scala/com/workflowfm/proter/events/Event.scala b/proter/src/main/scala/com/workflowfm/proter/events/Event.scala index c7f2c67..7f44d6c 100644 --- a/proter/src/main/scala/com/workflowfm/proter/events/Event.scala +++ b/proter/src/main/scala/com/workflowfm/proter/events/Event.scala @@ -11,7 +11,7 @@ import java.util.UUID */ sealed trait Event { /** - * A string representing the [[State]] that generated the event. + * A string representing the simulation that generated the event. */ val source: String @@ -41,12 +41,12 @@ final case class ETimeLimit( ) extends Event /** - * A [[TaskResource]] was added. + * A [[Resource]] was added. * * @param name * The name of the resource. - * @param costPerTick - * The [[TaskResource.costPerTick]] of the resource. + * @param resource + * The [[Resource]] that was added. */ final case class EResourceAdd( override val source: String, @@ -55,7 +55,7 @@ final case class EResourceAdd( ) extends Event /** - * A case was added. + * A case instance was added. * * @param name * The name of the case. @@ -72,12 +72,13 @@ final case class ECaseAdd( /** * An arrival was added. * + * @note + * The arrival rate is not included as there is no standard representation for distributions. + * * @param name * The name of the arriving cases. * @param start * The timestamp when arrivals is scheduled to start. - * @param rate - * The arrival rate. * @param limit * The optional limit of the number of cases to generate. */ @@ -90,21 +91,21 @@ final case class EArrivalAdd( ) extends Event /** - * A case was started. + * A case instance was started. * * @param name - * The name of the case. + * The name of the case instance. */ final case class ECaseStart(override val source: String, override val time: Long, name: String) extends Event /** - * A case was completed. + * A case instance was completed. * * @param name - * The name of the case. + * The name of the case instance. * @param result - * The output of the case (if any). + * The output result of the case (if any). */ final case class ECaseEnd( override val source: String, @@ -114,7 +115,7 @@ final case class ECaseEnd( ) extends Event /** - * A new [[Task]] was added in the queue. + * A new [[TaskInstance]] was added in the queue. * * @param task * The [[TaskInstance]] that was added. @@ -138,12 +139,12 @@ final case class ETaskStart( ) extends Event /** - * A [[TaskInstance]] was attached to a [[TaskResource]] as it started. + * A [[TaskInstance]] was attached to a [[Resource]] as it started. * * @param task * The [[TaskInstance]] that was attached. * @param resource - * The involved [[TaskResource]]. + * The corresponding [[ResourceState]] ''after'' the attachment of the task. */ final case class ETaskAttach( override val source: String, @@ -153,12 +154,14 @@ final case class ETaskAttach( ) extends Event /** - * A [[TaskInstance]] was detached from a [[TaskResource]] as it finished. + * A [[TaskInstance]] was detached from a [[Resource]] as it finished. * + * @param start + * The timestamp when the task had started. * @param task * The [[TaskInstance]] that was detached. * @param resource - * The involved [[TaskResource]]. + * The corresponding [[ResourceState]] ''after'' the detachment of the task. */ final case class ETaskDetach( override val source: String, @@ -187,7 +190,7 @@ final case class ETaskDone( ) extends Event /** - * A [[Task]] was aborted. + * A [[TaskInstance]] was aborted. * * @param id * The `UUID` of the [[TaskInstance]] that was aborted. diff --git a/proter/src/main/scala/com/workflowfm/proter/events/EventHandler.scala b/proter/src/main/scala/com/workflowfm/proter/events/EventHandler.scala index 8c757c0..1ea5500 100644 --- a/proter/src/main/scala/com/workflowfm/proter/events/EventHandler.scala +++ b/proter/src/main/scala/com/workflowfm/proter/events/EventHandler.scala @@ -16,6 +16,9 @@ import scala.collection.immutable.HashSet * A handler of [[Event]]s. * * Handles a stream of events from a [[Publisher]]. + * + * Provides a convenient breakdown of methods to facilitate implementation of custom handlers. + * Simply override the relevant methods to achieve the desired functionality. */ trait EventHandler[F[_] : Monad] extends Subscriber[F] { @@ -34,9 +37,6 @@ trait EventHandler[F[_] : Monad] extends Subscriber[F] { /** * Handles the initialisation of a new event stream. - * - * @param publisher - * The [[Publisher]] that started the stream. */ override def init(): F[Unit] = Monad[F].pure(()) @@ -50,9 +50,6 @@ trait EventHandler[F[_] : Monad] extends Subscriber[F] { /** * Handles the end of a stream. - * - * @param publisher - * The [[Publisher]] that ended the stream. */ def onDone(): F[Unit] = Monad[F].pure(()) @@ -61,13 +58,17 @@ trait EventHandler[F[_] : Monad] extends Subscriber[F] { * * @param e * The throwable error that occurred. - * @param publisher - * The [[Publisher]] that threw the error. */ def onFail(e: Throwable): F[Unit] = Monad[F].pure(()) } +/** + * An [[EventHandler]] that counts the number of events encountered. + * + * @param counter + * An immutable reference to the current count. + */ class CountEvents[F[_] : Monad](counter: Ref[F, Int]) extends EventHandler[F] { /** @@ -78,8 +79,14 @@ class CountEvents[F[_] : Monad](counter: Ref[F, Int]) extends EventHandler[F] { override def onEvent(e: Event): F[Unit] = counter.update(_ + 1) + /** + * Retrieves the current count. + */ def get(): F[Int] = counter.get + /** + * Resets the counter to 0. + */ def reset(): F[Unit] = counter.set(0) } @@ -92,12 +99,12 @@ object CountEvents { } /** - * Listens for the end of a named simulation and handles its result. + * Listens for the end of a specific case and handles its result. * * @param name - * The name of the [[SimulationRef]] to listen for. - * @param callback - * A function to handle the results of the simulation when it completes. + * The name of the [[CaseRef]] to listen for. + * @param result + * The deferred result output from the case. */ class GetCaseResult[F[_] : Monad](caseName: String, result: Deferred[F, String]) extends EventHandler[F] { @@ -105,8 +112,7 @@ class GetCaseResult[F[_] : Monad](caseName: String, result: Deferred[F, String]) /** * @inheritdoc * - * If the event is [[ESimEnd]] and the simulation name matches then we record the simulation - * result in [[simResult]], unsubscribe, and call the callback function. + * If the event is [[ESimEnd]] and the simulation name matches then we record the case result. */ override def onEvent(evt: Event): F[Unit] = evt match { case ECaseEnd(_, _, n, r) if n == caseName => { diff --git a/proter/src/main/scala/com/workflowfm/proter/events/JsonHandler.scala b/proter/src/main/scala/com/workflowfm/proter/events/JsonHandler.scala index a6700ee..d8eda63 100644 --- a/proter/src/main/scala/com/workflowfm/proter/events/JsonHandler.scala +++ b/proter/src/main/scala/com/workflowfm/proter/events/JsonHandler.scala @@ -14,9 +14,15 @@ import io.circe.{ Json, Encoder } import io.circe.generic.semiauto._ import io.circe.syntax.* +/** + * A [[TimedHandler]] that produces a JSON stream. + */ trait JsonHandler[F[_] : Applicative : Clock] extends TimedHandler[F] { import JsonHandler.given + /** + * A pipe to process the [[Publisher]] stream and produce JSON objects. + */ val jsonPipe: Pipe[F, Either[Throwable, Event], Json] = _.through(timedEventPipe).map(_.asJson) } @@ -32,6 +38,9 @@ object JsonHandler { given Encoder[TimedEvent] = deriveEncoder[TimedEvent] } +/** + * An [[Event]] handler that converts them to JSON and prints them to console. + */ class PrintJsonEvents[F[_] : Clock : Sync] extends Subscriber[F] with JsonHandler[F] { override def apply(s: Stream[F, Either[Throwable, Event]]): Stream[F, Unit] = diff --git a/proter/src/main/scala/com/workflowfm/proter/events/Publisher.scala b/proter/src/main/scala/com/workflowfm/proter/events/Publisher.scala index 5a31b19..61893fb 100644 --- a/proter/src/main/scala/com/workflowfm/proter/events/Publisher.scala +++ b/proter/src/main/scala/com/workflowfm/proter/events/Publisher.scala @@ -10,6 +10,11 @@ import java.util.UUID /** * A publisher of a stream of simulation [[Event]]s. + * + * @param topic + * The `fs2.Topic` used to broadcast events to all subscribers. + * @param maxQueued + * The maximum number of elements we can enqueue. */ case class Publisher[F[_]](topic: Topic[F, Either[Throwable, Event]], maxQueued: Int)( using MonadCancel[F, Throwable] @@ -19,7 +24,7 @@ case class Publisher[F[_]](topic: Topic[F, Either[Throwable, Event]], maxQueued: * Publishes an event into the stream. * * @param evt - * The event to publish. + * The [[Event]] to publish. */ def publish(evt: Event): F[Either[Topic.Closed, Unit]] = { val pub = topic.publish1(Right(evt)) @@ -30,6 +35,9 @@ case class Publisher[F[_]](topic: Topic[F, Either[Throwable, Event]], maxQueued: } } + /** + * Propagates a `Throwable` failure through the stream and then stops it. + */ def fail(e: Throwable): F[Either[Topic.Closed, Unit]] = topic.publish1(Left(e)) >> stop() /** @@ -38,10 +46,12 @@ case class Publisher[F[_]](topic: Topic[F, Either[Throwable, Event]], maxQueued: def stop(): F[Either[Topic.Closed, Unit]] = topic.close /** - * Subscribes an [[EventHandler]] to the stream so they can receive events. + * Subscribes a [[Subscriber]] to the stream so they can receive events. * * @param subscriber - * The [[EventHandler]] to subscribe. + * The [[Subscriber]]. + * @return + * The resulting stream resource. */ def subscribe(subscriber: Subscriber[F]): Resource[F, Stream[F, Unit]] = topic.subscribeAwait(maxQueued).evalMap { sub => @@ -50,6 +60,9 @@ case class Publisher[F[_]](topic: Topic[F, Either[Throwable, Event]], maxQueued: } yield sub.through(subscriber) } + /** + * Yields a subscriber stream of [[Event]]s directly. + */ def stream: Stream[F, Either[Throwable, Event]] = topic.subscribe(maxQueued) } @@ -61,7 +74,13 @@ object Publisher { } yield (Publisher[F](topic, 10)) } +/** + * A subscriber is essentially a pipe of the [[Publisher]] stream to `Unit`. + */ trait Subscriber[F[_]] extends Pipe[F, Either[Throwable, Event], Unit] { + /** + * Method to be called when the stream is initialized. + */ def init(): F[Unit] } diff --git a/proter/src/main/scala/com/workflowfm/proter/events/StringHandler.scala b/proter/src/main/scala/com/workflowfm/proter/events/StringHandler.scala index 7113ae5..320e67a 100644 --- a/proter/src/main/scala/com/workflowfm/proter/events/StringHandler.scala +++ b/proter/src/main/scala/com/workflowfm/proter/events/StringHandler.scala @@ -10,6 +10,9 @@ import cats.effect.implicits.* import fs2.{ Stream, Pipe } +/** + * A [[TimedHandler]] that converts timed events to a string representation. + */ trait StringHandler[F[_] : Applicative : Clock] extends TimedHandler[F] { def strPipe(newlines: Boolean): Pipe[F, Either[Throwable, Event], String] = @@ -19,7 +22,7 @@ trait StringHandler[F[_] : Applicative : Clock] extends TimedHandler[F] { */ val formatter = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss.SSS") - def timedEventToString(newlines: Boolean)(e: TimedEvent): String = { + protected def timedEventToString(newlines: Boolean)(e: TimedEvent): String = { val time = formatter.format(e.time) val str = s"[$time] ${Event.asString(e.event)}" if newlines then str + "\n" else str @@ -28,7 +31,7 @@ trait StringHandler[F[_] : Applicative : Clock] extends TimedHandler[F] { } /** - * An [[EventHandler]] that prints events to standard error. + * An [[Event]] handler that prints events to standard output. */ class PrintEvents[F[_] : Clock : Sync] extends Subscriber[F] with StringHandler[F] { diff --git a/proter/src/main/scala/com/workflowfm/proter/events/TimedHandler.scala b/proter/src/main/scala/com/workflowfm/proter/events/TimedHandler.scala index fb60020..91ee4eb 100644 --- a/proter/src/main/scala/com/workflowfm/proter/events/TimedHandler.scala +++ b/proter/src/main/scala/com/workflowfm/proter/events/TimedHandler.scala @@ -10,8 +10,16 @@ import fs2.{ Pipe, Stream } final case class TimedEvent(time: Long, event: Event) +/** + * An [[Event]] handler that attaches the system time to all events and exceptions. + * + * Exceptions are wrapped in [[EError]]. + */ trait TimedHandler[F[_] : Applicative : Clock] { + /** + * A pipe to process the [[Publisher]] stream and produce [[TimedEvent]]s. + */ val timedEventPipe: Pipe[F, Either[Throwable, Event], TimedEvent] = s => s.evalMap(evt => evt match { @@ -20,11 +28,11 @@ trait TimedHandler[F[_] : Applicative : Clock] { } ).handleErrorWith(ex => Stream.eval(fail(ex))) - def event(e: Event): F[TimedEvent] = for { + private def event(e: Event): F[TimedEvent] = for { t <- Clock[F].realTime } yield TimedEvent(t.toMillis, e) - def fail(e: Throwable): F[TimedEvent] = for { + private def fail(e: Throwable): F[TimedEvent] = for { t <- Clock[F].realTime } yield TimedEvent(t.toMillis, EError("*FATAL ERROR*", Long.MaxValue, e.getLocalizedMessage)) diff --git a/proter/src/main/scala/com/workflowfm/proter/flows/Flow.scala b/proter/src/main/scala/com/workflowfm/proter/flows/Flow.scala index d44f8e1..cad74e7 100644 --- a/proter/src/main/scala/com/workflowfm/proter/flows/Flow.scala +++ b/proter/src/main/scala/com/workflowfm/proter/flows/Flow.scala @@ -13,58 +13,73 @@ import java.util.UUID import scala.util.Success +/** + * Represents a simple flow of tasks. + * + * Tasks can be connected either in sequence or in parallel. + */ sealed trait Flow { + /** + * Adds another flow in parallel. + */ def +(f: Flow): Flow = f match { case NoTask => this case _ => And(this, f) } + /** + * Adds another flow in sequence. + */ def >(f: Flow): Flow = f match { case NoTask => this case _ => Then(this, f) } - def *(i: Int): Flow = Flow.par(for _ <- 1 to i yield this.copy()) - - def copy(): Flow + /** + * Repeats this flow a given number of times in parallel. + */ + def *(i: Int): Flow = Flow.par(for _ <- 1 to i yield this) - /* TODO def simulation(name: String, manager: Manager): FlowSimulation = FlowSimulation(name, - * manager, this) - * - * def simGenerator(name: String): FlowSimulationGenerator = FlowSimulationGenerator(name, this) */ } +/** + * Trivial flow with no tasks. Does nothing. + */ case object NoTask extends Flow { - override def copy(): Flow = NoTask override def +(f: Flow): Flow = f override def >(f: Flow): Flow = f override def *(i: Int): Flow = this } +/** + * Trivial flow with a single task. + */ case class FlowTask(val task: Task) extends Flow { - override def copy(): FlowTask = FlowTask(task.withID(UUID.randomUUID)) + override def toString(): String = task.name } given Conversion[Task, FlowTask] with def apply(t: Task): FlowTask = FlowTask(t) +/** + * Two flows in sequence. + */ case class Then(val left: Flow, val right: Flow) extends Flow { - override def copy(): Flow = Then(left.copy(), right.copy()) + override def toString(): String = "(" + left.toString + " > " + right.toString + ")" override def >(f: Flow): Then = Then(left, right > f) // make > right associative } case class And(val left: Flow, val right: Flow) extends Flow { - override def copy(): Flow = And(left.copy(), right.copy()) + override def toString(): String = "(" + left.toString + " + " + right.toString + ")" } object Flow { -// import scala.language.implicitConversions def apply(t: Task*): Flow = Flow.seq(t.map(FlowTask(_))) @@ -98,21 +113,19 @@ object Flow { } /** - * A simulation of a [[Flow]]. + * A [[CaseRef]] for a [[Flow]]. * * It uses a [[Flow]] structure which describes how and in what order certain tasks should be * executed. A Flow may consist of a single [[FlowTask]] or some combination of [[FlowTask]]s which - * are joined using [[And]]s, [[Then]]s, and [[Or]]s. + * are joined using [[And]]s and [[Then]]s. * - * @param name + * @param caseName * The name of the simulation being managed. - * @param manager - * The simulation manager for this simualation. * @param flow - * The flow which describes how the simulation behaves - * @param executionContext + * The flow which describes how the case should behave. + * @param callbackMap + * The map of callbacks for an extended [[AsyncCaseRef]] implementation. */ - case class FlowCaseRef[F[_] : Monad : UUIDGen : Random]( override val caseName: String, flow: Flow, @@ -128,14 +141,14 @@ case class FlowCaseRef[F[_] : Monad : UUIDGen : Random]( uuid <- UUIDGen[F].randomUUID cback = callback((_, _) => succeedState(())) updated = copy(callbackMap = callbackMap + (uuid -> cback)) - result <- updated.compose(execute(uuid, flow)) + result <- updated.applyState(execute(uuid, flow)) } yield (result) /** - * Completes an id by executing its callback and then removing it from the map + * Completes an id by executing its callback and then removing it from the map. * - * This overloads the definition of `complete` found in [[Simulation]] to allow for any id to be - * used in the `tasks` map, and not just [[Task]] objects. + * This overloads the definition of `complete` found in [[AsynCaseRef]] to allow for ''any''' id + * to be used in the `tasks` map, and not just [[TaskInstance]]s. * * @param id * The id to complete @@ -151,11 +164,13 @@ case class FlowCaseRef[F[_] : Monad : UUIDGen : Random]( }) /** - * Executes a flow by translating from a flow object to its sub-parts and appropriate callbacks, - * then calling `runFlow`. + * Executes a flow by recusively executing sub-parts with custom `UUID`s and appropriate + * callbacks. * + * @param id + * The `UUID` for the final callback of the entire flow. * @param flow - * The flow to be executed + * The flow to be executed. */ final def execute(id: UUID, flow: Flow): StateT[F, CallbackMap[F], SimState[F]] = { flow match { diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/CaseMetrics.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/CaseMetrics.scala index 11dd7aa..d161c3a 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/CaseMetrics.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/CaseMetrics.scala @@ -2,24 +2,24 @@ package com.workflowfm.proter package metrics /** - * Metrics for a simulation that has already started. + * Metrics for a case instance. * * @param name - * the unique name of the simulation + * The unique name of the instance. * @param started - * the virtual timestamp when the simulation started executing + * The virtual timestamp when the case instance started. * @param duration - * the virtual duration of the simulation + * The duration of the case instance. * @param delay - * the sum of all delays for all involved [[TaskInstance]]s + * The total [[TaskInstance]] delays in the case instance. * @param tasks - * the number of [[TaskInstance]]s associated with the simulation so far + * The number of started [[TaskInstance]]s associated with the case instance. * @param cost - * the total cost associated with the simulation so far + * The total cost associated with the case instance. * @param result - * a `String` representation of the returned result from the simulation, or [[scala.None]] if it - * still running. In case of failure, the field is populated with the localized message of the - * exception thrown + * A `String` representation of the returned result from the case, or [[scala.None]] if it still + * running. In case of failure, the field is populated with the localized message of the + * exception thrown. */ final case class CaseMetrics( name: String, @@ -35,7 +35,7 @@ final case class CaseMetrics( /** Adds some cost to the total cost. */ def addCost(c: Double): CaseMetrics = copy(cost = cost + c) - /** Adds some delay to the total delay. */ + /** Adds a starting task with some given delay and cost. */ def task(tdelay: Long, tcost: Double): CaseMetrics = copy( tasks = tasks + 1, delay = delay + tdelay, @@ -43,11 +43,12 @@ final case class CaseMetrics( ) /** - * Updates the metrics given that the simulation has completed with a certain result. + * Updates the metrics given that the case has completed with a certain result. + * * @param res - * the result of the simulation or localized message of the exception in case of failure + * The result of the case or localized message of the exception in case of failure. * @param time - * the virtual timestamp when the simulation finished + * The virtual timestamp when the case finished. */ def done(res: String, time: Long): CaseMetrics = copy(result = Some(res), duration = duration + time - started) @@ -55,7 +56,7 @@ final case class CaseMetrics( object CaseMetrics { - /** Initialize metrics for a named simulation starting at the given virtual time. */ + /** Initialize metrics for a named case starting at the given virtual time. */ def apply(name: String, t: Long): CaseMetrics = CaseMetrics(name, t, 0L, 0L, 0, 0L, None) } diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala index 9a1c112..58cc43d 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala @@ -7,7 +7,7 @@ import scala.collection.immutable.{ Map, Queue } import events.* /** - * Collects/aggregates metrics across multiple tasks, resources, and simulations. + * Collects/aggregates metrics across multiple tasks, resources, and cases. * * @groupprio Values * 1 @@ -19,10 +19,27 @@ import events.* * 4 * @groupprio Get * 5 + * + * @param start + * The system time in milliseconds when the simulation started. + * @param end + * The system time in milliseconds when the simulation ended. + * @param startTicks + * The timestamp when the simulation started. + * @param endTicks + * The timestamp when the simulation ended. + * @param tasks + * A map of all tracked [[TaskMetrics]]. + * @param cases + * A map of all tracked [[CaseMetrics]]. + * @param resources + * A map of all tracked [[ResourceMetrics]]. + * @param errors + * A queue of all errors caught. */ final case class Metrics( - sStart: Option[Long], - sEnd: Option[Long], + start: Option[Long], + end: Option[Long], startTicks: Long, endTicks: Long, tasks: Map[UUID, TaskMetrics], @@ -35,12 +52,13 @@ final case class Metrics( /** * Marks the start of metrics measurement with the current system time. + * * @group Start/End */ - def started(t: Long): Metrics = sStart match { + def started(t: Long): Metrics = start match { case None => copy( - sStart = Some(System.currentTimeMillis()), + start = Some(System.currentTimeMillis()), startTicks = t ) case _ => this @@ -48,51 +66,67 @@ final case class Metrics( /** * Marks the end of metrics measurement with the current system time. + * * @group Start/End */ def ended(t: Long): Metrics = copy( - sEnd = Some(System.currentTimeMillis()), + end = Some(System.currentTimeMillis()), endTicks = t ) /** - * Adds a new [[TaskMetrics]] instance, taking care of indexing automatically Overwrites a - * previous instance with the same IDs + * Adds a new [[TaskMetrics]] instance. + * + * Overwrites any previous instance with the same ID. + * * @group Set */ def +=(m: TaskMetrics): Metrics = copy(tasks = tasks + (m.id -> m)) + /** - * Adds a new [[CaseMetrics]] instance, taking care of indexing automatically Overwrites a - * previous instance with the same IDs + * Adds a new [[CaseMetrics]] instance. + * + * Overwrites any previous instance with the same name. + * * @group Set */ def +=(m: CaseMetrics): Metrics = copy(cases = cases + (m.name -> m)) + /** - * Adds a new [[ResourceMetrics]] instance, taking care of indexing automatically Overwrites a - * previous instance with the same IDs + * Adds a new [[ResourceMetrics]] instance. + * + * Overwrites any previous instance with the same name. + * * @group Set */ def +=(m: ResourceMetrics): Metrics = copy(resources = resources + (m.name -> m)) /** - * Initializes and adds a new [[TaskMetrics]] instance given a new [[TaskInstance]]. + * Adds a new [[TaskMetrics]] instance given a new [[TaskInstance]]. + * * @group Set */ def addTask(task: TaskInstance): Metrics = this += TaskMetrics(task) /** - * Initializes and adds a new [[SimulationMetrics]] instance given the name of the simulation - * starting now and the current virtual time. + * Adds a new [[CaseMetrics]] instance given a named case starting now and current time. + * * @group Set */ def addCase(s: String, t: Long): Metrics = this += CaseMetrics(s, t) /** - * Initializes and adds a new [[ResourceMetrics]] instance given a new [[TaskResource]]. + * Adds a new [[ResourceMetrics]] instance given a new [[Resource]]. + * * @group Set */ def addResource(t: Long, r: Resource): Metrics = this += ResourceMetrics(t, r) + /** + * Adds a new [[MetricsException]]. + * + * @group Set + */ def exception(e: MetricsException): Metrics = copy(errors = errors :+ e) @@ -101,15 +135,13 @@ final case class Metrics( * Updates a [[TaskMetrics]] instance. * * @return - * the updated [[TaskMetrics]] or [[scala.None]] if the identified instance does not exist - * + * The [[Metrics]] updated either with the new [[TaskMetrics]] or an error if the instance does + * not exist. * @param taskID - * the task ID for the involved [[TaskInstance]] + * The task ID for the involved [[TaskInstance]]. * @param u - * a function to update the [[TaskMetrics]] instance + * A function to update the [[TaskMetrics]]. * - * @see - * [[com.workflowfm.pew.metrics.MetricsAggregator]] for examples in a similar context * @group Update */ def updateTask(taskID: UUID)(u: TaskMetrics => TaskMetrics): Metrics = @@ -122,38 +154,28 @@ final case class Metrics( * Updates a [[TaskMetrics]] instance. * * @return - * the updated [[TaskMetrics]] or [[scala.None]] if the identified instance does not exist - * + * The [[Metrics]] updated either with the new [[TaskMetrics]] or an error if the instance does + * not exist. * @param task - * the involved [[TaskInstance]] + * The involved [[TaskInstance]]. * @param u - * a function to update the [[TaskMetrics]] instance - * - * @see - * [[com.workflowfm.pew.metrics.MetricsAggregator]] for examples in a similar context + * A function to update the [[TaskMetrics]]. * * @group Update */ def updateTask(task: TaskInstance)(u: TaskMetrics => TaskMetrics): Metrics = - tasks - .get(task.id) - .map { m => this += u(m) } - .getOrElse(exception(TaskNotFound(task.id))) + updateTask(task.id)(u) /** - * Updates a [[SimulationMetrics]] instance. + * Updates a [[CaseMetrics]] instance. * * @return - * the updated [[SimulationMetrics]] or [[scala.None]] if the identified instance does not - * exist - * - * @param simulation - * the name of the involved simulation + * The [[Metrics]] updated either with the new [[CaseMetrics]] or an error if the instance does + * not exist. + * @param caseName + * The name of the involved case. * @param u - * a function to update the [[SimulationMetrics]] instance - * - * @see - * [[com.workflowfm.pew.metrics.MetricsAggregator]] for examples in a similar context + * A function to update the [[CaseMetrics]]. * * @group Update */ @@ -169,15 +191,12 @@ final case class Metrics( * Updates a [[ResourceMetrics]] instance. * * @return - * the updated [[ResourceMetrics]] or [[scala.None]] if the identified instance does not exist - * + * The [[Metrics]] updated either with the new [[ResourceMetrics]] or an error if the instance + * does not exist. * @param resource - * the involved [[TaskResource]] + * The name of the involved resource. * @param u - * a function to update the [[ResourceMetrics]] instance - * - * @see - * [[com.workflowfm.pew.metrics.MetricsAggregator]] for examples in a similar context + * A function to update the [[ResourceMetrics]]. * * @group Update */ @@ -191,10 +210,9 @@ final case class Metrics( * Updates all [[ResourceMetrics]] instances. * * @return - * the updated [[resourceMap]] - * + * The updated [[Metrics]]. * @param u - * a function to update the [[ResourceMetrics]] instances + * A function to update each of the [[ResourceMetrics]]. * * @group Update */ @@ -208,31 +226,42 @@ final case class Metrics( /** * Returns all the tracked instances of [[TaskMetrics]] sorted by starting time. + * * @group Get */ def taskMetrics: Seq[TaskMetrics] = tasks.values.toSeq.sortBy(_.started) + /** - * Returns all the tracked instances of [[SimulationMetrics]] sorted by simulation name. + * Returns all the tracked instances of [[CaseMetrics]] sorted by name. + * * @group Get */ def caseMetrics: Seq[CaseMetrics] = cases.values.toSeq.sortBy(_.name) + /** - * Returns all the tracked instances of [[ResourceMetrics]] sorted by resource time. + * Returns all the tracked instances of [[ResourceMetrics]] sorted by name. + * * @group Get */ def resourceMetrics: Seq[ResourceMetrics] = resources.values.toSeq.sortBy(_.name) + /** - * Returns a [[scala.collection.immutable.Set]] of all task names being tracked. This is useful - * when using task names as a category, for example to colour code tasks in the timeline. + * Returns a `Set` of all task names being tracked. + * + * This is useful when using task names as a category, for example to colour code tasks in the + * timeline. + * * @group Get */ def taskSet: Set[String] = tasks.values.map(_.task).toSet[String] /** - * Returns all the tracked instances of [[TaskMetrics]] associated with a particular - * [[TaskResource]], sorted by starting time. + * All the tracked [[TaskMetrics]] instances associated with a [[TaskResource]], sorted by + * starting time. + * * @param r - * the tracked [[ResourceMetrics]] of the resource + * The tracked [[ResourceMetrics]] of the resource. + * * @group Get */ // TODO: we used to have 2 levels of sorting! @@ -249,6 +278,9 @@ final case class Metrics( def taskMetricsOf(s: CaseMetrics): Seq[TaskMetrics] = tasks.values.toSeq.filter(_.caseName.equals(s.name)).sortBy(_.started) + /** + * Convert [[Event]]s to metrics updates. + */ def handle(evt: Event): Metrics = evt match { case EStart(_, t) => this.started(t).updateAllResources(_.start(t)) case EDone(_, t) => updateAllResources(_.idle(t)).ended(t) @@ -262,10 +294,10 @@ final case class Metrics( .updateCase(task.caseName)(_.task(t - task.created, task.cost)) case ETaskAttach(_, t, task, r) => updateResource(r.resource.name)(_.task(t, task.resourceQuantity(r.resource.name))) - case ETaskDetach(_, t, start, task, r) => { + case ETaskDetach(_, t, tstart, task, r) => { val q = task.resourceQuantity(r.resource.name) - val cost = r.resource.costOf(t - start, q) - updateResource(r.resource.name)(_.endTask(t, start, cost, q)) + val cost = r.resource.costOf(t - tstart, q) + updateResource(r.resource.name)(_.endTask(t, tstart, cost, q)) .updateTask(task)(_.addCost(cost)) .updateCase(task.caseName)(_.addCost(cost)) } @@ -294,12 +326,13 @@ object Metrics { extends MetricsException(s"Tried to update metrics for task that does not exist: $name") import io.circe.generic.semiauto._ + import io.circe.Encoder - given io.circe.Encoder[TaskMetrics] = deriveEncoder[TaskMetrics] - given io.circe.Encoder[CaseMetrics] = deriveEncoder[CaseMetrics] - given io.circe.Encoder[ResourceMetrics] = deriveEncoder[ResourceMetrics] - given io.circe.Encoder[MetricsException] = deriveEncoder[MetricsException] + given Encoder[TaskMetrics] = deriveEncoder[TaskMetrics] + given Encoder[CaseMetrics] = deriveEncoder[CaseMetrics] + given Encoder[ResourceMetrics] = deriveEncoder[ResourceMetrics] + given Encoder[MetricsException] = deriveEncoder[MetricsException] - given io.circe.Encoder[Metrics] = deriveEncoder[Metrics] + given Encoder[Metrics] = deriveEncoder[Metrics] } diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsOutput.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsOutput.scala index 128ec8f..8cf0dd8 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsOutput.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsOutput.scala @@ -13,10 +13,7 @@ import org.apache.commons.lang3.time.DurationFormatUtils /** * Helper to write stuff to a file. - * @todo - * Move somewhere else as a utility? */ - trait FileOutput[F[_] : Sync] { import java.io.* @@ -32,13 +29,13 @@ trait FileOutput[F[_] : Sync] { } /** - * Manipulates a [[SimMetricsAggregator]] to produce some output via side-effects. - * - * As a function, takes 2 arguments: - * - a [[scala.Long]] representing the total virtual time elapsed - * - the [[SimMetricsAggregator]] to act upon + * Manipulates [[Metrics]] to produce some output via side-effects. */ trait MetricsOutput[F[_]] extends (Metrics => F[Unit]) { + + /** + * Evaluates the output side-effect within a [[Metrics]] stream. + */ def pipe: Pipe[F, Metrics, Unit] = _.evalMap(this) } @@ -80,6 +77,9 @@ object MetricsOutput { } } +/** + * Outputs the [[Metrics]] programmatically as a deferred result. + */ case class MetricsResult[F[_] : Concurrent](result: Deferred[F, Metrics]) extends MetricsOutput[F] { override def apply(metrics: Metrics): F[Unit] = { @@ -95,7 +95,7 @@ trait MetricsStringOutput[F[_]] extends MetricsOutput[F] { /** * The field names for [[TaskMetrics]]. * @param separator - * a string (such as a space or comma) to separate the names + * A string (such as a space or comma) to separate the names */ def taskHeader(separator: String): String = Seq( @@ -117,9 +117,9 @@ trait MetricsStringOutput[F[_]] extends MetricsOutput[F] { * String representation of a [[TaskMetrics]] instance. * * @param separator - * a string (such as a space or comma) to separate the values + * A string (such as a space or comma) to separate the values * @param resSeparator - * a string (such as a space or comma) to separate the list of names of [[TaskResource]]s in + * A string (such as a space or comma) to separate the list of names of [[TaskResource]]s in * [[TaskMetrics]] * @param m * the [[TaskMetrics]] instance to be handled @@ -142,9 +142,10 @@ trait MetricsStringOutput[F[_]] extends MetricsOutput[F] { } /** - * The field names for [[SimulationMetrics]]. + * The field names for [[CaseMetrics]]. + * * @param separator - * a string (such as a space or comma) to separate the names + * A string (such as a space or comma) to separate the names */ def caseHeader(separator: String): String = Seq("Name", "Start", "Duration", "Delay", "Tasks", "Cost", "Result").mkString(separator) @@ -153,7 +154,7 @@ trait MetricsStringOutput[F[_]] extends MetricsOutput[F] { * String representation of a [[SimulationMetrics]] instance. * * @param separator - * a string (such as a space or comma) to separate the values + * A string (such as a space or comma) to separate the values * @param m * the [[SimulationMetrics]] instance to be handled */ @@ -164,8 +165,9 @@ trait MetricsStringOutput[F[_]] extends MetricsOutput[F] { /** * The field names for [[ResourceMetrics]]. + * * @param separator - * a string (such as a space or comma) to separate the names + * A string (such as a space or comma) to separate the names. */ def resHeader(separator: String): String = Seq("Name", "Busy", "Idle", "Tasks", "Cost").mkString(separator) @@ -174,9 +176,9 @@ trait MetricsStringOutput[F[_]] extends MetricsOutput[F] { * String representation of a [[ResourceMetrics]] instance. * * @param separator - * a string (such as a space or comma) to separate the values + * A string (such as a space or comma) to separate the values. * @param m - * the [[ResourceMetrics]] instance to be handled + * The [[ResourceMetrics]] instance to be handled. */ def resCSV(separator: String)(m: ResourceMetrics): String = m match { case ResourceMetrics(name, _, _, _, _, b, i, ts, c) => @@ -184,17 +186,17 @@ trait MetricsStringOutput[F[_]] extends MetricsOutput[F] { } /** - * Formats all [[TaskMetrics]] in a [[SimMetricsAggregator]] in a single string. + * Formats all [[TaskMetrics]] in a single string. * - * @param aggregator - * the [[SimMetricsAggregator]] to retrieve the metrics to be formatted + * @param metrics + * The [[Metrics]] object from which to retrieve the case metrics. * @param separator - * a string (such as a space or comma) to separate values + * A string (such as a space or comma) to separate values. * @param lineSep - * a string (such as a new line) to separate tasks + * A string (such as a new line) to separate tasks. * @param resSeparator - * a string (such as a space or comma) to separate the list of names of [[TaskResource]]s in - * [[TaskMetrics]] + * A string (such as a space or comma) to separate the list of names of [[Resource]]s in + * [[TaskMetrics]]. */ def tasks( metrics: Metrics, @@ -205,14 +207,14 @@ trait MetricsStringOutput[F[_]] extends MetricsOutput[F] { metrics.taskMetrics.map(taskCSV(separator, resSeparator)).mkString(lineSep) /** - * Formats all [[SimulationMetrics]] in a [[SimMetricsAggregator]] in a single string. + * Formats all [[CaseMetrics]] in a single string. * - * @param aggregator - * the [[SimMetricsAggregator]] to retrieve the metrics to be formatted + * @param metrics + * The [[Metrics]] object from which to retrieve the case metrics. * @param separator - * a string (such as a space or comma) to separate values + * A string (such as a space or comma) to separate values. * @param lineSep - * a string (such as a new line) to separate simulations + * A string (such as a new line) to separate simulations. */ def cases( metrics: Metrics, @@ -222,14 +224,14 @@ trait MetricsStringOutput[F[_]] extends MetricsOutput[F] { metrics.caseMetrics.map(caseCSV(separator)).mkString(lineSep) /** - * Formats all [[ResourceMetrics]] in a [[SimMetricsAggregator]] in a single string. + * Formats all [[ResourceMetrics]] in a single string. * - * @param aggregator - * the [[SimMetricsAggregator]] to retrieve the metrics to be formatted + * @param metrics + * The [[Metrics]] object from which to retrieve the case metrics. * @param separator - * a string (such as a space or comma) to separate values + * A string (such as a space or comma) to separate values. * @param lineSep - * a string (such as a new line) to separate resources + * A string (such as a new line) to separate resources. */ def resources( metrics: Metrics, @@ -274,18 +276,20 @@ ${resHeader(sep)} ${resources(metrics, sep, lineSep)} --------- -Started: ${MetricsOutput.formatTimeOption(metrics.sStart, timeFormat, nullTime)} -Ended: ${MetricsOutput.formatTimeOption(metrics.sEnd, timeFormat, nullTime)} -Duration: ${MetricsOutput.formatDuration(metrics.sStart, metrics.sEnd, durFormat, nullTime)} +Started: ${MetricsOutput.formatTimeOption(metrics.start, timeFormat, nullTime)} +Ended: ${MetricsOutput.formatTimeOption(metrics.end, timeFormat, nullTime)} +Duration: ${MetricsOutput.formatDuration(metrics.start, metrics.end, durFormat, nullTime)} """ ) } } /** - * Outputs simulation metrics to files using a standard CSV format. Generates 3 CSV files, + * Outputs simulation metrics to files using a standard CSV format. + * + * Generates 3 CSV files: * 1. One for tasks with a "-tasks.csv" suffix, - * 1. One for simulations with a "-simulations.csv" suffix. + * 1. One for casess with a "-cases.csv" suffix. * 1. One for resources with a "-resources.csv" suffix. * * @param path @@ -302,7 +306,7 @@ class CSVFile[F[_] : Sync](path: String, name: String) override def apply(metrics: Metrics): F[Unit] = { val taskFile = s"$path$name-tasks.csv" - val caseFile = s"$path$name-simulations.csv" + val caseFile = s"$path$name-cases.csv" val resourceFile = s"$path$name-resources.csv" val t = writeToFile(taskFile, taskHeader(separator) + "\n" + tasks(metrics, separator, lineSep)) @@ -319,8 +323,9 @@ class CSVFile[F[_] : Sync](path: String, name: String) } /** - * Outputs simulation metrics to a file using the d3-timeline format. Generates 1 file with a - * "-simdata.js" suffix. This can then be combined with the resources at + * Outputs simulation metrics to a file using the d3-timeline format. + * + * Generates 1 file with a "-simdata.js" suffix. This can then be combined with the resources at * [[https://github.com/PetrosPapapa/WorkflowFM-PEW/tree/master/resources/d3-timeline]] to render * the timeline in a browser. * @@ -330,11 +335,11 @@ class CSVFile[F[_] : Sync](path: String, name: String) * to provide a `tick` value of 60000. * * @param path - * path to directory where the files will be placed + * Path to directory where the files will be placed. * @param file - * file name prefix + * File name (with no suffix - `.js` will be added). * @param tick - * the size of 1 unit of virtual time + * The size of 1 unit of virtual time. */ class D3Timeline[F[_] : Sync](path: String, file: String, tick: Int = 1) extends MetricsOutput[F] @@ -343,11 +348,10 @@ class D3Timeline[F[_] : Sync](path: String, file: String, tick: Int = 1) override def apply(metrics: Metrics): F[Unit] = { val result = build(metrics, System.currentTimeMillis()) // println(result) - val dataFile = s"$path$file-simdata.js" + val dataFile = s"$path$file.js" writeToFile(dataFile, result) } - /** Helps build the output with a static system time. */ def build(metrics: Metrics, now: Long): String = { val buf: StringBuilder = new StringBuilder() buf.append("var tasks = [\n") @@ -358,12 +362,12 @@ class D3Timeline[F[_] : Sync](path: String, file: String, tick: Int = 1) for m <- metrics.resourceMetrics do buf.append(s"""${resourceEntry(m, metrics)}\n""") buf.append("];\n\n") buf.append("var simulationData = [\n") - for m <- metrics.caseMetrics do buf.append(s"""${simulationEntry(m, metrics)}\n""") + for m <- metrics.caseMetrics do buf.append(s"""${caseEntry(m, metrics)}\n""") buf.append("];\n") buf.toString } - def simulationEntry(s: CaseMetrics, agg: Metrics): String = { + def caseEntry(s: CaseMetrics, agg: Metrics): String = { val times = agg.taskMetricsOf(s).flatMap(taskEntry).mkString(",\n") s"""{label: "${s.name}", times: [ $times diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsSubscriber.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsSubscriber.scala index 8bcf9b7..ced7f39 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsSubscriber.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsSubscriber.scala @@ -7,6 +7,14 @@ import cats.effect.Concurrent import fs2.Stream import events.{ Event, Subscriber } +/** + * A [[Subscriber]] that compiles and outputs [[Metrics]]. + * + * Runs all outputs concurrently. + * + * @param outputs + * The [[MetricsOutput]]s to run at the end of the stream. + */ final case class MetricsParSubscriber[F[_] : Concurrent](outputs: MetricsOutput[F]*) extends Subscriber[F] { override def init(): F[Unit] = Concurrent[F].pure(()) @@ -20,6 +28,14 @@ final case class MetricsParSubscriber[F[_] : Concurrent](outputs: MetricsOutput[ ).broadcastThrough(outputs.map(_.pipe): _*) } +/** + * A [[Subscriber]] that compiles and outputs [[Metrics]]. + * + * Runs all outputs in sequence. + * + * @param outputs + * The [[MetricsOutput]]s to run at the end of the stream. + */ final case class MetricsSubscriber[F[_] : Applicative](outputs: MetricsOutput[F]*) extends Subscriber[F] { override def init(): F[Unit] = Applicative[F].pure(()) diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/ResourceMetrics.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/ResourceMetrics.scala index 8bff21b..c82277b 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/ResourceMetrics.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/ResourceMetrics.scala @@ -4,20 +4,29 @@ package metrics import com.workflowfm.proter.* /** - * Metrics for at [[TaskResource]]. + * Metrics for at [[Resource]]. + * + * @note + * Busy and idle times are measured for each unit of capacity. * * @param name - * the unique name of the [[TaskResource]] + * The unique name of the [[Resource]]. + * @param capacity + * The total capacity of the [[Resource]]. + * @param costPerTick + * The cost of using the [[Resource]] per unit of time. + * @param idleUpdate + * The last timestamp when busy/idle times were calculated. + * @param load + * The resource load since `idleUpdate`. * @param busyTime - * the total amount of virtual time that the [[TaskResource]] has been busy, i.e. attached to a - * [[TaskInstance]] + * The total amount of virtual time that the [[Resource]] has been busy. * @param idleTime - * the total amount of virtual time that the [[TaskResource]] has been idle, i.e. not attached to - * any [[TaskInstance]] + * The total amount of virtual time that the [[Resource]] has been idle. * @param tasks - * the number of different [[TaskInstance]]s that have been attached to this [[TaskResource]] + * The number of different [[TaskInstance]]s that have been attached to this [[Resource]]. * @param cost - * the total cost associated with this [[TaskResource]] + * The total cost associated with the use of this [[Resource]]. */ final case class ResourceMetrics( name: String, @@ -42,13 +51,13 @@ final case class ResourceMetrics( ) else this - /** Updates the metrics given a new [[TaskInstance]] has been attached to the [[TaskResource]]. */ + /** Updates the metrics given a new [[TaskInstance]] has been attached to the [[Resource]]. */ def task(t: Long, q: Int): ResourceMetrics = idle(t).copy( tasks = tasks + 1, load = load + q ) - /** Updates the metrics given a new [[TaskInstance]] has been attached to the [[TaskResource]]. */ + /** Updates the metrics given a [[TaskInstance]] has been detached from the [[Resource]]. */ def endTask(t: Long, start: Long, tcost: Double, q: Int): ResourceMetrics = idle(t).copy( cost = cost + tcost, load = load - q, @@ -58,7 +67,7 @@ final case class ResourceMetrics( object ResourceMetrics { - /** Initialize metrics given the name of a [[TaskResource]]. */ + /** Initialize metrics given the name of a [[Resource]]. */ def apply(t: Long, r: Resource): ResourceMetrics = ResourceMetrics(r.name, r.capacity, r.costPerTick, t, 0, 0L, 0L, 0, 0d) } diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/TaskMetrics.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/TaskMetrics.scala index d666f82..e4adfda 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/TaskMetrics.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/TaskMetrics.scala @@ -4,27 +4,29 @@ package metrics import java.util.UUID /** - * Metrics for a simulated [[TaskInstance]] that consumed virtual time. + * Metrics for a simulated [[TaskInstance]]. * * @param id - * the unique ID of the [[TaskInstance]] + * The unique `UUID` of the [[TaskInstance]]. * @param task - * the name of the [[TaskInstance]] - * @param simulation - * the name of the simulation the [[TaskInstance]] belongs to + * The name of the [[TaskInstance]]. + * @param caseName + * The name of the case the [[TaskInstance]] belongs to. * @param priority - * the priority of the [[TaskInstance]] + * The priority of the [[TaskInstance]]. * @param created - * the virtual timestamp when the [[TaskInstance]] was created and entered the [[Coordinator]] + * The virtual timestamp when the [[TaskInstance]] was created/added. * @param started - * the virtual timestamp when the [[TaskInstance]] started executing, or [[scala.None]] if it has - * not started yet + * The virtual timestamp when the [[TaskInstance]] started, or [[scala.None]] if it has not + * started yet. * @param duration - * the virtual duration of the [[TaskInstance]] + * The virtual duration of the [[TaskInstance]]. * @param cost - * the cost associated with the [[TaskInstance]] + * The cost associated with the [[TaskInstance]]. * @param resources - * the list of names of the [[TaskResource]]s this [[TaskInstance]] used + * The map of names and respective capacities of the [[Resource]]s this [[TaskInstance]] used. + * @param aborted + * Whether this task was aborted during simulation. */ final case class TaskMetrics( id: UUID, diff --git a/proter/src/main/scala/com/workflowfm/proter/schedule/Schedule.scala b/proter/src/main/scala/com/workflowfm/proter/schedule/Schedule.scala index fbf3ab1..a30e74f 100644 --- a/proter/src/main/scala/com/workflowfm/proter/schedule/Schedule.scala +++ b/proter/src/main/scala/com/workflowfm/proter/schedule/Schedule.scala @@ -170,21 +170,6 @@ object Schedule { */ def apply(): Schedule = Schedule(List.empty[(Long, Long)]) - /** - * Creates a [[Schedule]] from a [[ResourceState]] based on its currently running - * [[TaskInstance]] (if any). - * - * @param r - * The [[ResourceState]] to schedule for. - * @return - * The initialised schedule. - */ - /* TODO this shouldn't be needed any more <<<<<<< HEAD def apply(r: TaskResource): Schedule = - * r.currentTasks.values.foldLeft(Schedule()){ (s, task) => s +> (task._1, - * task._2.estimatedDuration)} - * ======= - * def apply(r: ResourceState): Schedule = r.currentTask match { case None => Schedule() case - * Some((s, t)) => Schedule((s, s + t.estimatedDuration) :: Nil) } >>>>>>> fp-capacity */ /** * Adds an interval to a list of intervals. * diff --git a/proter/src/main/scala/com/workflowfm/proter/schedule/Scheduler.scala b/proter/src/main/scala/com/workflowfm/proter/schedule/Scheduler.scala index cb4de85..9962c8c 100644 --- a/proter/src/main/scala/com/workflowfm/proter/schedule/Scheduler.scala +++ b/proter/src/main/scala/com/workflowfm/proter/schedule/Scheduler.scala @@ -37,6 +37,9 @@ trait Scheduler { * * This means a lower priority task may start now and block a higher priority task which is * currently blocked, but could have started soon. + * + * @param strict + * If `true` then idle resources are prevented from starting lower priority tasks. */ case class GreedyScheduler(strict: Boolean) extends Scheduler { @@ -67,7 +70,7 @@ case class GreedyScheduler(strict: Boolean) extends Scheduler { /** * The default priority based [[Scheduler]]. * - * Relies on the use of [[Schedule]]s for each [[TaskResource]]. + * Relies on the use of [[Schedule]]s for each [[Resource]]. * * Avoids scheduling lower priority tasks that might cause delays/waiting times to higher priority * ones. @@ -89,7 +92,7 @@ case object ProterScheduler extends Scheduler { * @param currentTime * The current timestamp. * @param resourceMap - * The map of available [[TaskResource]]s. + * The current [[ResourceMap]]. * @return * The sequence of [[TaskInstance]]s to start now. */ @@ -112,21 +115,21 @@ case object ProterScheduler extends Scheduler { * [[Task]]s are assumed to be sorted by priority. * * Taking each [[TaskInstance]] from high to low priority, the algorithm does the following: - * 1. It merges the current [[Schedule]]s of all the [[TaskResource]]s involved in the + * 1. It merges the current [[Schedule]]s of all the [[Resource]]s involved in the * [[TaskInstance]]. * 1. It finds the earliest possible starting time of the [[TaskInstance]] in the merged * [[Schedule]]. * 1. Takes the interval defined by the starting time and the estimated duration of the - * [[TaskInstance]] and adds it to the [[Schedule]]s of all the involved [[TaskResource]]s. - * 1. If the starting time is equal to the current time, and all involved [[TaskResource]]s are + * [[TaskInstance]] and adds it to the [[Schedule]]s of all the involved [[Resource]]s. + * 1. If the starting time is equal to the current time, and all involved [[Resource]]s are * idle, it adds the [[TaskInstance]] to the result. * * @param currentTime * The current timestamp. * @param resourceMap - * The map of available [[TaskResource]]s. + * The current [[ResourceMap]]. * @param schedules - * The map of [[Schedule]]s for each [[TaskResource]]. + * The map of [[WeightedSchedule]]s for each [[Resource]]. * @param tasks * The set of [[TaskInstance]]s that need to start. * @param result diff --git a/proter/src/main/scala/com/workflowfm/proter/schedule/WeightedSchedule.scala b/proter/src/main/scala/com/workflowfm/proter/schedule/WeightedSchedule.scala index 4fde573..8b104e8 100644 --- a/proter/src/main/scala/com/workflowfm/proter/schedule/WeightedSchedule.scala +++ b/proter/src/main/scala/com/workflowfm/proter/schedule/WeightedSchedule.scala @@ -4,13 +4,14 @@ package schedule import scala.annotation.tailrec /** - * A list of time intervals indicating the amount of used capacity of a [[TaskResource]]. An empty - * time interval also indicates that no amount of capacity is being used in that interval. + * A list of time intervals indicating the amount of used capacity of a [[Resource]]. + * + * An empty time interval indicates that no amount of capacity is being used in that interval. * * Each interval is represented as a pair of timestamps and a number indicating the amount of * capacity used. * @example - * Schedule(List( (1L,2L, 2), (3L,4L, 2) )) // The corresponding [[TaskResource]] is scheduled to + * Schedule(List( (1L,2L, 2), (3L,4L, 2) )) // The corresponding [[Resource]] is scheduled to * have `1` capacity being used between `1L` and `2L` and `2` capacity used between `3L` and * `4L`, and idle (no capacity used) between `0L` and `1L`, between `2L` and `3L` and after `4L`. * @@ -38,6 +39,20 @@ case class WeightedSchedule(tasks: List[(Long, Long, Int)]) { this +> (startTime, startTime + t.estimatedDuration, usage) } + /** + * Converts to a unweighted [[Schedule]]. + * + * The resulting [[Schedule]] has intervals during which there is insufficient capacity in the + * [[Resource]]. This can be used to find when the given [[Resource]] has sufficient capacity for + * a particular task. + * + * @param targetCapacity + * The capacity required to consider the [[Resource]] available. + * @param resourceCapacity + * The total [[Resource]] capacity. + * @return + * The unweighted [[Schedule]]. + */ def binary(targetCapacity: Int, resourceCapacity: Int): Schedule = if targetCapacity > resourceCapacity then Schedule.Full else @@ -93,11 +108,15 @@ object WeightedSchedule { usage + u, if (end < r) u else usage ) - var timeline = result // TODO wtf? fix - if (times(0) != times(1)) timeline = timeline :+ (times(0), times(1), usages(0)) - timeline = timeline :+ (times(1), times(2), usages(1)) - if (times(2) != times(3)) add(times(2), times(3), usages(2), t, timeline) - else Some(timeline.toList) + + val timeline = + if (times(0) != times(1)) result :+ (times(0), times(1), usages(0)) + else result + + val finalTimeline = timeline :+ (times(1), times(2), usages(1)) + + if (times(2) != times(3)) add(times(2), times(3), usages(2), t, finalTimeline) + else Some(finalTimeline.toList) } } } diff --git a/proter/src/test/scala/com/workflowfm/proter/cases/Case.scala b/proter/src/test/scala/com/workflowfm/proter/cases/Case.scala index 59dda6a..455f70d 100644 --- a/proter/src/test/scala/com/workflowfm/proter/cases/Case.scala +++ b/proter/src/test/scala/com/workflowfm/proter/cases/Case.scala @@ -293,7 +293,7 @@ trait CaseTester extends AsyncWordSpec with AsyncIOSpec with Matchers with Insid override def updateState(callbackUpdate: CallbackMap[IO]): AsyncCaseRef[IO] = copy(callbackMap = callbackUpdate) - override def run(): IO[SimState[IO]] = compose(task(t1, t1callback)) + override def run(): IO[SimState[IO]] = applyState(task(t1, t1callback)) val t1callback: Callback = { case Success((t, _)) => { @@ -345,7 +345,7 @@ trait CaseTester extends AsyncWordSpec with AsyncIOSpec with Matchers with Insid override def updateState(callbackUpdate: CallbackMap[IO]): AsyncCaseRef[IO] = copy(callbackMap = callbackUpdate) - override def run(): IO[SimState[IO]] = compose(task(t1, t1callback)) + override def run(): IO[SimState[IO]] = applyState(task(t1, t1callback)) val t1callback: Callback = { case Success((t, _)) => task(t2, t2callback) From 5a3d5b965bcc8df8de8b541950a24592dcd421d1 Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Sat, 30 Jul 2022 00:42:44 +0100 Subject: [PATCH 02/31] Updates scaladoc of `Resource.scala` --- .../com/workflowfm/proter/Resource.scala | 153 ++++++++++++++---- 1 file changed, 121 insertions(+), 32 deletions(-) diff --git a/proter/src/main/scala/com/workflowfm/proter/Resource.scala b/proter/src/main/scala/com/workflowfm/proter/Resource.scala index 73e831c..859eeea 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Resource.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Resource.scala @@ -7,42 +7,57 @@ import collection.immutable.Queue import cats.implicits.* +/** + * A peristent resource that can be used for simulated tasks. + * + * @param name A unique name. + * @param capacity The resource capacity. + * @param costPerTick The cost of using 1 unit of resource capacity per unit of time. + */ case class Resource(name: String, capacity: Int, costPerTick: Double) { + /** + * Initial state. + */ def start: ResourceState = ResourceState(this, Map()) + /** + * Calculates the cost of using certain units of capacity over a given time. + * + * @param actualDuration The duration to calculate. + * @param quantity The units of capacity to use. + * @return The calculated total cost. + */ def costOf(actualDuration: Long, quantity: Int): Double = costPerTick * actualDuration * quantity } +/** + * The state of a [[Resource]] during simulation. + * + * Includes the [[TaskInstance]]s that are attached to the resource at a given time. + * + * @param resource The associated [[Resource]]. + * @param currentTasks A `Map` of attached [[TaskInstances]] paired with their starting times and indexed by their IDs. + */ case class ResourceState(resource: Resource, currentTasks: Map[UUID, (Long, TaskInstance)]) { - // TODO add explicit remaining capacity to avoid too many calcs /** - * True if the resource is idle, false otherwise. - * - * @return - * true if the resource is idle, false otherwise. + * The remaining available capacity of the resource. */ - def hasCapacity: Boolean = remainingCapacity > 0 - - def remainingCapacity: Int = + lazy val remainingCapacity: Int = resource.capacity - currentTasks.map { case (_, (_, ti)) => ti.resourceQuantity(resource.name) }.sum /** - * Attach a [[TaskInstance]] to this resource. - * - * If the resource is already attached to another [[TaskInstance]], the attached task is - * returned. Otherwise, we return the updated [[ResourceState]]. + * Attach a [[TaskInstance]] to this [[Resource]]. * * @param task * The [[TaskInstance]] to attach. * @param currentTime * The current (virtual) time. * @return - * Some [[TaskInstance]] that was already attached before or An updated [[ResourceState]] if - * the task was attached successfully. + * The updated state (`Right`) or a [[ResourceState.Full]] if there is not enough capacity. */ def startTask( // TODO double check we are not running it twice task: TaskInstance, @@ -52,6 +67,12 @@ case class ResourceState(resource: Resource, currentTasks: Map[UUID, (Long, Task else Right(this.copy(currentTasks = currentTasks + (task.id -> (currentTime, task)))) } + /** + * Detach a [[TaskInstance]] from the [[Resource]]. + * + * @param taskID The `UUID` of the task to detach. + * @return The [[DetachedTask]] or `None` if the ID was not found attached here. + */ def detach(taskID: UUID): Option[DetachedTask] = currentTasks.get(taskID).map { (start, task) => DetachedTask( @@ -61,9 +82,23 @@ case class ResourceState(resource: Resource, currentTasks: Map[UUID, (Long, Task ) } + /** + * Checks if any task IDs in a given list are attached to this resource. + * + * @param taskIDs The IDs of the tasks we are interested in. + * @return True if any of the task IDs are attached to this resource. + */ def runningAnyOf(taskIDs: Seq[UUID]): Boolean = taskIDs.exists(id => currentTasks.contains(id)) + /** + * Reduces the capacity of the resource based on a given map of named resource quantities. + * + * This is used when scheduling tasks which are not yet attached. + * + * @param A `Map` of resource names and quantities to reduce. + * @return The updated state. + */ def reduce(toReduce: Map[String, Int]): ResourceState = copy( resource = resource.copy( @@ -74,15 +109,24 @@ case class ResourceState(resource: Resource, currentTasks: Map[UUID, (Long, Task } object ResourceState { + /** + * Wrapper around a [[ResourceState]] that does not have enough capacity for some task. + * + * @param state The corresponding [[ResourceState]]. + */ case class Full(state: ResourceState) } +/** + * A map of all simulated [[Resource]]s. + * + * @param resources A `Map` of [[Resource]] names to their [[ResourceState]]. + */ case class ResourceMap(resources: Map[String, ResourceState]) { /** * Add a new [[Resource]] to our map of available resources. * - * @group resources * @param r * The [[Resource]] to be added. */ @@ -95,17 +139,20 @@ case class ResourceMap(resources: Map[String, ResourceState]) { /** * Add multiple [[Resource]]s in one go. * - * @group resources * @param resources * The sequence of [[Resource]]s to be added. */ def addResources(resourcesToAdd: Seq[Resource]): ResourceMap = copy(resources ++ (resourcesToAdd.map { r => r.name -> r.start })) - // def finishTask(task: TaskInstance): ResourceMap = { - // copy(resources = resources.map { (n, r) => n -> r.detach(task.id) }) - // } - + /** + * Attach a [[TaskInstance]] to all associated [[ReourceState]]s. + * + * @param task The [[TaskInstance]] to attach. + * @param time The current timestamp. + * @return The updated structure or a `Left` of a [[ResourceState.Full]] if any of the resources + * did not have enough capacity. + */ def startTask(task: TaskInstance, time: Long): Either[ResourceState.Full, ResourceMap] = (for { (name, _) <- task.resources @@ -114,6 +161,12 @@ case class ResourceMap(resources: Map[String, ResourceState]) { state.startTask(task, time).map { newState => name -> newState } )).toSeq.sequence.map { stateUpdates => copy(resources = resources ++ stateUpdates) } + /** + * Detach a [[TaskInstance]] from all associated [[ReourceState]]s. + * + * @param id The ID of the [[TaskInstance]] to detach. + * @return The updated structure paired with the resulting sequence of [[DetachedTask]]s. + */ def stopTask(id: UUID): (ResourceMap, Seq[DetachedTask]) = { val stopping = resources.values .flatMap(_.detach(id)) @@ -124,6 +177,12 @@ case class ResourceMap(resources: Map[String, ResourceState]) { ) } + /** + * Detach multiple [[TaskInstance]]s from all associated [[ReourceState]]s. + * + * @param ids The IDs of the [[TaskInstance]]s to detach. + * @return The updated structure paired with the resulting sequence of [[DetachedTask]]s. + */ def stopTasks(ids: Seq[UUID]): (ResourceMap, Seq[DetachedTask]) = { ids.foldLeft((this, Queue[DetachedTask]())) { case ((m, q), id) => { @@ -133,37 +192,60 @@ case class ResourceMap(resources: Map[String, ResourceState]) { } } - def hasCapacity(r: String): Boolean = resources.get(r) match { - case None => false - case Some(resourceState) => resourceState.hasCapacity - } - - def getAvailable(): ResourceMap = copy(resources = resources.filter(_._2.hasCapacity)) + /** + * Filters the structure to keep only resources with some available capacity. + */ + def getAvailable(): ResourceMap = copy(resources = resources.filter(_._2.remainingCapacity > 0)) - // TODO improve to only go through selected resources + /** + * Reduces the capacity of the resources based on a given map of named resource quantities. + * + * This is used when scheduling tasks which are not yet attached. + * + * @param A `Map` of resource names and quantities to reduce. + * @return The updated resource map. + */ def reduce(toReduce: Map[String, Int]): ResourceMap = + // TODO improve to only go through selected resources copy(resources = resources.map((n, s) => n -> s.reduce(toReduce))) /** - * The actual [[TaskResource]]s required. Retrieves the actual objects (instead of just their - * names) from a map. + * Retrieves the states of the resources required by a [[TaskInstance]]s. * - * @param resourceMap - * The map of available [[TaskResource]]s + * @param task + * The associated [[TaskInstance]]s * @return - * The [[TaskResource]]s required for this task. + * The [[ResourceState]]s required for this task. */ def get(task: TaskInstance): Seq[ResourceState] = task.resources.flatMap((n, _) => resources.get(n)).toSeq + /** + * Checks if the available resources have enough capacity to run a given [[TaskInstance]]. + * + * @param task The [[TaskInstance]] at hand. + * @return True if the task can be handled by the current resources. + */ def canHandle(task: TaskInstance): Boolean = task.resources.forall { (r, q) => resources.get(r).map(_.remainingCapacity >= q).getOrElse(false) } + /** + * Retrieves the remaining capacity of a named resource. + * + * @param name The name of the resource to check. + * @return The current capacity. + */ def remainingCapacityOf(name: String): Int = resources.get(name).map(_.remainingCapacity).getOrElse(0) + /** + * Retrieves the total capacity of a named resource. + * + * @param name The name of the resource to check. + * @return Its total capacity. + */ def capacityOf(name: String): Int = resources.get(name).map(_.resource.capacity).getOrElse(0) } @@ -174,4 +256,11 @@ object ResourceMap { ) } +/** + * A structure of a [[TaskInstance]] that has been detached and the corresponding [[ResourceState]]. + * + * @param start The timestamp when the task was attached originally. + * @param task The detached [[TaskKInstance]]. + * @param resource The updated [[ResourceState]]. + */ final case class DetachedTask(start: Long, task: TaskInstance, resource: ResourceState) From 3422f0010daf4b9d4a04d94e5ce3e374d5268690 Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Sun, 31 Jul 2022 00:15:57 +0100 Subject: [PATCH 03/31] Adds `Scenario` and `Simulator` scaladocs --- .../com/workflowfm/proter/Scenario.scala | 185 ++++++++++++++++++ .../com/workflowfm/proter/Simulator.scala | 72 ++++++- 2 files changed, 255 insertions(+), 2 deletions(-) diff --git a/proter/src/main/scala/com/workflowfm/proter/Scenario.scala b/proter/src/main/scala/com/workflowfm/proter/Scenario.scala index db4c350..8e3c836 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Scenario.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Scenario.scala @@ -11,33 +11,126 @@ import events.* import schedule.* import state.* +/** + * Convenience class to construct simulation scenarios. + * + * Provides various functions to set simulation parameters and compile them in + * a [[Simulation.SimState]]. + * + * Parameters include resources, cases/arrivals, and start and ending times. + * + * @note Ordering of method calls matters, especially when using [[withStartingTime]]. + * + * @param A name to identify the scenario. + * @param The current simulation state update corresponding to the parameters provided so far. + */ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState[F]) extends ScenarioState with StateOps { import Simulation._ + /** + * Composes another simulation state update directly. + * + * @param s The `SimState` to compose. + * @return The updated scenario. + */ def and(s: SimState[F]): Scenario[F] = copy(state = compose2(state, s)) + /** + * Adds a [[Resource]] to the simulation scenario. + * + * @param r The [[Resource]] to add. + * @return The updated scenario. + */ def withResource(r: Resource): Scenario[F] = and(lift(addResource(r))) + /** + * Adds a collection of [[Resource]]s to the simulation scenario. + * + * @param rs The [[Resource]]s to add. + * @return The updated scenario. + */ def withResources(rs: Seq[Resource]): Scenario[F] = and(lift(addResources(rs))) + /** + * Adds a [[Case]] to the simulation scenario. + * + * The case will be scheduled to start in the '''current''' start time + * of the scenario. + * + * Manipulating the scenario start time ''after'' adding the case may have unintended effects, + * such as having a case start time in the past. + * + * @tparam T The type of the object used for the simulation case. + * @param n A unique name for the case. + * @param t The object to use for the simulation case. + * @return The updated scenario. + */ def withCase[T](n: String, t: T)(using ct: Case[F, T]): Scenario[F] = and(addCaseNow(n, t)) + /** + * Adds a [[Case]] with a specified starting time to the simulation scenario. + * + * @tparam T The type of the object used for the simulation case. + * @param n A unique name for the case. + * @param time The timestamp when the case should start. + * @param t The object to use for the simulation case. + * @return The updated scenario. + */ def withTimedCase[T](n: String, time: Long, t: T)(using ct: Case[F, T]): Scenario[F] = and(addCase(time, n, t)) + /** + * Adds a collectiion of [[Case]]s to the simulation scenario. + * + * The cases will be scheduled to start in the '''current''' start time + * of the scenario. + * + * Manipulating the scenario start time ''after'' adding the cases may have unintended effects, + * such as having a case start time in the past. + * + * @tparam T The type of the objects used for the simulation case. + * @param cases The objects to use for the simulation case, + * each paired with its own unique name. + * @return The updated scenario. + */ def withCases[T](cases: (String, T)*)(using ct: Case[F, T]): Scenario[F] = and(addCasesNow(cases)) + /** + * Adds a collection of [[Case]]s, each with a specified starting time, to the simulation scenario. + * + * @tparam T The type of the objects used for the simulation case. + * @param cases The objects to use for the simulation case, + * each paired with its own unique name and starting timestamp. + * @return The updated scenario. + */ def withTimedCases[T](cases: (Long, String, T)*)(using ct: Case[F, T]): Scenario[F] = and(addCases(cases)) + /** + * Adds a [[Case]] with an arrival pattern to the simulation scenario. + * + * The first case will be scheduled to arrive in the '''current''' start time + * of the scenario. + * + * Manipulating the scenario start time ''after'' adding the cases may have unintended effects, + * such as having a case start time in the past. + * + * @tparam T The type of the object used for the simulation case. + * @param n A unique name for the cases. + * @param t The object to use for the simulation case. + * @param rate The probability ditribution determining the duration until the + * next arrival. + * @param limit The maximum number of cases to generate. + * @return The updated scenario. + */ def withArrival[T]( n: String, t: T, @@ -46,6 +139,18 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState )(using ct: Case[F, T], r: Random[F]): Scenario[F] = and(addArrivalNow(n, t, rate, Some(limit))) + /** + * Adds a [[Case]] with an arrival pattern and specified start time to the simulation scenario. + * + * @tparam T The type of the object used for the simulation case. + * @param n A unique name for the cases. + * @param time The timestamp when the first case should arrive. + * @param t The object to use for the simulation case. + * @param rate The probability ditribution determining the duration until the + * next arrival. + * @param limit The maximum number of cases to generate. + * @return The updated scenario. + */ def withTimedArrival[T]( n: String, time: Long, @@ -55,6 +160,26 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState )(using ct: Case[F, T], r: Random[F]): Scenario[F] = and(addArrival(time, n, t, rate, Some(limit))) + /** + * Adds a [[Case]] with an infinite arrival pattern to the simulation scenario. + * + * The first case will be scheduled to arrive in the '''current''' start time + * of the scenario. + * + * Manipulating the scenario start time ''after'' adding the cases may have unintended effects, + * such as having a case start time in the past. + * + * The scenario will continue to generate cases infinitely until the time limit has been reached. + * + * @see [[withLimit]] + * + * @tparam T The type of the object used for the simulation case. + * @param n A unique name for the cases. + * @param t The object to use for the simulation case. + * @param rate The probability ditribution determining the duration until the + * next arrival. + * @return The updated scenario. + */ def withInfiniteArrival[T]( n: String, t: T, @@ -62,6 +187,21 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState )(using ct: Case[F, T], r: Random[F]): Scenario[F] = and(addArrivalNow(n, t, rate, None)) + /** + * Adds a [[Case]] with an infinite arrival pattern and specified start time. + * + * The scenario will continue to generate cases infinitely until the time limit has been reached. + * + * @see [[withLimit]] + * + * @tparam T The type of the object used for the simulation case. + * @param n A unique name for the cases. + * @param time The timestamp when the first case should arrive. + * @param t The object to use for the simulation case. + * @param rate The probability ditribution determining the duration until the + * next arrival. + * @return The updated scenario. + */ def withTimedInfiniteArrival[T]( n: String, time: Long, @@ -70,16 +210,61 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState )(using ct: Case[F, T], r: Random[F]): Scenario[F] = and(addArrival(time, n, t, rate, None)) + /** + * Sets a time limit for the simulation. + * + * All running cases will be aborted at that timestamp and the simulation will stop. + * + * Calling this method multiple times will result in the earliest timestamp becoming the + * time limit. + * + * Setting the time limit after the start time will result in an error. + * + * @param t The timestamp to use as the time limit. + * @return The updated scenario. + */ def withLimit(t: Long): Scenario[F] = and(lift(limit(t))) + /** + * Sets the start time for the simulation. + * + * This will be the first timestamp in the simulation. Cases with no specified + * start time will start at the time set here. + * + * Setting the start time after some cases are already scheduled will result in an error. + * + * Calling this method multiple times will result in the timestamp given in the last call + * becoming the start time. + * + * Setting the start time after the time limit will result in an error. + * + * @param t The timestamp to use as the start time. + * @return The updated scenario. + */ def withStartingTime(t: Long): Scenario[F] = and(StateT(sim => Monad[F].pure((sim.copy(time = t), Seq())))) } object Scenario extends StateOps { + /** + * Initialise a scenario by its name. + * + * @param name The name to use for the scenario. + * @return An empty scenario. + */ def apply[F[_] : Monad](name: String): Scenario[F] = Scenario(name, idState) + /** + * Initialise a scenario by its name and start time. + * + * Using this as a constructor is preferred as it reduces the chance of + * misusing `withStartingTime`. + * + * @param name The name to use for the scenario. + * @param start The timestamp to use as the start time. + * @return An empty scenario. + */ def apply[F[_] : Monad](name: String, start: Long): Scenario[F] = Scenario(name).withStartingTime(start) } diff --git a/proter/src/main/scala/com/workflowfm/proter/Simulator.scala b/proter/src/main/scala/com/workflowfm/proter/Simulator.scala index e363f3a..8a37bf7 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Simulator.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Simulator.scala @@ -13,23 +13,74 @@ import cats.effect.std.Random import cats.implicits.* import cats.effect.implicits.* +/** + * Runs simulations. + * + * @param scheduler The [[Scheduler]] to use during simulation. + * @param subscribers The [[Subscriber]]s that should receive events. + */ final case class Simulator[F[_] : Concurrent]( scheduler: Scheduler, subscribers: Seq[Subscriber[F]] ) extends ScenarioState { + /** + * Updates the [[Scheduler]] to be used during simulation. + * + * @param s The new [[Scheduler]]. + * @return The updated simulator. + */ def withScheduler(s: Scheduler): Simulator[F] = copy(scheduler = s) + /** + * Updates to using a single [[Subscriber]]. + * + * @param sub The new [[Subscriber]]. + * @return The updated simulator. + */ def withSub(sub: Subscriber[F]): Simulator[F] = copy(subscribers = Seq(sub)) - def withSubs(subs: Subscriber[F]*): Simulator[F] = copy(subscribers = subscribers ++ subs) - def and(sub: Subscriber[F]): Simulator[F] = copy(subscribers = subscribers :+ sub) + /** + * Updates to using new [[Subscriber]]s. + * + * @param subs The new [[Subscriber]]s. + * @return The updated simulator. + */ + def withSubs(subs: Subscriber[F]*): Simulator[F] = copy(subscribers = subs) + + /** + * Adds additional [[Subscriber]]s. + * + * @param subs The new [[Subscriber]]s to add. + * @return The updated simulator. + */ + def and(subs: Subscriber[F]*): Simulator[F] = copy(subscribers = subscribers ++ subs) + + /** + * Simulates a [[Scenario]]. + * + * @param scenario The [[Scenario]] to simulate. + * @return An effect producing `Unit` when the simulation finishes. + */ def simulate(scenario: Scenario[F]): F[Unit] = simulateState(scenario.name, scenario.state) + /** + * Simulates a [[Scenario]] and streams the [[Event]]s. + * + * @param scenario The [[Scenario]] to simulate. + * @return A stream of [[Event]]s or `Throwable` errors. + */ def stream(scenario: Scenario[F]): Stream[F, Either[Throwable, Event]] = streamState(scenario.name, scenario.state) + /** + * Runs a simulation from a given [[Simulation.SimState]]. + * + * @param name A name to use for the simulation. + * @param state The starting state. + * @return An effect producing `Unit` when the simulation finishes. + */ def simulateState(name: String, state: StateT[F, Simulation[F], Seq[Event]]): F[Unit] = for { publisher <- Publisher.build[F]() subresource = subscribers.map(publisher.subscribe(_)).parSequence @@ -42,6 +93,13 @@ final case class Simulator[F[_] : Concurrent]( } } yield (()) + /** + * Runs and streams a simulation from a given [[Simulation.SimState]]. + * + * @param name A name to use for the simulation. + * @param state The starting state. + * @return A stream of [[Event]]s or `Throwable` errors. + */ def streamState( name: String, state: StateT[F, Simulation[F], Seq[Event]] @@ -60,6 +118,16 @@ final case class Simulator[F[_] : Concurrent]( } yield (stream)) .flatten + /** + * Runs a [[Simulation.SimState]] with a given [[Publisher]]. + * + * Subscribers should be handled externally. We are only publishing here. + * + * @param name A name to use for the simulation. + * @param state The starting state. + * @param publisher The [[Publisher]] to use. + * @return An effect producing `Unit` when the simulation finishes.. + */ def simulateStateWithPublisher( name: String, state: StateT[F, Simulation[F], Seq[Event]], From 6c3bd28eccc5863587f487e665e39329e48ce0db Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Sun, 31 Jul 2022 00:17:53 +0100 Subject: [PATCH 04/31] Removes no longer needed `ResourceState.hasCapacity` tests --- .../com/workflowfm/proter/Resource.scala | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/proter/src/test/scala/com/workflowfm/proter/Resource.scala b/proter/src/test/scala/com/workflowfm/proter/Resource.scala index 7f2adc8..ff0bf7b 100644 --- a/proter/src/test/scala/com/workflowfm/proter/Resource.scala +++ b/proter/src/test/scala/com/workflowfm/proter/Resource.scala @@ -12,27 +12,6 @@ class ResourceTests with LoneElement { "ResourceState" when { - "calling `hasCapacity`" should { - "check capacity of an empty state" in { - rs("Test", 1821)().hasCapacity `should` be(true) - } - - "check capacity with a single task" in { - rs("Test", 1821)((1L, 0L, 1820)).hasCapacity `should` be(true) - } - - "check capacity with 2 tasks" in { - rs("Test", 1821)((1L, 0L, 20), (2L, 0L, 1800)).hasCapacity `should` be(true) - } - - "check full capacity with a single task" in { - rs("Test", 1821)((1L, 0L, 1821)).hasCapacity `should` be(false) - } - - "check full capacity with 2 tasks" in { - rs("Test", 1821)((1L, 0L, 21), (2L, 0L, 1800)).hasCapacity `should` be(false) - } - } "calling `remainingCapacity`" should { "calculate capacity of an empty state" in { From 588601ebcec4172fbb194b30da98ca8c9aab7d6c Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Sun, 31 Jul 2022 00:23:15 +0100 Subject: [PATCH 05/31] Moves `TestSim` to tests --- .../com/workflowfm/proter/Simulator.scala | 126 ----------------- .../scala/com/workflowfm/proter/TestSim.scala | 133 ++++++++++++++++++ 2 files changed, 133 insertions(+), 126 deletions(-) create mode 100644 proter/src/test/scala/com/workflowfm/proter/TestSim.scala diff --git a/proter/src/main/scala/com/workflowfm/proter/Simulator.scala b/proter/src/main/scala/com/workflowfm/proter/Simulator.scala index 8a37bf7..e5206a0 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Simulator.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Simulator.scala @@ -159,129 +159,3 @@ object Simulator { } -import cases.* -import cases.given -import flows.* -import flows.given -import metrics.* - -import cats.effect.{ IO, IOApp, ExitCode } - -object TestSim extends IOApp { - - def run(args: List[String]): IO[ExitCode] = - runScenarioStream() - - def runState(): IO[ExitCode] = - Random.scalaUtilRandom[IO].flatMap { r => - given Random[IO] = r - val simulator = Simulator[IO](ProterScheduler) withSub (PrintEvents()) - val cases = simulator.addCasesNow[IO, Task]( - Seq( - ("foo1", Task("t", 1)), - ("foo2", Task("t", 2)), - ("foo3", Task("t", 3)), - ("foo4", Task("t", 4)), - ("foo4.2", Task("t", 4)) - ) - ) - simulator.simulateState("X", cases).as(ExitCode(1)) - } - - def runScenario(): IO[ExitCode] = - Random.scalaUtilRandom[IO].flatMap { r => - given Random[IO] = r - val simulator = Simulator[IO](ProterScheduler) withSubs ( - // PrintEvents(), - PrintJsonEvents(), -// PrintEvents(), - MetricsSubscriber[IO]( - MetricsPrinter() - // CSVFile("output/", "HAHA"), - // D3Timeline("output/", "HAHA") - ) - ) - val scenario = Scenario[IO]("MYSCENARIO") - .withStartingTime(14) - .withResources( - Seq( - Resource("A", 2, 1) - ) - ) - // .withCases( - // ("foo1", Task("t", 1)), - // ("foo2", Task("t", 2)) - // ("foo3", Task("t", 3)), - // ("foo4", Task("t", 4)), - // ("foo4.2", Task("t", 4)), - // ) - // .withCases( - // ("foo1", Task("t", 1).withCost(10).withResources(Seq("A"))), - // ("foo2", Task("t", 2).withCost(10).withResources(Seq("A"))), - // ("foo3", Task("t", 3).withResources(Seq("A"))), - // ("foo4", Task("t", 4).withResourceQuantities(Seq(("A", 2)).toMap)), - // ("foo4.2", Task("t", 4).withResourceQuantities(Seq(("A", 2)).toMap)), - // ) - .withTimedCases( - (14, "foo1", Task("t", 10).withCost(10).withResourceQuantities(Seq(("A", 1)).toMap)), - (16, "foo2", Task("t", 2).withCost(10).withResourceQuantities(Seq(("A", 1)).toMap)) - ) - - // .withCases( - // ("flowsingle", FlowTask(Task("f1", 1)): Flow), - // ("flow1", Flow(Task("f1", 1), Task("f2", 1))), - // ("flow2", Flow.par(Seq(Task("f2a", 1), Task("f2b", 2), Task("f2c", 3)).map(FlowTask(_)))) - // ("flowAnd", And(FlowTask(Task("f1", 1)), FlowTask(Task("f2", 2))): Flow), - // ) - // .withArrival("A1", Task("t", 1), ConstantLong(2), 10) - // .withTimedArrival("A2", 5, Task("t", 1), ConstantLong(2), 1) - // .withInfiniteArrival("A3", Task("t", 2), ConstantLong(5)) - .withLimit(25) - - simulator.simulate(scenario).as(ExitCode(1)) - } - - def run2Scenarios(): IO[ExitCode] = - Random.scalaUtilRandom[IO].flatMap { r => - given Random[IO] = r - for { - counter <- CountEvents[IO]() - simulator = Simulator[IO](ProterScheduler) withSubs ( - PrintEvents(), - counter - ) - - scenario1 = Scenario[IO]("Scenario 1") - .withStartingTime(1) - .withCase("foo1", Task("t1", 1)) - scenario2 = Scenario[IO]("Scenario 2") - .withStartingTime(20) - .withCase("foo2", Task("2", 1)) - - _ <- simulator.simulate(scenario1) - _ <- simulator.simulate(scenario2) - count <- counter.get() - _ <- IO.println(s"*** Final count: $count") - } yield (ExitCode.Success) - } - - def runScenarioStream(): IO[ExitCode] = - Random.scalaUtilRandom[IO].flatMap { r => - given Random[IO] = r - val simulator = Simulator[IO](ProterScheduler) withSubs ( - PrintEvents() - ) - - val scenario = Scenario[IO]("Scenario 1") - .withStartingTime(1) - .withCase("foo1", Task("t1", 1)) - - simulator - .stream(scenario) - .evalTap(x => IO.println(s">>>>> $x")) - .compile - .drain - .as(ExitCode.Success) - } - -} diff --git a/proter/src/test/scala/com/workflowfm/proter/TestSim.scala b/proter/src/test/scala/com/workflowfm/proter/TestSim.scala new file mode 100644 index 0000000..15ca787 --- /dev/null +++ b/proter/src/test/scala/com/workflowfm/proter/TestSim.scala @@ -0,0 +1,133 @@ +package com.workflowfm.proter + +import cases.* +import cases.given +import events.* +import flows.* +import flows.given +import metrics.* +import schedule.* + +import cats.effect.{ IO, IOApp, ExitCode } +import cats.effect.std.Random + +object TestSim extends IOApp { + + def run(args: List[String]): IO[ExitCode] = + runScenarioStream() + + def runState(): IO[ExitCode] = + Random.scalaUtilRandom[IO].flatMap { r => + given Random[IO] = r + val simulator = Simulator[IO](ProterScheduler) withSub (PrintEvents()) + val cases = simulator.addCasesNow[IO, Task]( + Seq( + ("foo1", Task("t", 1)), + ("foo2", Task("t", 2)), + ("foo3", Task("t", 3)), + ("foo4", Task("t", 4)), + ("foo4.2", Task("t", 4)) + ) + ) + simulator.simulateState("X", cases).as(ExitCode(1)) + } + + def runScenario(): IO[ExitCode] = + Random.scalaUtilRandom[IO].flatMap { r => + given Random[IO] = r + val simulator = Simulator[IO](ProterScheduler) withSubs ( + // PrintEvents(), + PrintJsonEvents(), +// PrintEvents(), + MetricsSubscriber[IO]( + MetricsPrinter() + // CSVFile("output/", "HAHA"), + // D3Timeline("output/", "HAHA") + ) + ) + val scenario = Scenario[IO]("MYSCENARIO") + .withStartingTime(14) + .withResources( + Seq( + Resource("A", 2, 1) + ) + ) + // .withCases( + // ("foo1", Task("t", 1)), + // ("foo2", Task("t", 2)) + // ("foo3", Task("t", 3)), + // ("foo4", Task("t", 4)), + // ("foo4.2", Task("t", 4)), + // ) + // .withCases( + // ("foo1", Task("t", 1).withCost(10).withResources(Seq("A"))), + // ("foo2", Task("t", 2).withCost(10).withResources(Seq("A"))), + // ("foo3", Task("t", 3).withResources(Seq("A"))), + // ("foo4", Task("t", 4).withResourceQuantities(Seq(("A", 2)).toMap)), + // ("foo4.2", Task("t", 4).withResourceQuantities(Seq(("A", 2)).toMap)), + // ) + .withTimedCases( + (14, "foo1", Task("t", 10).withCost(10).withResourceQuantities(Seq(("A", 1)).toMap)), + (16, "foo2", Task("t", 2).withCost(10).withResourceQuantities(Seq(("A", 1)).toMap)) + ) + + // .withCases( + // ("flowsingle", FlowTask(Task("f1", 1)): Flow), + // ("flow1", Flow(Task("f1", 1), Task("f2", 1))), + // ("flow2", Flow.par(Seq(Task("f2a", 1), Task("f2b", 2), Task("f2c", 3)).map(FlowTask(_)))) + // ("flowAnd", And(FlowTask(Task("f1", 1)), FlowTask(Task("f2", 2))): Flow), + // ) + // .withArrival("A1", Task("t", 1), ConstantLong(2), 10) + // .withTimedArrival("A2", 5, Task("t", 1), ConstantLong(2), 1) + // .withInfiniteArrival("A3", Task("t", 2), ConstantLong(5)) + .withLimit(25) + + simulator.simulate(scenario).as(ExitCode(1)) + } + + def run2Scenarios(): IO[ExitCode] = + Random.scalaUtilRandom[IO].flatMap { r => + given Random[IO] = r + for { + counter <- CountEvents[IO]() + simulator = Simulator[IO](ProterScheduler) withSubs ( + PrintEvents(), + counter + ) + + scenario1 = Scenario[IO]("Scenario 1") + .withStartingTime(1) + .withCase("foo1", Task("t1", 1)) + scenario2 = Scenario[IO]("Scenario 2") + .withStartingTime(20) + .withCase("foo2", Task("2", 1)) + + _ <- simulator.simulate(scenario1) + _ <- simulator.simulate(scenario2) + count <- counter.get() + _ <- IO.println(s"*** Final count: $count") + } yield (ExitCode.Success) + } + + def runScenarioStream(): IO[ExitCode] = + Random.scalaUtilRandom[IO].flatMap { r => + given Random[IO] = r + val simulator = Simulator[IO](ProterScheduler) withSubs ( + PrintEvents() + ) + + val scenario = Scenario[IO]("Scenario 1") + .withStartingTime(1) + .withCase("foo1", Task("t1", 1)) + + simulator + .stream(scenario) + .evalTap(x => IO.println(s">>>>> $x")) + .compile + .drain + .as(ExitCode.Success) + } + +} + + From 192f10b976bfbe4c3838fd34c0909facffe7f6e4 Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Sun, 31 Jul 2022 00:46:13 +0100 Subject: [PATCH 06/31] Scaladoc for `Task` and `Simulation` (WIP) --- .../scala/com/workflowfm/proter/Task.scala | 34 +++++++++++-------- .../workflowfm/proter/state/Simulation.scala | 14 ++++++++ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/proter/src/main/scala/com/workflowfm/proter/Task.scala b/proter/src/main/scala/com/workflowfm/proter/Task.scala index 051ef7d..de7c23a 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Task.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Task.scala @@ -11,23 +11,23 @@ import cats.implicits.* * @note * We expect that task instances are only generated through a [[Task]]. * - * The samples of the parameters are generated by the [[Coordinator]]. The duration can be + * The samples of the parameters are generated during simulation. The duration can be * specified through random sampling in a [[Distribution]]. We store the estimated value as well as * the actual sampled value. * * @param id - * A unique id that separates this task from any other task. A workflow may spawn multiple tasks + * A unique id that separates this task from any other task. A case may spawn multiple tasks * with the same name, so this is necessary. * @param name * A descriptive name. - * @param simulation - * A unique name of the simulation this task belongs to. + * @param caseName + * The unique name of the case this task belongs to. * @param created * The timestamp when this task was created. * @param minStartTime - * The earliest possible starting time of this task. + * The earliest starting time of this task. Used for scheduling tasks in the future. * @param resources - * The names of the [[TaskResource]]s required by this task. + * The names and required capacities of the [[Resource]]s for this task. * @param duration * The actual duration of the task. * @param estimatedDuration @@ -110,7 +110,7 @@ final case class TaskInstance( } /** - * A generator/factory of tasks (specifically [[TaskInstance]]s). + * A descriptor of tasks and generator/factory of [[TaskInstance]]s. * * As a case class, it can be easily manipulated dynamically to alter its values. * @@ -130,9 +130,9 @@ final case class TaskInstance( * @param cost * The generator of the cost. * @param minStartTime - * The earliest possible starting time of the task. + * The earliest starting time of the task. Used for scheduling tasks in the future. * @param resources - * The resources of this task + * The resources and required capacities for this task. * @param interrupt * The [[TaskInstance.interrupt]] property of the task. * @param priority @@ -155,12 +155,10 @@ final case class Task( /** * Generate a [[TaskInstance]]. * - * @param simulation - * The name of the simulation that is spawning the instance. + * @param caseName + * The name of the case that is spawning the instance. * @param currentTime * The current time. - * @param addedCost - * Any added cost, such as resource running costs. * @return * The generated [[TaskInstance]]. */ @@ -197,7 +195,7 @@ final case class Task( def withID(i: UUID): Task = copy(id = Some(i)) /** - * Update the resources to use. + * Add required resources to use, each with required capacity 1. * * @param r * The new resources. @@ -206,6 +204,14 @@ final case class Task( */ def withResources(r: Seq[String]): Task = copy(resources = resources ++ r.map(_ -> 1)) + /** + * Add resources and required capacities to use. + * + * @param r + * The new resources. + * @return + * An updated [[Task]]. + */ def withResourceQuantities(s: Map[String, Int]): Task = copy(resources = resources ++ s) /** diff --git a/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala b/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala index 58c2d0b..c552fe8 100644 --- a/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala +++ b/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala @@ -15,6 +15,20 @@ import scala.collection.immutable.{ HashSet, Set, Map, Queue } import scala.util.{ Try, Success, Failure } import java.util.UUID +/** + * A simulation state. + * + * @param id A name for the entire simulation. + * @param scheduler The [[Scheduler]] being used. + * @param time The current time. + * @param events The [[EventQueue]] of pending discrete events. + * @param tasks Current running [[TaskInstance]]s. + * @param cases Indexed map of currently running [[CaseRef]]s. + * @param resources The [[ResourceMap]] of the resources used in the simulation. + * @param waiting Indexed map of [[CaseRef]] names and corresponding finished tasks (if any) + * from which we are expecting a response. + * @param abortedTasks Set of [[TaskInstance]]s that have been aborted. + */ case class Simulation[F[_]]( id: String, scheduler: Scheduler, From 7fafc92be4b86e29010091353808d070bd784f55 Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Sun, 31 Jul 2022 15:13:44 +0100 Subject: [PATCH 07/31] Adds/updates all state-related scaladoc --- .../com/workflowfm/proter/Scenario.scala | 4 +- .../workflowfm/proter/state/CaseState.scala | 63 ++++- .../proter/state/ScenarioState.scala | 142 +++++++---- .../workflowfm/proter/state/Simulation.scala | 227 ++++++++++++------ 4 files changed, 296 insertions(+), 140 deletions(-) diff --git a/proter/src/main/scala/com/workflowfm/proter/Scenario.scala b/proter/src/main/scala/com/workflowfm/proter/Scenario.scala index 8e3c836..740b68c 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Scenario.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Scenario.scala @@ -95,8 +95,8 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState * Manipulating the scenario start time ''after'' adding the cases may have unintended effects, * such as having a case start time in the past. * - * @tparam T The type of the objects used for the simulation case. - * @param cases The objects to use for the simulation case, + * @tparam T The type of the objects used for the simulation cases. + * @param cases The objects to use for each simulation case, * each paired with its own unique name. * @return The updated scenario. */ diff --git a/proter/src/main/scala/com/workflowfm/proter/state/CaseState.scala b/proter/src/main/scala/com/workflowfm/proter/state/CaseState.scala index 8844686..aa26f12 100644 --- a/proter/src/main/scala/com/workflowfm/proter/state/CaseState.scala +++ b/proter/src/main/scala/com/workflowfm/proter/state/CaseState.scala @@ -15,22 +15,26 @@ import scala.collection.immutable.{ HashSet, Set, Map, Queue } import scala.util.{ Try, Success, Failure } import java.util.UUID +/** + * Includes simulation state updates required when executing a [[Case]]/[[CaseRef]]. + */ trait CaseState extends ScenarioState { /** - * Adds new [[Task]](s) for a simulation. + * Adds a new [[Task]]. * * - Uses [[Task.create]] to create a [[TaskInstance]], which will now have a fixed duration * and cost. * - Publishes a [[com.workflowfm.proter.events.ETaskAdd ETaskAdd]]. * - If the task does not require any resources, it is started immediately using [[startTask]]. - * Otherwise, we add it to the [[schedule.Scheduler Scheduler]]. * * @group tasks - * @param simulation - * The name of the [[Simulation]] that owns the task(s). + * @param caseName + * The name of the [[CaseRef]] that owns the task. * @param task - * The list of [[Task]]s to be added. + * The [[Task]] to be added. + * @return + * The state update. */ def addTask[F[_] : Random : Monad]( caseName: String @@ -47,25 +51,51 @@ trait CaseState extends ScenarioState { } }) + /** + * Adds a collection of new [[Task]]s. + * + * @see [[addTask]] + * + * @group tasks + * @param caseName + * The name of the [[CaseRef]] that owns the task. + * @param tasks + * The [[Task]]s to be added. + * @return + * The state update. + */ def addTasks[F[_] : Random : Monad]( caseName: String, tasks: Seq[Task] ): StateT[F, Simulation[F], Seq[Event]] = tasks.traverse(addTask(caseName)).map(_.flatten) + /** + * Aborts a list of [[TaskInstance]]s by their IDs. + * + * @see [[Simulation.abortTasks]] + * + * @group tasks + * @param ids + * The `UUID`s of the [[TaskInstance]]s to abort. + * @return + * The state update. + */ def abortTasks[F[_]](ids: Seq[UUID]): State[Simulation[F], Seq[Event]] = Simulation.abortTasks(ids) /** - * Handles a [[SimDone]] response from a simulation, indicating that it has completed. + * Updates the simulation with a completed [[CaseRef]]. * - * Calls [[stopSimulation]] according to the reported success or failure result. + * @see [[Simulation.stopCase]] * - * @group simulations - * @param simulation - * The name of the simulation + * @group cases + * @param caseName + * The name of the [[CaseRef]]. * @param result - * The result of completion + * The result produced by the completed [[CaseRef]]. + * @return + * The state update. */ def caseDone[F[_] : Monad]( caseName: String, @@ -81,6 +111,17 @@ trait CaseState extends ScenarioState { } } + /** + * Updates a [[CaseRef]]. + * + * @group cases + * @param caseName + * The name of the [[CaseRef]]. + * @param c + * The new [[CaseRef]] reflecting the new state of the case. + * @return + * The state update. + */ def updateCase[F[_] : Monad]( caseName: String, c: CaseRef[F] diff --git a/proter/src/main/scala/com/workflowfm/proter/state/ScenarioState.scala b/proter/src/main/scala/com/workflowfm/proter/state/ScenarioState.scala index 3cd97c7..6cebde6 100644 --- a/proter/src/main/scala/com/workflowfm/proter/state/ScenarioState.scala +++ b/proter/src/main/scala/com/workflowfm/proter/state/ScenarioState.scala @@ -15,8 +15,19 @@ import scala.collection.immutable.{ HashSet, Set, Map, Queue } import scala.util.{ Try, Success, Failure } import java.util.UUID +/** + * Includes simulation state updates required when setting up a simulation [[Scenario]]. + */ trait ScenarioState { + /** + * Adds a [[Resource]] to the simulation. + * + * Produces an [[EResourceAdd]] event. + * + * @param r The [[Resource]] to add. + * @return The state update. + */ def addResource[F[_]](r: Resource): State[Simulation[F], Seq[Event]] = State(sim => ( sim.copy(resources = sim.resources.addResource(r)), @@ -24,22 +35,27 @@ trait ScenarioState { ) ) + /** + * Adds a collection of [[Resource]]s to the simulation. + * + * Produces an [[EResourceAdd]] event for each resource. + * + * @param rs The [[Resource]]s to add. + * @return The state update. + */ def addResources[F[_]](rs: Seq[Resource]): State[Simulation[F], Seq[Event]] = State(sim => { val events = rs.map { r => EResourceAdd(sim.id, sim.time, r) } (sim.copy(resources = sim.resources.addResources(rs)), events) }) /** - * Add a new simulation to be run. - * - * Publishes a [[com.workflowfm.proter.events.ESimAdd ESimAdd]]. - * - * @group simulations - * @param t - * The timestamp when the simulation needs to start. Must be greater or equal to the current - * time. - * @param simulation - * The [[Simulation]] to run. + * Adds a [[CaseRef]] to the simulation. + * + * Produces an [[ECaseAdd]] event. + * + * @param t The timestamp when the case needs to start. Must be greater or equal to the current + * simulation time. + * @return The state update. */ def addCaseRef[F[_]](t: Long, caseRef: CaseRef[F]): State[Simulation[F], Seq[Event]] = State(sim => @@ -51,6 +67,18 @@ trait ScenarioState { else (sim, Seq(sim.error(s"Attempted to start case [${caseRef.caseName}] in the past: $t"))) ) + /** + * Adds a [[Case]] to the simulation. + * + * Produces an [[ECaseAdd]] event. + * + * @tparam T The type of the object used for the simulation case. + * @param time The timestamp when the case needs to start. Must be greater or equal to the current + * simulation time. + * @param name A unique name for the case. + * @param t The object to use for the simulation case. + * @return The state update. + */ def addCase[F[_] : Monad, T](time: Long, name: String, t: T)( using ct: Case[F, T] ): StateT[F, Simulation[F], Seq[Event]] = StateT(sim => @@ -65,13 +93,14 @@ trait ScenarioState { ) /** - * Add a new simulation to be run in the current virtual time. - * - * Publishes a [[com.workflowfm.proter.events.ESimAdd ESimAdd]] for each simulation. - * - * @group simulations - * @param simulation - * The [[Simulation]] to run. + * Adds a [[Case]] to be run in the '''current''' simulation time. + * + * Produces an [[ECaseAdd]] event. + * + * @tparam T The type of the object used for the simulation case. + * @param name A unique name for the case. + * @param t The object to use for the simulation case. + * @return The state update. */ def addCaseNow[F[_] : Monad, T](name: String, t: T)( using ct: Case[F, T] @@ -79,14 +108,14 @@ trait ScenarioState { StateT.inspect[F, Simulation[F], Long](_.time).flatMap { time => addCase(time, name, t) } /** - * Adds multiple simulations at the same time. - * - * This is equivalent to mapping [[addSimulation]] over the given sequence, but more efficient. - * - * @group simulations - * @param sims - * A sequence of pairs, each consisting of a starting timestamp and a [[Simulation]]. - * Timestamps must be greater or equal to the current time. + * Adds a collection of [[Case]]s to the simulation. + * + * Produces an [[ECaseAdd]] event for each case added. + * + * @tparam T The type of the object used for the simulation case. + * @param cases The objects to use for each simulation case, + * each paired with its own unique name and starting timestamp. + * @return The state update. */ def addCases[F[_] : Monad, T](cases: Seq[(Long, String, T)])( using ct: Case[F, T] @@ -94,11 +123,14 @@ trait ScenarioState { cases.map((t, n, c) => addCase(t, n, c)).sequence.map(_.flatten) /** - * Add multiple simulations to be run in the current virtual time. - * - * @group simulations - * @param sims - * A sequence of [[Simulation]]s. + * Adds a collection of [[Case]]s to be run in the '''current''' simulation time. + * + * Produces an [[ECaseAdd]] event for each case added. + * + * @tparam T The type of the object used for the simulation case. + * @param cases The objects to use for each simulation case, + * each paired with its own unique name. + * @return The state update. */ def addCasesNow[F[_] : Monad, T](cases: Seq[(String, T)])( using ct: Case[F, T] @@ -106,18 +138,18 @@ trait ScenarioState { cases.map((n, c) => addCaseNow(n, c)).sequence.map(_.flatten) /** - * Adds a new arrival process to the coordinator. - * - * @param t - * The virtual timestamp when the arrival process will begin. - * @param name - * The name to use - * @param limit - * The number of simulation instances to spawn. - * @param rate - * The arrival rate of the simulation instances. - * @param simulationGenerator - * The generator used to create new instances. + * Adds a [[Case]] with an arrival pattern to the simulation. + * + * Produces an [[EArrivalAdd]] event. + * + * @tparam T The type of the object used for the simulation cases. + * @param t The timestamp when the first case should arrive. + * @param name A unique name for the cases. + * @param item The object to use for the simulation case. + * @param rate The probability ditribution determining the duration until the + * next arrival. + * @param limit An optional maximum number of cases to generate. + * @return The state update. */ def addArrival[F[_] : Monad : Random, T]( t: Long, @@ -140,6 +172,19 @@ trait ScenarioState { ) ) + /** + * Adds a [[Case]] with an arrival pattern to start in the '''current''' simulation time. + * + * Produces an [[EArrivalAdd]] event. + * + * @tparam T The type of the object used for the simulation cases. + * @param name A unique name for the cases. + * @param item The object to use for the simulation case. + * @param rate The probability ditribution determining the duration until the + * next arrival. + * @param limit An optional maximum number of cases to generate. + * @return The state update. + */ def addArrivalNow[F[_] : Monad : Random, T]( name: String, item: T, @@ -151,15 +196,18 @@ trait ScenarioState { } /** - * Sets a time limit in virtual time for the simulation to end. + * Sets a time limit for the simulation. * + * Produces an [[ETimeLimit]] event. + * * @note * Once a time limit is placed it cannot be removed. Multiple time limits can be set so that * the earliest one will be triggered. - * - * @group toplevel - * @param t - * The virtual timestamp to end the simulation. + * + * Setting the time limit after the start time will result in an error. + * + * @param t The timestamp to use as the time limit. + * @return The state update. */ def limit[F[_]](t: Long): State[Simulation[F], Seq[Event]] = State(sim => if t >= sim.time then diff --git a/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala b/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala index c552fe8..639f587 100644 --- a/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala +++ b/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala @@ -41,27 +41,83 @@ case class Simulation[F[_]]( abortedTasks: HashSet[UUID] ) { + + /** + * Convenience method to produce an [[EError]] event. + * + * @param description A description of the error that occurred. + * @return An [[EError]] event. + */ def error(description: String): EError = EError(id, time, description) + /** + * Convenience method to produce an [[EError]] event, followed by [[EDone]]. + * + * Essentially tells the event stream that the simulation has completed after the error, + * i.e. that the error was unrecoverable. + * + * @param description A description of the error that occurred. + * @return The generated sequence of 2 events. + */ def fatalError(description: String): Seq[Event] = Seq(EError(id, time, description), EDone(id, time)) + /** + * Removes a [[CaseRef]] name from the waiting list. + * + * @param description A description of the error that occurred. + * @return An [[EError]] event. + */ def ready(name: String): Simulation[F] = copy(waiting = waiting - name) + + /** + * Uses the [[Scheduler]] to compute the next [[TaskInstance]]s to run based on resource availability. + * + * @param description A description of the error that occurred. + * @return An [[EError]] event. + */ def nextTasks(): Iterable[TaskInstance] = scheduler.getNextTasks(time, tasks, resources) + /** + * Yields a state change from a [[CaseRef]]. + * + * This happens when we are waiting from a response from the [[CaseRef]], either because + * it has just started or because one or more of its [[TaskInstance]]s has completed. + * + * @param waiting The name of the [[CaseRef]] to notify, paired with a sequence of completed + * [[TaskInstance]]s or an empty sequence if the case just started. + * @return The state update produced by the [[CaseRef]]. + */ def notifyCase(waiting: (String, Seq[TaskInstance]))(using Monad[F]): F[Simulation.SimState[F]] = waiting match { case (caseName, tasks) => cases.get(caseName) match { - case None => Monad[F].pure(Simulation.unknownCase(caseName)) + case None => Monad[F].pure(Simulation.unknownCaseToNotify(caseName)) case Some(c) => if tasks.isEmpty then c.run() else c.completed(time, tasks) } } + /** + * Notifies all [[CaseRef]]s in the waiting list. + * + * @see [[notifyCase]] + * + * Composes and applies all state updates produced by all notified [[CaseRef]]s. + * + * @return The updated simulation state and produced [[Event]]s. + */ def notifyCases(using Monad[F]): F[(Simulation[F], Seq[Event])] = waiting.map(notifyCase).toSeq.sequence.map(Simulation.compose(_: _*).run(this)).flatten + /** + * Starts the simulation with an initial state update. + * + * Produces an [[EStart]] event. + * + * @param state The state update to apply. + * @return The updated state and produced [[Event]]s. + */ def start( state: StateT[F, Simulation[F], Seq[Event]] )(using Monad[F]): F[(Simulation[F], Seq[Event])] = @@ -73,6 +129,20 @@ case class Simulation[F[_]]( ) .run(this) + /** + * Progresses the simulation time. + * + * This is the main simulation cycle: + * 1. Finish with an [[EDone]] if no events, tasks, or cases remain. + * 1. Pop the next group of discrete events in the queue. + * 1. Handle the events using [[Simulation.handleDiscreteEvent]]. + * 1. Stop any tasks that completed ysing [[Simulation.stopTasks]]. + * 1. Notify the cases that need to be notified with [[notifyCases]]. + * 1. Allocate new tasks to the resources using [[Simulation.allocateTasks]]. + * 1. Terminate the simulation using [[Simulation.stop()]] if a termination condition (e.g. time limit) has been met. + * + * @return Either the updated state or `Unit` if the simulation terminated, and any produced [[Event]]s. + */ def tick(using Monad[F]): F[(Either[Simulation[F], Unit], Seq[Event])] = { /* if !waiting.isEmpty // still waiting for responses! * then Monad[F].pure((Right(()), fatalError(s"Called `tick()` even though I am still waiting @@ -131,6 +201,13 @@ case class Simulation[F[_]]( object Simulation extends StateOps { type SimState[F[_]] = StateT[F, Simulation[F], Seq[Event]] + /** + * Initialize a simulation state with a name and [[Scheduler]]. + * + * @param id The name to use for the simulation. + * @param scheduler The [[Scheduler]] to use. + * @return The initialised [[Simulation]] state. + */ def apply[F[_]](id: String, scheduler: Scheduler): Simulation[F] = Simulation[F]( id, scheduler, @@ -143,35 +220,17 @@ object Simulation extends StateOps { HashSet() ) - def applyState[F[_] : Monad]( - r: Either[Simulation[F], Unit], - s: StateT[F, Simulation[F], Seq[Event]] - ): F[(Either[Simulation[F], Unit], Seq[Event])] = r match { - case Left(sim) => - for { - result <- s.run(sim) - (update, events) = result - } yield ((Left(update), events)) - case Right(u) => Monad[F].pure((r, Seq())) - } - - def inspectState[F[_] : Monad](f: Simulation[F] => Unit) = - StateT.inspect[F, Simulation[F], Seq[Event]](sim => { - f(sim) - Seq() - }) - /** * Start a [[CaseRef]]. * * Once the case starts, we expect to hear from it in case it wants to add some [[Task]]s. We * therefore add it to the waiting queue. * - * Publishes a [[com.workflowfm.proter.events.ESimStart ESimStart]]. + * Publishes a [[com.workflowfm.proter.events.ECaseStart ECaseStart]]. * - * @group simulations * @param caseRef * The [[CaseRef]] to start. + * @return The state update. */ def startCase[F[_]](caseRef: CaseRef[F]): State[Simulation[F], Event] = State(sim => ( @@ -184,18 +243,16 @@ object Simulation extends StateOps { ) /** - * Stops a case when it is done. + * Stops a [[CaseRef]] when it is done. * - * - Removes the simulation from the list of running simulations and the waiting list. - * - Removes any [[Lookahead]] from the [[schedule.Scheduler Scheduler]]. - * - Publishes a [[com.workflowfm.proter.events.ESimEnd ESimEnd]]. - * - Calls [[ready]] to handle the fact that we no longer need to wait for this simulation. + * - Removes it from the list of running cases and the waiting list. + * - Publishes a [[com.workflowfm.proter.events.ECaseEnd ECaseEnd]]. * - * @group simulations * @param name - * The name of the completed simulation. + * The name of the completed [[CaseRef]]. * @param result - * A string representation of the output of the simulation. + * A string representation of the resulting output of the case. + * @return The state update. */ def stopCase[F[_] : Monad](name: String, result: String): StateT[F, Simulation[F], Seq[Event]] = StateT { sim => @@ -214,23 +271,16 @@ object Simulation extends StateOps { // ready(name) /** - * Stops/aborts a simulation before it is done. - * - * - Removes the simulation from the list of running simulations and from the waiting list. - * - Detaches all tasks of the simulation from the resources and adds them to the abort list. - * - Publishes a [[com.workflowfm.proter.events.ETaskAbort ETaskAbort]] for each aborted task - * and associated [[com.workflowfm.proter.events.ETaskDetach ETaskDetach]] for each released - * resource. - * - Removes all queued tasks of the simulation from the scheduler. - * - Publishes a [[com.workflowfm.proter.events.ESimEnd ESimEnd]]. - * - Asks the simulation to stop. - * - Does '''not''' progress time. + * Stops/aborts a [[CaseRef]] before it is done. * - * The bookkeeping assumes the rest of the simulation(s) can still proceed. + * - Removes it from the list of running cases and from the waiting list. + * - Aborts and removes all tasks of the case. + * - Publishes a [[com.workflowfm.proter.events.ECaseEnd ECaseEnd]] with a "Simulation Aborted" result. + * - Tells the [[CaseRef]] to stop. * - * @group simulations - * @param simulation - * The [[Simulation]] to stop. + * @param caseRef + * The [[CaseRef]] to stop. + * @return The state update. */ def abortCase[F[_] : Applicative](caseRef: CaseRef[F]): StateT[F, Simulation[F], Seq[Event]] = StateT(sim => { @@ -251,10 +301,11 @@ object Simulation extends StateOps { }) /** - * Aborts all currently running simulations. + * Aborts all currently running cases. * - * Calls [[abortSimulation]] for each of them. - * @group simulations + * Calls [[abortCase]] for each of them. + * + * @return The state update. */ protected def abortAll[F[_] : Monad](): StateT[F, Simulation[F], Seq[Event]] = StateT(sim => { sim.cases.values.toSeq.traverse(abortCase[F]).map(_.flatten).run(sim) @@ -264,21 +315,20 @@ object Simulation extends StateOps { * Start a [[TaskInstance]] at the current timestamp. * * A [[TaskInstance]] is started when scheduled by the [[schedule.Scheduler Scheduler]]. This - * assumes all the [[TaskResource]]s it needs are available. + * assumes all the [[Resource]]s it needs are available. * * - Publishes a [[com.workflowfm.proter.events.ETaskAdd ETaskAdd]]. - * - Calls [[TaskResource.startTask]] for each involved [[TaskResource]] to attach this - * [[TaskInstance]] to them. Publishes a - * [[com.workflowfm.proter.events.ETaskAttach ETaskAttach]] for each successful attachment. + * - Calls [[ResourceMap.startTask]] to attach the task to its resources. + * - Produces an [[com.workflowfm.proter.events.ETaskAttach ETaskAttach]] event for each successful attachment. * Otherwise publishes an appropriate [[com.workflowfm.proter.events.EError EError]]. The * latter would only happen if the [[schedule.Scheduler Scheduler]] tried to schedule a - * [[Task]] to a busy [[TaskResource]]. + * [[Task]] to a [[Resource]] that is busy/does not have enough available capacity. * - Creates a [[FinishingTask]] event for this [[Task]] based on its duration, and adds it to - * the even queue. + * the event queue. * - * @group tasks * @param task * The [[TaskInstance]] to be started. + * @return The state update. */ def startTask[F[_]](task: TaskInstance): State[Simulation[F], Seq[Event]] = State(sim => sim.resources.startTask(task, sim.time) match { @@ -309,16 +359,16 @@ object Simulation extends StateOps { ) /** - * Aborts one or more [[TaskInstance]]s. + * Aborts one or more [[TaskInstance]]s by their IDs. * - * - Detaches all associated [[TaskResource]]s publishing a - * [[com.workflowfm.proter.events.ETaskDetach ETaskDetach]] each time. + * - Detaches all associated resources using [[ResourceMap.stopTasks]]. + * - Produces an [[com.workflowfm.proter.events.ETaskDetach ETaskDetach]] event for each resource. * - Adds the task ID to the [[abortedTasks]] set. - * - Publishes a [[com.workflowfm.proter.events.ETaskAbort ETaskAbort]]. + * - Produces an [[com.workflowfm.proter.events.ETaskAbort ETaskAbort]] event. * - * @group tasks - * @param id + * @param ids * The `UUID`s of the [[TaskInstance]]s that need to be aborted. + * @return The state update. */ def abortTasks[F[_]](ids: Seq[UUID]): State[Simulation[F], Seq[Event]] = State(sim => { val (abortMap, detached) = sim.resources.stopTasks(ids) @@ -331,20 +381,17 @@ object Simulation extends StateOps { }) /** - * Handles a group of [[TaskInstance]]s of the same simulation that has just finished. - * - * Assumes all instances belong to the same simulation. + * Handles a group of [[TaskInstance]]s that have just finished. * - * - Notifies the [[schedule.Scheduler Scheduler]] about each task comleting. - * - Publishes a [[com.workflowfm.proter.events.ETaskDone ETaskDone]]. - * - Notifies the [[Simulation]] that its [[TaskInstance]]s have finished. This happens in the - * same thread if `singleThread` is `true` or using a `Future` otherwise. + * - Ignore tasks that have been aborted already. + * - Detaches all associated resources using [[ResourceMap.stopTasks]]. + * - Produces an [[com.workflowfm.proter.events.ETaskDetach ETaskDetach]] event for each resource. + * - Produces an [[com.workflowfm.proter.events.ETaskDone ETaskDone]] event. + * - Adds the corresponding [[CaseRef]]s to the waiting list. * - * Note that resources are detached before this in [[tick]] using [[filterFinishingTasks]]. - * - * @group tasks - * @param taskGroup - * The simulation name paired with the [[TaskInstance]]s that need to be stopped. + * @param tasks + * The [[TaskInstance]]s that need to be stopped. + * @return The state update. */ def stopTasks[F[_]](tasks: Seq[TaskInstance]): State[Simulation[F], Seq[Event]] = State(sim => { val (someAbortedTasks, nonAbortedTasks) = tasks.partition(t => sim.abortedTasks.contains(t.id)) @@ -363,6 +410,13 @@ object Simulation extends StateOps { ) }) + /** + * Allocates and starts new [[TaskInstance]]s. + * + * New tasks are decided by the [[Scheduler]] given the resource availability. + * + * @return The state update. + */ def allocateTasks[F[_] : Monad](): StateT[F, Simulation[F], Seq[Event]] = StateT { sim => StateT .fromState( @@ -372,9 +426,16 @@ object Simulation extends StateOps { } /** - * Handles all [[DiscreteEvent]]s other than [[FinishingTask]]. + * Folding function to handle [[DiscreteEvent]]s * - * @param event + * For each event we compute the following 3 things: + * 1. A corresponding simulation state update. + * 1. A collection of completed [[TaskInstance]]s (from [[FinishingTask]] events). + * 1. A flag that becomes true if a terminating condition (e.g. time limit) has been met. + * + * @param acc The result accumulated from folding so far. + * @param event The next [[DiscreteEvent]] to handle. + * @return The 3 computed parts. */ protected def handleDiscreteEvent[F[_] : Monad]( acc: (StateT[F, Simulation[F], Queue[Event]], Queue[TaskInstance], Boolean), @@ -431,7 +492,7 @@ object Simulation extends StateOps { /** * Aborts all simulations and stops immediately. * - * @group toplevel + * @return The state update. */ def stop[F[_] : Monad](): StateT[F, Simulation[F], Seq[Event]] = abortAll() @@ -439,19 +500,25 @@ object Simulation extends StateOps { .flatMap { events => StateT.fromState(finish().map(e => Monad[F].pure(events ++ e))) } /** - * Shuts down the entire simulation and shuts down the actor. + * Indicates the simulation has completed. * * Publishes a [[com.workflowfm.proter.events.EDone EDone]]. * - * Fulfils the completion [[promise]]. - * - * @group toplevel + * @return The state update. */ def finish[F[_]](): State[Simulation[F], Seq[Event]] = State { sim => (sim, Seq(EDone(sim.id, sim.time))) // TODO do we want to mark the simulation as done? } - def unknownCase[F[_] : Monad](caseName: String): StateT[F, Simulation[F], Seq[Event]] = StateT { + /** + * Produces an [[EError]] indicating a [[CaseRef]] in the waiting list is unknown. + * + * @see [[notifyCase]] + * + * @param caseName The name of the [[CaseRef]] we were supposed to notify. + * @return The state update. + */ + def unknownCaseToNotify[F[_] : Monad](caseName: String): StateT[F, Simulation[F], Seq[Event]] = StateT { sim => Monad[F].pure( (sim.ready(caseName), Seq(sim.error(s"Skipping waiting for unknown case: $caseName"))) From db602f740c046b9cc9737d828aae7025b57922e3 Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Sun, 31 Jul 2022 15:14:48 +0100 Subject: [PATCH 08/31] Runs scalafmt --- .../com/workflowfm/proter/Resource.scala | 146 +++++---- .../com/workflowfm/proter/Scenario.scala | 299 ++++++++++-------- .../com/workflowfm/proter/Simulator.scala | 115 ++++--- .../scala/com/workflowfm/proter/Task.scala | 10 +- .../workflowfm/proter/state/CaseState.scala | 9 +- .../proter/state/ScenarioState.scala | 159 ++++++---- .../workflowfm/proter/state/Simulation.scala | 216 ++++++++----- 7 files changed, 574 insertions(+), 380 deletions(-) diff --git a/proter/src/main/scala/com/workflowfm/proter/Resource.scala b/proter/src/main/scala/com/workflowfm/proter/Resource.scala index 859eeea..0326119 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Resource.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Resource.scala @@ -9,10 +9,13 @@ import cats.implicits.* /** * A peristent resource that can be used for simulated tasks. - * - * @param name A unique name. - * @param capacity The resource capacity. - * @param costPerTick The cost of using 1 unit of resource capacity per unit of time. + * + * @param name + * A unique name. + * @param capacity + * The resource capacity. + * @param costPerTick + * The cost of using 1 unit of resource capacity per unit of time. */ case class Resource(name: String, capacity: Int, costPerTick: Double) { /** @@ -22,10 +25,13 @@ case class Resource(name: String, capacity: Int, costPerTick: Double) { /** * Calculates the cost of using certain units of capacity over a given time. - * - * @param actualDuration The duration to calculate. - * @param quantity The units of capacity to use. - * @return The calculated total cost. + * + * @param actualDuration + * The duration to calculate. + * @param quantity + * The units of capacity to use. + * @return + * The calculated total cost. */ def costOf(actualDuration: Long, quantity: Int): Double = costPerTick * actualDuration * quantity @@ -33,11 +39,14 @@ case class Resource(name: String, capacity: Int, costPerTick: Double) { /** * The state of a [[Resource]] during simulation. - * + * * Includes the [[TaskInstance]]s that are attached to the resource at a given time. - * - * @param resource The associated [[Resource]]. - * @param currentTasks A `Map` of attached [[TaskInstances]] paired with their starting times and indexed by their IDs. + * + * @param resource + * The associated [[Resource]]. + * @param currentTasks + * A `Map` of attached [[TaskInstances]] paired with their starting times and indexed by their + * IDs. */ case class ResourceState(resource: Resource, currentTasks: Map[UUID, (Long, TaskInstance)]) { @@ -69,9 +78,11 @@ case class ResourceState(resource: Resource, currentTasks: Map[UUID, (Long, Task /** * Detach a [[TaskInstance]] from the [[Resource]]. - * - * @param taskID The `UUID` of the task to detach. - * @return The [[DetachedTask]] or `None` if the ID was not found attached here. + * + * @param taskID + * The `UUID` of the task to detach. + * @return + * The [[DetachedTask]] or `None` if the ID was not found attached here. */ def detach(taskID: UUID): Option[DetachedTask] = currentTasks.get(taskID).map { (start, task) => @@ -84,20 +95,24 @@ case class ResourceState(resource: Resource, currentTasks: Map[UUID, (Long, Task /** * Checks if any task IDs in a given list are attached to this resource. - * - * @param taskIDs The IDs of the tasks we are interested in. - * @return True if any of the task IDs are attached to this resource. + * + * @param taskIDs + * The IDs of the tasks we are interested in. + * @return + * True if any of the task IDs are attached to this resource. */ def runningAnyOf(taskIDs: Seq[UUID]): Boolean = taskIDs.exists(id => currentTasks.contains(id)) /** * Reduces the capacity of the resource based on a given map of named resource quantities. - * + * * This is used when scheduling tasks which are not yet attached. - * - * @param A `Map` of resource names and quantities to reduce. - * @return The updated state. + * + * @param A + * `Map` of resource names and quantities to reduce. + * @return + * The updated state. */ def reduce(toReduce: Map[String, Int]): ResourceState = copy( @@ -111,16 +126,18 @@ case class ResourceState(resource: Resource, currentTasks: Map[UUID, (Long, Task object ResourceState { /** * Wrapper around a [[ResourceState]] that does not have enough capacity for some task. - * - * @param state The corresponding [[ResourceState]]. + * + * @param state + * The corresponding [[ResourceState]]. */ case class Full(state: ResourceState) } /** * A map of all simulated [[Resource]]s. - * - * @param resources A `Map` of [[Resource]] names to their [[ResourceState]]. + * + * @param resources + * A `Map` of [[Resource]] names to their [[ResourceState]]. */ case class ResourceMap(resources: Map[String, ResourceState]) { @@ -147,11 +164,14 @@ case class ResourceMap(resources: Map[String, ResourceState]) { /** * Attach a [[TaskInstance]] to all associated [[ReourceState]]s. - * - * @param task The [[TaskInstance]] to attach. - * @param time The current timestamp. - * @return The updated structure or a `Left` of a [[ResourceState.Full]] if any of the resources - * did not have enough capacity. + * + * @param task + * The [[TaskInstance]] to attach. + * @param time + * The current timestamp. + * @return + * The updated structure or a `Left` of a [[ResourceState.Full]] if any of the resources did + * not have enough capacity. */ def startTask(task: TaskInstance, time: Long): Either[ResourceState.Full, ResourceMap] = (for { @@ -163,9 +183,11 @@ case class ResourceMap(resources: Map[String, ResourceState]) { /** * Detach a [[TaskInstance]] from all associated [[ReourceState]]s. - * - * @param id The ID of the [[TaskInstance]] to detach. - * @return The updated structure paired with the resulting sequence of [[DetachedTask]]s. + * + * @param id + * The ID of the [[TaskInstance]] to detach. + * @return + * The updated structure paired with the resulting sequence of [[DetachedTask]]s. */ def stopTask(id: UUID): (ResourceMap, Seq[DetachedTask]) = { val stopping = resources.values @@ -179,9 +201,11 @@ case class ResourceMap(resources: Map[String, ResourceState]) { /** * Detach multiple [[TaskInstance]]s from all associated [[ReourceState]]s. - * - * @param ids The IDs of the [[TaskInstance]]s to detach. - * @return The updated structure paired with the resulting sequence of [[DetachedTask]]s. + * + * @param ids + * The IDs of the [[TaskInstance]]s to detach. + * @return + * The updated structure paired with the resulting sequence of [[DetachedTask]]s. */ def stopTasks(ids: Seq[UUID]): (ResourceMap, Seq[DetachedTask]) = { ids.foldLeft((this, Queue[DetachedTask]())) { @@ -199,11 +223,13 @@ case class ResourceMap(resources: Map[String, ResourceState]) { /** * Reduces the capacity of the resources based on a given map of named resource quantities. - * + * * This is used when scheduling tasks which are not yet attached. - * - * @param A `Map` of resource names and quantities to reduce. - * @return The updated resource map. + * + * @param A + * `Map` of resource names and quantities to reduce. + * @return + * The updated resource map. */ def reduce(toReduce: Map[String, Int]): ResourceMap = // TODO improve to only go through selected resources @@ -222,9 +248,11 @@ case class ResourceMap(resources: Map[String, ResourceState]) { /** * Checks if the available resources have enough capacity to run a given [[TaskInstance]]. - * - * @param task The [[TaskInstance]] at hand. - * @return True if the task can be handled by the current resources. + * + * @param task + * The [[TaskInstance]] at hand. + * @return + * True if the task can be handled by the current resources. */ def canHandle(task: TaskInstance): Boolean = task.resources.forall { (r, q) => @@ -233,18 +261,22 @@ case class ResourceMap(resources: Map[String, ResourceState]) { /** * Retrieves the remaining capacity of a named resource. - * - * @param name The name of the resource to check. - * @return The current capacity. + * + * @param name + * The name of the resource to check. + * @return + * The current capacity. */ def remainingCapacityOf(name: String): Int = resources.get(name).map(_.remainingCapacity).getOrElse(0) /** * Retrieves the total capacity of a named resource. - * - * @param name The name of the resource to check. - * @return Its total capacity. + * + * @param name + * The name of the resource to check. + * @return + * Its total capacity. */ def capacityOf(name: String): Int = resources.get(name).map(_.resource.capacity).getOrElse(0) } @@ -257,10 +289,14 @@ object ResourceMap { } /** - * A structure of a [[TaskInstance]] that has been detached and the corresponding [[ResourceState]]. - * - * @param start The timestamp when the task was attached originally. - * @param task The detached [[TaskKInstance]]. - * @param resource The updated [[ResourceState]]. + * A structure of a [[TaskInstance]] that has been detached and the corresponding + * [[ResourceState]]. + * + * @param start + * The timestamp when the task was attached originally. + * @param task + * The detached [[TaskKInstance]]. + * @param resource + * The updated [[ResourceState]]. */ final case class DetachedTask(start: Long, task: TaskInstance, resource: ResourceState) diff --git a/proter/src/main/scala/com/workflowfm/proter/Scenario.scala b/proter/src/main/scala/com/workflowfm/proter/Scenario.scala index 740b68c..87cf0ab 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Scenario.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Scenario.scala @@ -13,16 +13,19 @@ import state.* /** * Convenience class to construct simulation scenarios. - * - * Provides various functions to set simulation parameters and compile them in - * a [[Simulation.SimState]]. - * + * + * Provides various functions to set simulation parameters and compile them in a + * [[Simulation.SimState]]. + * * Parameters include resources, cases/arrivals, and start and ending times. - * - * @note Ordering of method calls matters, especially when using [[withStartingTime]]. - * - * @param A name to identify the scenario. - * @param The current simulation state update corresponding to the parameters provided so far. + * + * @note + * Ordering of method calls matters, especially when using [[withStartingTime]]. + * + * @param A + * name to identify the scenario. + * @param The + * current simulation state update corresponding to the parameters provided so far. */ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState[F]) extends ScenarioState @@ -32,104 +35,127 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState /** * Composes another simulation state update directly. - * - * @param s The `SimState` to compose. - * @return The updated scenario. + * + * @param s + * The `SimState` to compose. + * @return + * The updated scenario. */ def and(s: SimState[F]): Scenario[F] = copy(state = compose2(state, s)) /** * Adds a [[Resource]] to the simulation scenario. - * - * @param r The [[Resource]] to add. - * @return The updated scenario. + * + * @param r + * The [[Resource]] to add. + * @return + * The updated scenario. */ def withResource(r: Resource): Scenario[F] = and(lift(addResource(r))) /** * Adds a collection of [[Resource]]s to the simulation scenario. - * - * @param rs The [[Resource]]s to add. - * @return The updated scenario. + * + * @param rs + * The [[Resource]]s to add. + * @return + * The updated scenario. */ def withResources(rs: Seq[Resource]): Scenario[F] = and(lift(addResources(rs))) /** * Adds a [[Case]] to the simulation scenario. - * - * The case will be scheduled to start in the '''current''' start time - * of the scenario. - * + * + * The case will be scheduled to start in the '''current''' start time of the scenario. + * * Manipulating the scenario start time ''after'' adding the case may have unintended effects, - * such as having a case start time in the past. - * - * @tparam T The type of the object used for the simulation case. - * @param n A unique name for the case. - * @param t The object to use for the simulation case. - * @return The updated scenario. + * such as having a case start time in the past. + * + * @tparam T + * The type of the object used for the simulation case. + * @param n + * A unique name for the case. + * @param t + * The object to use for the simulation case. + * @return + * The updated scenario. */ def withCase[T](n: String, t: T)(using ct: Case[F, T]): Scenario[F] = and(addCaseNow(n, t)) /** * Adds a [[Case]] with a specified starting time to the simulation scenario. - * - * @tparam T The type of the object used for the simulation case. - * @param n A unique name for the case. - * @param time The timestamp when the case should start. - * @param t The object to use for the simulation case. - * @return The updated scenario. + * + * @tparam T + * The type of the object used for the simulation case. + * @param n + * A unique name for the case. + * @param time + * The timestamp when the case should start. + * @param t + * The object to use for the simulation case. + * @return + * The updated scenario. */ def withTimedCase[T](n: String, time: Long, t: T)(using ct: Case[F, T]): Scenario[F] = and(addCase(time, n, t)) /** * Adds a collectiion of [[Case]]s to the simulation scenario. - * - * The cases will be scheduled to start in the '''current''' start time - * of the scenario. - * + * + * The cases will be scheduled to start in the '''current''' start time of the scenario. + * * Manipulating the scenario start time ''after'' adding the cases may have unintended effects, - * such as having a case start time in the past. - * - * @tparam T The type of the objects used for the simulation cases. - * @param cases The objects to use for each simulation case, - * each paired with its own unique name. - * @return The updated scenario. + * such as having a case start time in the past. + * + * @tparam T + * The type of the objects used for the simulation cases. + * @param cases + * The objects to use for each simulation case, each paired with its own unique name. + * @return + * The updated scenario. */ def withCases[T](cases: (String, T)*)(using ct: Case[F, T]): Scenario[F] = and(addCasesNow(cases)) /** - * Adds a collection of [[Case]]s, each with a specified starting time, to the simulation scenario. - * - * @tparam T The type of the objects used for the simulation case. - * @param cases The objects to use for the simulation case, - * each paired with its own unique name and starting timestamp. - * @return The updated scenario. + * Adds a collection of [[Case]]s, each with a specified starting time, to the simulation + * scenario. + * + * @tparam T + * The type of the objects used for the simulation case. + * @param cases + * The objects to use for the simulation case, each paired with its own unique name and + * starting timestamp. + * @return + * The updated scenario. */ def withTimedCases[T](cases: (Long, String, T)*)(using ct: Case[F, T]): Scenario[F] = and(addCases(cases)) /** * Adds a [[Case]] with an arrival pattern to the simulation scenario. - * - * The first case will be scheduled to arrive in the '''current''' start time - * of the scenario. - * + * + * The first case will be scheduled to arrive in the '''current''' start time of the scenario. + * * Manipulating the scenario start time ''after'' adding the cases may have unintended effects, - * such as having a case start time in the past. - * - * @tparam T The type of the object used for the simulation case. - * @param n A unique name for the cases. - * @param t The object to use for the simulation case. - * @param rate The probability ditribution determining the duration until the - * next arrival. - * @param limit The maximum number of cases to generate. - * @return The updated scenario. + * such as having a case start time in the past. + * + * @tparam T + * The type of the object used for the simulation case. + * @param n + * A unique name for the cases. + * @param t + * The object to use for the simulation case. + * @param rate + * The probability ditribution determining the duration until the next arrival. + * @param limit + * The maximum number of cases to generate. + * @return + * The updated scenario. */ def withArrival[T]( n: String, @@ -141,15 +167,21 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState /** * Adds a [[Case]] with an arrival pattern and specified start time to the simulation scenario. - * - * @tparam T The type of the object used for the simulation case. - * @param n A unique name for the cases. - * @param time The timestamp when the first case should arrive. - * @param t The object to use for the simulation case. - * @param rate The probability ditribution determining the duration until the - * next arrival. - * @param limit The maximum number of cases to generate. - * @return The updated scenario. + * + * @tparam T + * The type of the object used for the simulation case. + * @param n + * A unique name for the cases. + * @param time + * The timestamp when the first case should arrive. + * @param t + * The object to use for the simulation case. + * @param rate + * The probability ditribution determining the duration until the next arrival. + * @param limit + * The maximum number of cases to generate. + * @return + * The updated scenario. */ def withTimedArrival[T]( n: String, @@ -162,23 +194,27 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState /** * Adds a [[Case]] with an infinite arrival pattern to the simulation scenario. - * - * The first case will be scheduled to arrive in the '''current''' start time - * of the scenario. - * + * + * The first case will be scheduled to arrive in the '''current''' start time of the scenario. + * * Manipulating the scenario start time ''after'' adding the cases may have unintended effects, * such as having a case start time in the past. - * + * * The scenario will continue to generate cases infinitely until the time limit has been reached. - * - * @see [[withLimit]] - * - * @tparam T The type of the object used for the simulation case. - * @param n A unique name for the cases. - * @param t The object to use for the simulation case. - * @param rate The probability ditribution determining the duration until the - * next arrival. - * @return The updated scenario. + * + * @see + * [[withLimit]] + * + * @tparam T + * The type of the object used for the simulation case. + * @param n + * A unique name for the cases. + * @param t + * The object to use for the simulation case. + * @param rate + * The probability ditribution determining the duration until the next arrival. + * @return + * The updated scenario. */ def withInfiniteArrival[T]( n: String, @@ -189,18 +225,24 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState /** * Adds a [[Case]] with an infinite arrival pattern and specified start time. - * + * * The scenario will continue to generate cases infinitely until the time limit has been reached. - * - * @see [[withLimit]] - * - * @tparam T The type of the object used for the simulation case. - * @param n A unique name for the cases. - * @param time The timestamp when the first case should arrive. - * @param t The object to use for the simulation case. - * @param rate The probability ditribution determining the duration until the - * next arrival. - * @return The updated scenario. + * + * @see + * [[withLimit]] + * + * @tparam T + * The type of the object used for the simulation case. + * @param n + * A unique name for the cases. + * @param time + * The timestamp when the first case should arrive. + * @param t + * The object to use for the simulation case. + * @param rate + * The probability ditribution determining the duration until the next arrival. + * @return + * The updated scenario. */ def withTimedInfiniteArrival[T]( n: String, @@ -212,35 +254,39 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState /** * Sets a time limit for the simulation. - * + * * All running cases will be aborted at that timestamp and the simulation will stop. - * - * Calling this method multiple times will result in the earliest timestamp becoming the - * time limit. - * + * + * Calling this method multiple times will result in the earliest timestamp becoming the time + * limit. + * * Setting the time limit after the start time will result in an error. - * - * @param t The timestamp to use as the time limit. - * @return The updated scenario. + * + * @param t + * The timestamp to use as the time limit. + * @return + * The updated scenario. */ def withLimit(t: Long): Scenario[F] = and(lift(limit(t))) /** * Sets the start time for the simulation. - * - * This will be the first timestamp in the simulation. Cases with no specified - * start time will start at the time set here. - * + * + * This will be the first timestamp in the simulation. Cases with no specified start time will + * start at the time set here. + * * Setting the start time after some cases are already scheduled will result in an error. - * + * * Calling this method multiple times will result in the timestamp given in the last call * becoming the start time. - * + * * Setting the start time after the time limit will result in an error. - * - * @param t The timestamp to use as the start time. - * @return The updated scenario. + * + * @param t + * The timestamp to use as the start time. + * @return + * The updated scenario. */ def withStartingTime(t: Long): Scenario[F] = and(StateT(sim => Monad[F].pure((sim.copy(time = t), Seq())))) @@ -249,21 +295,26 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState object Scenario extends StateOps { /** * Initialise a scenario by its name. - * - * @param name The name to use for the scenario. - * @return An empty scenario. + * + * @param name + * The name to use for the scenario. + * @return + * An empty scenario. */ def apply[F[_] : Monad](name: String): Scenario[F] = Scenario(name, idState) /** * Initialise a scenario by its name and start time. - * - * Using this as a constructor is preferred as it reduces the chance of - * misusing `withStartingTime`. - * - * @param name The name to use for the scenario. - * @param start The timestamp to use as the start time. - * @return An empty scenario. + * + * Using this as a constructor is preferred as it reduces the chance of misusing + * `withStartingTime`. + * + * @param name + * The name to use for the scenario. + * @param start + * The timestamp to use as the start time. + * @return + * An empty scenario. */ def apply[F[_] : Monad](name: String, start: Long): Scenario[F] = Scenario(name).withStartingTime(start) diff --git a/proter/src/main/scala/com/workflowfm/proter/Simulator.scala b/proter/src/main/scala/com/workflowfm/proter/Simulator.scala index e5206a0..e08a47a 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Simulator.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Simulator.scala @@ -15,71 +15,88 @@ import cats.effect.implicits.* /** * Runs simulations. - * - * @param scheduler The [[Scheduler]] to use during simulation. - * @param subscribers The [[Subscriber]]s that should receive events. + * + * @param scheduler + * The [[Scheduler]] to use during simulation. + * @param subscribers + * The [[Subscriber]]s that should receive events. */ final case class Simulator[F[_] : Concurrent]( scheduler: Scheduler, subscribers: Seq[Subscriber[F]] ) extends ScenarioState { - /** - * Updates the [[Scheduler]] to be used during simulation. - * - * @param s The new [[Scheduler]]. - * @return The updated simulator. + /** + * Updates the [[Scheduler]] to be used during simulation. + * + * @param s + * The new [[Scheduler]]. + * @return + * The updated simulator. */ def withScheduler(s: Scheduler): Simulator[F] = copy(scheduler = s) - /** + /** * Updates to using a single [[Subscriber]]. - * - * @param sub The new [[Subscriber]]. - * @return The updated simulator. + * + * @param sub + * The new [[Subscriber]]. + * @return + * The updated simulator. */ def withSub(sub: Subscriber[F]): Simulator[F] = copy(subscribers = Seq(sub)) - /** + /** * Updates to using new [[Subscriber]]s. - * - * @param subs The new [[Subscriber]]s. - * @return The updated simulator. + * + * @param subs + * The new [[Subscriber]]s. + * @return + * The updated simulator. */ def withSubs(subs: Subscriber[F]*): Simulator[F] = copy(subscribers = subs) - /** + /** * Adds additional [[Subscriber]]s. - * - * @param subs The new [[Subscriber]]s to add. - * @return The updated simulator. + * + * @param subs + * The new [[Subscriber]]s to add. + * @return + * The updated simulator. */ def and(subs: Subscriber[F]*): Simulator[F] = copy(subscribers = subscribers ++ subs) - /** + /** * Simulates a [[Scenario]]. - * - * @param scenario The [[Scenario]] to simulate. - * @return An effect producing `Unit` when the simulation finishes. + * + * @param scenario + * The [[Scenario]] to simulate. + * @return + * An effect producing `Unit` when the simulation finishes. */ def simulate(scenario: Scenario[F]): F[Unit] = simulateState(scenario.name, scenario.state) - /** + /** * Simulates a [[Scenario]] and streams the [[Event]]s. - * - * @param scenario The [[Scenario]] to simulate. - * @return A stream of [[Event]]s or `Throwable` errors. + * + * @param scenario + * The [[Scenario]] to simulate. + * @return + * A stream of [[Event]]s or `Throwable` errors. */ def stream(scenario: Scenario[F]): Stream[F, Either[Throwable, Event]] = streamState(scenario.name, scenario.state) - /** + /** * Runs a simulation from a given [[Simulation.SimState]]. - * - * @param name A name to use for the simulation. - * @param state The starting state. - * @return An effect producing `Unit` when the simulation finishes. + * + * @param name + * A name to use for the simulation. + * @param state + * The starting state. + * @return + * An effect producing `Unit` when the simulation finishes. */ def simulateState(name: String, state: StateT[F, Simulation[F], Seq[Event]]): F[Unit] = for { publisher <- Publisher.build[F]() @@ -93,12 +110,15 @@ final case class Simulator[F[_] : Concurrent]( } } yield (()) - /** + /** * Runs and streams a simulation from a given [[Simulation.SimState]]. - * - * @param name A name to use for the simulation. - * @param state The starting state. - * @return A stream of [[Event]]s or `Throwable` errors. + * + * @param name + * A name to use for the simulation. + * @param state + * The starting state. + * @return + * A stream of [[Event]]s or `Throwable` errors. */ def streamState( name: String, @@ -118,15 +138,19 @@ final case class Simulator[F[_] : Concurrent]( } yield (stream)) .flatten - /** + /** * Runs a [[Simulation.SimState]] with a given [[Publisher]]. - * + * * Subscribers should be handled externally. We are only publishing here. - * - * @param name A name to use for the simulation. - * @param state The starting state. - * @param publisher The [[Publisher]] to use. - * @return An effect producing `Unit` when the simulation finishes.. + * + * @param name + * A name to use for the simulation. + * @param state + * The starting state. + * @param publisher + * The [[Publisher]] to use. + * @return + * An effect producing `Unit` when the simulation finishes.. */ def simulateStateWithPublisher( name: String, @@ -158,4 +182,3 @@ object Simulator { def apply[F[_] : Concurrent](scheduler: Scheduler): Simulator[F] = Simulator(scheduler, Seq()) } - diff --git a/proter/src/main/scala/com/workflowfm/proter/Task.scala b/proter/src/main/scala/com/workflowfm/proter/Task.scala index de7c23a..7a8a204 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Task.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Task.scala @@ -11,13 +11,13 @@ import cats.implicits.* * @note * We expect that task instances are only generated through a [[Task]]. * - * The samples of the parameters are generated during simulation. The duration can be - * specified through random sampling in a [[Distribution]]. We store the estimated value as well as - * the actual sampled value. + * The samples of the parameters are generated during simulation. The duration can be specified + * through random sampling in a [[Distribution]]. We store the estimated value as well as the + * actual sampled value. * * @param id - * A unique id that separates this task from any other task. A case may spawn multiple tasks - * with the same name, so this is necessary. + * A unique id that separates this task from any other task. A case may spawn multiple tasks with + * the same name, so this is necessary. * @param name * A descriptive name. * @param caseName diff --git a/proter/src/main/scala/com/workflowfm/proter/state/CaseState.scala b/proter/src/main/scala/com/workflowfm/proter/state/CaseState.scala index aa26f12..9e0fa46 100644 --- a/proter/src/main/scala/com/workflowfm/proter/state/CaseState.scala +++ b/proter/src/main/scala/com/workflowfm/proter/state/CaseState.scala @@ -54,7 +54,8 @@ trait CaseState extends ScenarioState { /** * Adds a collection of new [[Task]]s. * - * @see [[addTask]] + * @see + * [[addTask]] * * @group tasks * @param caseName @@ -73,7 +74,8 @@ trait CaseState extends ScenarioState { /** * Aborts a list of [[TaskInstance]]s by their IDs. * - * @see [[Simulation.abortTasks]] + * @see + * [[Simulation.abortTasks]] * * @group tasks * @param ids @@ -87,7 +89,8 @@ trait CaseState extends ScenarioState { /** * Updates the simulation with a completed [[CaseRef]]. * - * @see [[Simulation.stopCase]] + * @see + * [[Simulation.stopCase]] * * @group cases * @param caseName diff --git a/proter/src/main/scala/com/workflowfm/proter/state/ScenarioState.scala b/proter/src/main/scala/com/workflowfm/proter/state/ScenarioState.scala index 6cebde6..313a665 100644 --- a/proter/src/main/scala/com/workflowfm/proter/state/ScenarioState.scala +++ b/proter/src/main/scala/com/workflowfm/proter/state/ScenarioState.scala @@ -22,11 +22,13 @@ trait ScenarioState { /** * Adds a [[Resource]] to the simulation. - * + * * Produces an [[EResourceAdd]] event. - * - * @param r The [[Resource]] to add. - * @return The state update. + * + * @param r + * The [[Resource]] to add. + * @return + * The state update. */ def addResource[F[_]](r: Resource): State[Simulation[F], Seq[Event]] = State(sim => ( @@ -37,11 +39,13 @@ trait ScenarioState { /** * Adds a collection of [[Resource]]s to the simulation. - * + * * Produces an [[EResourceAdd]] event for each resource. - * - * @param rs The [[Resource]]s to add. - * @return The state update. + * + * @param rs + * The [[Resource]]s to add. + * @return + * The state update. */ def addResources[F[_]](rs: Seq[Resource]): State[Simulation[F], Seq[Event]] = State(sim => { val events = rs.map { r => EResourceAdd(sim.id, sim.time, r) } @@ -50,12 +54,14 @@ trait ScenarioState { /** * Adds a [[CaseRef]] to the simulation. - * + * * Produces an [[ECaseAdd]] event. - * - * @param t The timestamp when the case needs to start. Must be greater or equal to the current - * simulation time. - * @return The state update. + * + * @param t + * The timestamp when the case needs to start. Must be greater or equal to the current + * simulation time. + * @return + * The state update. */ def addCaseRef[F[_]](t: Long, caseRef: CaseRef[F]): State[Simulation[F], Seq[Event]] = State(sim => @@ -69,15 +75,20 @@ trait ScenarioState { /** * Adds a [[Case]] to the simulation. - * + * * Produces an [[ECaseAdd]] event. - * - * @tparam T The type of the object used for the simulation case. - * @param time The timestamp when the case needs to start. Must be greater or equal to the current - * simulation time. - * @param name A unique name for the case. - * @param t The object to use for the simulation case. - * @return The state update. + * + * @tparam T + * The type of the object used for the simulation case. + * @param time + * The timestamp when the case needs to start. Must be greater or equal to the current + * simulation time. + * @param name + * A unique name for the case. + * @param t + * The object to use for the simulation case. + * @return + * The state update. */ def addCase[F[_] : Monad, T](time: Long, name: String, t: T)( using ct: Case[F, T] @@ -94,13 +105,17 @@ trait ScenarioState { /** * Adds a [[Case]] to be run in the '''current''' simulation time. - * + * * Produces an [[ECaseAdd]] event. - * - * @tparam T The type of the object used for the simulation case. - * @param name A unique name for the case. - * @param t The object to use for the simulation case. - * @return The state update. + * + * @tparam T + * The type of the object used for the simulation case. + * @param name + * A unique name for the case. + * @param t + * The object to use for the simulation case. + * @return + * The state update. */ def addCaseNow[F[_] : Monad, T](name: String, t: T)( using ct: Case[F, T] @@ -109,13 +124,16 @@ trait ScenarioState { /** * Adds a collection of [[Case]]s to the simulation. - * + * * Produces an [[ECaseAdd]] event for each case added. - * - * @tparam T The type of the object used for the simulation case. - * @param cases The objects to use for each simulation case, - * each paired with its own unique name and starting timestamp. - * @return The state update. + * + * @tparam T + * The type of the object used for the simulation case. + * @param cases + * The objects to use for each simulation case, each paired with its own unique name and + * starting timestamp. + * @return + * The state update. */ def addCases[F[_] : Monad, T](cases: Seq[(Long, String, T)])( using ct: Case[F, T] @@ -124,13 +142,15 @@ trait ScenarioState { /** * Adds a collection of [[Case]]s to be run in the '''current''' simulation time. - * + * * Produces an [[ECaseAdd]] event for each case added. - * - * @tparam T The type of the object used for the simulation case. - * @param cases The objects to use for each simulation case, - * each paired with its own unique name. - * @return The state update. + * + * @tparam T + * The type of the object used for the simulation case. + * @param cases + * The objects to use for each simulation case, each paired with its own unique name. + * @return + * The state update. */ def addCasesNow[F[_] : Monad, T](cases: Seq[(String, T)])( using ct: Case[F, T] @@ -139,17 +159,23 @@ trait ScenarioState { /** * Adds a [[Case]] with an arrival pattern to the simulation. - * + * * Produces an [[EArrivalAdd]] event. - * - * @tparam T The type of the object used for the simulation cases. - * @param t The timestamp when the first case should arrive. - * @param name A unique name for the cases. - * @param item The object to use for the simulation case. - * @param rate The probability ditribution determining the duration until the - * next arrival. - * @param limit An optional maximum number of cases to generate. - * @return The state update. + * + * @tparam T + * The type of the object used for the simulation cases. + * @param t + * The timestamp when the first case should arrive. + * @param name + * A unique name for the cases. + * @param item + * The object to use for the simulation case. + * @param rate + * The probability ditribution determining the duration until the next arrival. + * @param limit + * An optional maximum number of cases to generate. + * @return + * The state update. */ def addArrival[F[_] : Monad : Random, T]( t: Long, @@ -174,16 +200,21 @@ trait ScenarioState { /** * Adds a [[Case]] with an arrival pattern to start in the '''current''' simulation time. - * + * * Produces an [[EArrivalAdd]] event. - * - * @tparam T The type of the object used for the simulation cases. - * @param name A unique name for the cases. - * @param item The object to use for the simulation case. - * @param rate The probability ditribution determining the duration until the - * next arrival. - * @param limit An optional maximum number of cases to generate. - * @return The state update. + * + * @tparam T + * The type of the object used for the simulation cases. + * @param name + * A unique name for the cases. + * @param item + * The object to use for the simulation case. + * @param rate + * The probability ditribution determining the duration until the next arrival. + * @param limit + * An optional maximum number of cases to generate. + * @return + * The state update. */ def addArrivalNow[F[_] : Monad : Random, T]( name: String, @@ -199,15 +230,17 @@ trait ScenarioState { * Sets a time limit for the simulation. * * Produces an [[ETimeLimit]] event. - * + * * @note * Once a time limit is placed it cannot be removed. Multiple time limits can be set so that * the earliest one will be triggered. - * + * * Setting the time limit after the start time will result in an error. - * - * @param t The timestamp to use as the time limit. - * @return The state update. + * + * @param t + * The timestamp to use as the time limit. + * @return + * The state update. */ def limit[F[_]](t: Long): State[Simulation[F], Seq[Event]] = State(sim => if t >= sim.time then diff --git a/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala b/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala index 639f587..69308b1 100644 --- a/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala +++ b/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala @@ -17,17 +17,26 @@ import java.util.UUID /** * A simulation state. - * - * @param id A name for the entire simulation. - * @param scheduler The [[Scheduler]] being used. - * @param time The current time. - * @param events The [[EventQueue]] of pending discrete events. - * @param tasks Current running [[TaskInstance]]s. - * @param cases Indexed map of currently running [[CaseRef]]s. - * @param resources The [[ResourceMap]] of the resources used in the simulation. - * @param waiting Indexed map of [[CaseRef]] names and corresponding finished tasks (if any) - * from which we are expecting a response. - * @param abortedTasks Set of [[TaskInstance]]s that have been aborted. + * + * @param id + * A name for the entire simulation. + * @param scheduler + * The [[Scheduler]] being used. + * @param time + * The current time. + * @param events + * The [[EventQueue]] of pending discrete events. + * @param tasks + * Current running [[TaskInstance]]s. + * @param cases + * Indexed map of currently running [[CaseRef]]s. + * @param resources + * The [[ResourceMap]] of the resources used in the simulation. + * @param waiting + * Indexed map of [[CaseRef]] names and corresponding finished tasks (if any) from which we are + * expecting a response. + * @param abortedTasks + * Set of [[TaskInstance]]s that have been aborted. */ case class Simulation[F[_]]( id: String, @@ -41,53 +50,62 @@ case class Simulation[F[_]]( abortedTasks: HashSet[UUID] ) { - /** * Convenience method to produce an [[EError]] event. - * - * @param description A description of the error that occurred. - * @return An [[EError]] event. + * + * @param description + * A description of the error that occurred. + * @return + * An [[EError]] event. */ def error(description: String): EError = EError(id, time, description) /** * Convenience method to produce an [[EError]] event, followed by [[EDone]]. - * + * * Essentially tells the event stream that the simulation has completed after the error, * i.e. that the error was unrecoverable. - * - * @param description A description of the error that occurred. - * @return The generated sequence of 2 events. + * + * @param description + * A description of the error that occurred. + * @return + * The generated sequence of 2 events. */ def fatalError(description: String): Seq[Event] = Seq(EError(id, time, description), EDone(id, time)) /** * Removes a [[CaseRef]] name from the waiting list. - * - * @param description A description of the error that occurred. - * @return An [[EError]] event. + * + * @param description + * A description of the error that occurred. + * @return + * An [[EError]] event. */ def ready(name: String): Simulation[F] = copy(waiting = waiting - name) - /** - * Uses the [[Scheduler]] to compute the next [[TaskInstance]]s to run based on resource availability. - * - * @param description A description of the error that occurred. - * @return An [[EError]] event. + * Uses the [[Scheduler]] to compute the next [[TaskInstance]]s to run based on resource + * availability. + * + * @param description + * A description of the error that occurred. + * @return + * An [[EError]] event. */ def nextTasks(): Iterable[TaskInstance] = scheduler.getNextTasks(time, tasks, resources) /** * Yields a state change from a [[CaseRef]]. - * - * This happens when we are waiting from a response from the [[CaseRef]], either because - * it has just started or because one or more of its [[TaskInstance]]s has completed. - * - * @param waiting The name of the [[CaseRef]] to notify, paired with a sequence of completed - * [[TaskInstance]]s or an empty sequence if the case just started. - * @return The state update produced by the [[CaseRef]]. + * + * This happens when we are waiting from a response from the [[CaseRef]], either because it has + * just started or because one or more of its [[TaskInstance]]s has completed. + * + * @param waiting + * The name of the [[CaseRef]] to notify, paired with a sequence of completed [[TaskInstance]]s + * or an empty sequence if the case just started. + * @return + * The state update produced by the [[CaseRef]]. */ def notifyCase(waiting: (String, Seq[TaskInstance]))(using Monad[F]): F[Simulation.SimState[F]] = waiting match { @@ -100,23 +118,27 @@ case class Simulation[F[_]]( /** * Notifies all [[CaseRef]]s in the waiting list. - * - * @see [[notifyCase]] - * + * + * @see + * [[notifyCase]] + * * Composes and applies all state updates produced by all notified [[CaseRef]]s. - * - * @return The updated simulation state and produced [[Event]]s. + * + * @return + * The updated simulation state and produced [[Event]]s. */ def notifyCases(using Monad[F]): F[(Simulation[F], Seq[Event])] = waiting.map(notifyCase).toSeq.sequence.map(Simulation.compose(_: _*).run(this)).flatten /** * Starts the simulation with an initial state update. - * + * * Produces an [[EStart]] event. - * - * @param state The state update to apply. - * @return The updated state and produced [[Event]]s. + * + * @param state + * The state update to apply. + * @return + * The updated state and produced [[Event]]s. */ def start( state: StateT[F, Simulation[F], Seq[Event]] @@ -131,7 +153,7 @@ case class Simulation[F[_]]( /** * Progresses the simulation time. - * + * * This is the main simulation cycle: * 1. Finish with an [[EDone]] if no events, tasks, or cases remain. * 1. Pop the next group of discrete events in the queue. @@ -139,9 +161,12 @@ case class Simulation[F[_]]( * 1. Stop any tasks that completed ysing [[Simulation.stopTasks]]. * 1. Notify the cases that need to be notified with [[notifyCases]]. * 1. Allocate new tasks to the resources using [[Simulation.allocateTasks]]. - * 1. Terminate the simulation using [[Simulation.stop()]] if a termination condition (e.g. time limit) has been met. - * - * @return Either the updated state or `Unit` if the simulation terminated, and any produced [[Event]]s. + * 1. Terminate the simulation using [[Simulation.stop()]] if a termination condition (e.g. + * time limit) has been met. + * + * @return + * Either the updated state or `Unit` if the simulation terminated, and any produced + * [[Event]]s. */ def tick(using Monad[F]): F[(Either[Simulation[F], Unit], Seq[Event])] = { /* if !waiting.isEmpty // still waiting for responses! @@ -201,12 +226,15 @@ case class Simulation[F[_]]( object Simulation extends StateOps { type SimState[F[_]] = StateT[F, Simulation[F], Seq[Event]] - /** + /** * Initialize a simulation state with a name and [[Scheduler]]. - * - * @param id The name to use for the simulation. - * @param scheduler The [[Scheduler]] to use. - * @return The initialised [[Simulation]] state. + * + * @param id + * The name to use for the simulation. + * @param scheduler + * The [[Scheduler]] to use. + * @return + * The initialised [[Simulation]] state. */ def apply[F[_]](id: String, scheduler: Scheduler): Simulation[F] = Simulation[F]( id, @@ -230,7 +258,8 @@ object Simulation extends StateOps { * * @param caseRef * The [[CaseRef]] to start. - * @return The state update. + * @return + * The state update. */ def startCase[F[_]](caseRef: CaseRef[F]): State[Simulation[F], Event] = State(sim => ( @@ -252,7 +281,8 @@ object Simulation extends StateOps { * The name of the completed [[CaseRef]]. * @param result * A string representation of the resulting output of the case. - * @return The state update. + * @return + * The state update. */ def stopCase[F[_] : Monad](name: String, result: String): StateT[F, Simulation[F], Seq[Event]] = StateT { sim => @@ -275,12 +305,14 @@ object Simulation extends StateOps { * * - Removes it from the list of running cases and from the waiting list. * - Aborts and removes all tasks of the case. - * - Publishes a [[com.workflowfm.proter.events.ECaseEnd ECaseEnd]] with a "Simulation Aborted" result. + * - Publishes a [[com.workflowfm.proter.events.ECaseEnd ECaseEnd]] with a "Simulation Aborted" + * result. * - Tells the [[CaseRef]] to stop. * * @param caseRef * The [[CaseRef]] to stop. - * @return The state update. + * @return + * The state update. */ def abortCase[F[_] : Applicative](caseRef: CaseRef[F]): StateT[F, Simulation[F], Seq[Event]] = StateT(sim => { @@ -304,8 +336,9 @@ object Simulation extends StateOps { * Aborts all currently running cases. * * Calls [[abortCase]] for each of them. - * - * @return The state update. + * + * @return + * The state update. */ protected def abortAll[F[_] : Monad](): StateT[F, Simulation[F], Seq[Event]] = StateT(sim => { sim.cases.values.toSeq.traverse(abortCase[F]).map(_.flatten).run(sim) @@ -319,16 +352,18 @@ object Simulation extends StateOps { * * - Publishes a [[com.workflowfm.proter.events.ETaskAdd ETaskAdd]]. * - Calls [[ResourceMap.startTask]] to attach the task to its resources. - * - Produces an [[com.workflowfm.proter.events.ETaskAttach ETaskAttach]] event for each successful attachment. - * Otherwise publishes an appropriate [[com.workflowfm.proter.events.EError EError]]. The - * latter would only happen if the [[schedule.Scheduler Scheduler]] tried to schedule a - * [[Task]] to a [[Resource]] that is busy/does not have enough available capacity. + * - Produces an [[com.workflowfm.proter.events.ETaskAttach ETaskAttach]] event for each + * successful attachment. Otherwise publishes an appropriate + * [[com.workflowfm.proter.events.EError EError]]. The latter would only happen if the + * [[schedule.Scheduler Scheduler]] tried to schedule a [[Task]] to a [[Resource]] that is + * busy/does not have enough available capacity. * - Creates a [[FinishingTask]] event for this [[Task]] based on its duration, and adds it to * the event queue. * * @param task * The [[TaskInstance]] to be started. - * @return The state update. + * @return + * The state update. */ def startTask[F[_]](task: TaskInstance): State[Simulation[F], Seq[Event]] = State(sim => sim.resources.startTask(task, sim.time) match { @@ -362,13 +397,15 @@ object Simulation extends StateOps { * Aborts one or more [[TaskInstance]]s by their IDs. * * - Detaches all associated resources using [[ResourceMap.stopTasks]]. - * - Produces an [[com.workflowfm.proter.events.ETaskDetach ETaskDetach]] event for each resource. + * - Produces an [[com.workflowfm.proter.events.ETaskDetach ETaskDetach]] event for each + * resource. * - Adds the task ID to the [[abortedTasks]] set. * - Produces an [[com.workflowfm.proter.events.ETaskAbort ETaskAbort]] event. * * @param ids * The `UUID`s of the [[TaskInstance]]s that need to be aborted. - * @return The state update. + * @return + * The state update. */ def abortTasks[F[_]](ids: Seq[UUID]): State[Simulation[F], Seq[Event]] = State(sim => { val (abortMap, detached) = sim.resources.stopTasks(ids) @@ -385,13 +422,15 @@ object Simulation extends StateOps { * * - Ignore tasks that have been aborted already. * - Detaches all associated resources using [[ResourceMap.stopTasks]]. - * - Produces an [[com.workflowfm.proter.events.ETaskDetach ETaskDetach]] event for each resource. + * - Produces an [[com.workflowfm.proter.events.ETaskDetach ETaskDetach]] event for each + * resource. * - Produces an [[com.workflowfm.proter.events.ETaskDone ETaskDone]] event. * - Adds the corresponding [[CaseRef]]s to the waiting list. * * @param tasks * The [[TaskInstance]]s that need to be stopped. - * @return The state update. + * @return + * The state update. */ def stopTasks[F[_]](tasks: Seq[TaskInstance]): State[Simulation[F], Seq[Event]] = State(sim => { val (someAbortedTasks, nonAbortedTasks) = tasks.partition(t => sim.abortedTasks.contains(t.id)) @@ -412,10 +451,11 @@ object Simulation extends StateOps { /** * Allocates and starts new [[TaskInstance]]s. - * + * * New tasks are decided by the [[Scheduler]] given the resource availability. - * - * @return The state update. + * + * @return + * The state update. */ def allocateTasks[F[_] : Monad](): StateT[F, Simulation[F], Seq[Event]] = StateT { sim => StateT @@ -432,10 +472,13 @@ object Simulation extends StateOps { * 1. A corresponding simulation state update. * 1. A collection of completed [[TaskInstance]]s (from [[FinishingTask]] events). * 1. A flag that becomes true if a terminating condition (e.g. time limit) has been met. - * - * @param acc The result accumulated from folding so far. - * @param event The next [[DiscreteEvent]] to handle. - * @return The 3 computed parts. + * + * @param acc + * The result accumulated from folding so far. + * @param event + * The next [[DiscreteEvent]] to handle. + * @return + * The 3 computed parts. */ protected def handleDiscreteEvent[F[_] : Monad]( acc: (StateT[F, Simulation[F], Queue[Event]], Queue[TaskInstance], Boolean), @@ -492,7 +535,8 @@ object Simulation extends StateOps { /** * Aborts all simulations and stops immediately. * - * @return The state update. + * @return + * The state update. */ def stop[F[_] : Monad](): StateT[F, Simulation[F], Seq[Event]] = abortAll() @@ -504,7 +548,8 @@ object Simulation extends StateOps { * * Publishes a [[com.workflowfm.proter.events.EDone EDone]]. * - * @return The state update. + * @return + * The state update. */ def finish[F[_]](): State[Simulation[F], Seq[Event]] = State { sim => (sim, Seq(EDone(sim.id, sim.time))) // TODO do we want to mark the simulation as done? @@ -512,17 +557,20 @@ object Simulation extends StateOps { /** * Produces an [[EError]] indicating a [[CaseRef]] in the waiting list is unknown. - * - * @see [[notifyCase]] - * - * @param caseName The name of the [[CaseRef]] we were supposed to notify. - * @return The state update. + * + * @see + * [[notifyCase]] + * + * @param caseName + * The name of the [[CaseRef]] we were supposed to notify. + * @return + * The state update. */ - def unknownCaseToNotify[F[_] : Monad](caseName: String): StateT[F, Simulation[F], Seq[Event]] = StateT { - sim => + def unknownCaseToNotify[F[_] : Monad](caseName: String): StateT[F, Simulation[F], Seq[Event]] = + StateT { sim => Monad[F].pure( (sim.ready(caseName), Seq(sim.error(s"Skipping waiting for unknown case: $caseName"))) ) - } + } } From 0171e1f4f7d5b11ddc3f9ab0554d2183a7f939fb Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Sun, 31 Jul 2022 15:49:22 +0100 Subject: [PATCH 09/31] Fixes all scaladoc cross-link issues --- .../com/workflowfm/proter/DiscreteEvent.scala | 6 +- .../com/workflowfm/proter/Resource.scala | 10 +- .../com/workflowfm/proter/Scenario.scala | 24 ++--- .../com/workflowfm/proter/Simulator.scala | 34 +++---- .../proter/events/EventHandler.scala | 4 +- .../com/workflowfm/proter/flows/Flow.scala | 6 +- .../workflowfm/proter/metrics/Metrics.scala | 24 ++--- .../proter/metrics/MetricsOutput.scala | 12 +-- .../proter/metrics/MetricsSubscriber.scala | 4 +- .../proter/schedule/Scheduler.scala | 2 +- .../workflowfm/proter/state/CaseState.scala | 21 +++-- .../proter/state/ScenarioState.scala | 34 +++---- .../workflowfm/proter/state/Simulation.scala | 94 ++++++++++--------- 13 files changed, 136 insertions(+), 139 deletions(-) diff --git a/proter/src/main/scala/com/workflowfm/proter/DiscreteEvent.scala b/proter/src/main/scala/com/workflowfm/proter/DiscreteEvent.scala index e0ae729..24cc92d 100644 --- a/proter/src/main/scala/com/workflowfm/proter/DiscreteEvent.scala +++ b/proter/src/main/scala/com/workflowfm/proter/DiscreteEvent.scala @@ -79,7 +79,7 @@ case class FinishingTask(override val time: Long, task: TaskInstance) extends Di * @param time * The timestamp of the event * @param caseRef - * The [[CaseRef]] that needs to start. + * The [[cases.CaseRef CaseRef]] that needs to start. */ case class StartingCase[F[_]](override val time: Long, caseRef: CaseRef[F]) extends DiscreteEvent { override val classOrder: Short = 10 @@ -141,10 +141,10 @@ case class Arrival[F[_] : Monad : Random, T]( } /** - * Generates the next arrival event to be queued and [[CaseRef]] to add. + * Generates the next arrival event to be queued and [[cases.CaseRef CaseRef]] to add. * * @return - * The next arrival event and [[CaseRef]], unless the limit is reached. + * The next arrival event and [[cases.CaseRef CaseRef]], unless the limit is reached. */ def next(): Option[F[(Arrival[F, T], CaseRef[F])]] = limit.filter(_ <= count) match { case None => diff --git a/proter/src/main/scala/com/workflowfm/proter/Resource.scala b/proter/src/main/scala/com/workflowfm/proter/Resource.scala index 0326119..1730925 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Resource.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Resource.scala @@ -45,7 +45,7 @@ case class Resource(name: String, capacity: Int, costPerTick: Double) { * @param resource * The associated [[Resource]]. * @param currentTasks - * A `Map` of attached [[TaskInstances]] paired with their starting times and indexed by their + * A `Map` of attached [[TaskInstance]]s paired with their starting times and indexed by their * IDs. */ case class ResourceState(resource: Resource, currentTasks: Map[UUID, (Long, TaskInstance)]) { @@ -163,7 +163,7 @@ case class ResourceMap(resources: Map[String, ResourceState]) { copy(resources ++ (resourcesToAdd.map { r => r.name -> r.start })) /** - * Attach a [[TaskInstance]] to all associated [[ReourceState]]s. + * Attach a [[TaskInstance]] to all associated [[ResourceState]]s. * * @param task * The [[TaskInstance]] to attach. @@ -182,7 +182,7 @@ case class ResourceMap(resources: Map[String, ResourceState]) { )).toSeq.sequence.map { stateUpdates => copy(resources = resources ++ stateUpdates) } /** - * Detach a [[TaskInstance]] from all associated [[ReourceState]]s. + * Detach a [[TaskInstance]] from all associated [[ResourceState]]s. * * @param id * The ID of the [[TaskInstance]] to detach. @@ -200,7 +200,7 @@ case class ResourceMap(resources: Map[String, ResourceState]) { } /** - * Detach multiple [[TaskInstance]]s from all associated [[ReourceState]]s. + * Detach multiple [[TaskInstance]]s from all associated [[ResourceState]]s. * * @param ids * The IDs of the [[TaskInstance]]s to detach. @@ -295,7 +295,7 @@ object ResourceMap { * @param start * The timestamp when the task was attached originally. * @param task - * The detached [[TaskKInstance]]. + * The detached [[TaskInstance]]. * @param resource * The updated [[ResourceState]]. */ diff --git a/proter/src/main/scala/com/workflowfm/proter/Scenario.scala b/proter/src/main/scala/com/workflowfm/proter/Scenario.scala index 87cf0ab..994f013 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Scenario.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Scenario.scala @@ -15,7 +15,7 @@ import state.* * Convenience class to construct simulation scenarios. * * Provides various functions to set simulation parameters and compile them in a - * [[Simulation.SimState]]. + * [[state.Simulation.SimState SimState]]. * * Parameters include resources, cases/arrivals, and start and ending times. * @@ -37,7 +37,7 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState * Composes another simulation state update directly. * * @param s - * The `SimState` to compose. + * The [[state.Simulation.SimState SimState]] to compose. * @return * The updated scenario. */ @@ -67,7 +67,7 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState and(lift(addResources(rs))) /** - * Adds a [[Case]] to the simulation scenario. + * Adds a [[cases.Case Case]] to the simulation scenario. * * The case will be scheduled to start in the '''current''' start time of the scenario. * @@ -87,7 +87,7 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState and(addCaseNow(n, t)) /** - * Adds a [[Case]] with a specified starting time to the simulation scenario. + * Adds a [[cases.Case Case]] with a specified starting time to the simulation scenario. * * @tparam T * The type of the object used for the simulation case. @@ -104,7 +104,7 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState and(addCase(time, n, t)) /** - * Adds a collectiion of [[Case]]s to the simulation scenario. + * Adds a collectiion of [[cases.Case Case]]s to the simulation scenario. * * The cases will be scheduled to start in the '''current''' start time of the scenario. * @@ -122,7 +122,7 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState and(addCasesNow(cases)) /** - * Adds a collection of [[Case]]s, each with a specified starting time, to the simulation + * Adds a collection of [[cases.Case Case]]s, each with a specified starting time, to the simulation * scenario. * * @tparam T @@ -137,7 +137,7 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState and(addCases(cases)) /** - * Adds a [[Case]] with an arrival pattern to the simulation scenario. + * Adds a [[cases.Case Case]] with an arrival pattern to the simulation scenario. * * The first case will be scheduled to arrive in the '''current''' start time of the scenario. * @@ -166,7 +166,7 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState and(addArrivalNow(n, t, rate, Some(limit))) /** - * Adds a [[Case]] with an arrival pattern and specified start time to the simulation scenario. + * Adds a [[cases.Case Case]] with an arrival pattern and specified start time to the simulation scenario. * * @tparam T * The type of the object used for the simulation case. @@ -193,7 +193,7 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState and(addArrival(time, n, t, rate, Some(limit))) /** - * Adds a [[Case]] with an infinite arrival pattern to the simulation scenario. + * Adds a [[cases.Case Case]] with an infinite arrival pattern to the simulation scenario. * * The first case will be scheduled to arrive in the '''current''' start time of the scenario. * @@ -203,7 +203,7 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState * The scenario will continue to generate cases infinitely until the time limit has been reached. * * @see - * [[withLimit]] + * [[Scenario.withLimit]] * * @tparam T * The type of the object used for the simulation case. @@ -224,12 +224,12 @@ final case class Scenario[F[_] : Monad](name: String, state: Simulation.SimState and(addArrivalNow(n, t, rate, None)) /** - * Adds a [[Case]] with an infinite arrival pattern and specified start time. + * Adds a [[cases.Case Case]] with an infinite arrival pattern and specified start time. * * The scenario will continue to generate cases infinitely until the time limit has been reached. * * @see - * [[withLimit]] + * [[Scenario.withLimit]] * * @tparam T * The type of the object used for the simulation case. diff --git a/proter/src/main/scala/com/workflowfm/proter/Simulator.scala b/proter/src/main/scala/com/workflowfm/proter/Simulator.scala index e08a47a..43a1a3f 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Simulator.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Simulator.scala @@ -17,9 +17,9 @@ import cats.effect.implicits.* * Runs simulations. * * @param scheduler - * The [[Scheduler]] to use during simulation. + * The [[schedule.Scheduler Scheduler]] to use during simulation. * @param subscribers - * The [[Subscriber]]s that should receive events. + * The [[events.Subscriber Subscriber]]s that should receive events. */ final case class Simulator[F[_] : Concurrent]( scheduler: Scheduler, @@ -27,40 +27,40 @@ final case class Simulator[F[_] : Concurrent]( ) extends ScenarioState { /** - * Updates the [[Scheduler]] to be used during simulation. + * Updates the [[schedule.Scheduler Scheduler]] to be used during simulation. * * @param s - * The new [[Scheduler]]. + * The new [[schedule.Scheduler Scheduler]]. * @return * The updated simulator. */ def withScheduler(s: Scheduler): Simulator[F] = copy(scheduler = s) /** - * Updates to using a single [[Subscriber]]. + * Updates to using a single [[events.Subscriber Subscriber]]. * * @param sub - * The new [[Subscriber]]. + * The new [[events.Subscriber Subscriber]]. * @return * The updated simulator. */ def withSub(sub: Subscriber[F]): Simulator[F] = copy(subscribers = Seq(sub)) /** - * Updates to using new [[Subscriber]]s. + * Updates to using new [[events.Subscriber Subscriber]]s. * * @param subs - * The new [[Subscriber]]s. + * The new [[events.Subscriber Subscriber]]s. * @return * The updated simulator. */ def withSubs(subs: Subscriber[F]*): Simulator[F] = copy(subscribers = subs) /** - * Adds additional [[Subscriber]]s. + * Adds additional [[events.Subscriber Subscriber]]s. * * @param subs - * The new [[Subscriber]]s to add. + * The new [[events.Subscriber Subscriber]]s to add. * @return * The updated simulator. */ @@ -78,18 +78,18 @@ final case class Simulator[F[_] : Concurrent]( simulateState(scenario.name, scenario.state) /** - * Simulates a [[Scenario]] and streams the [[Event]]s. + * Simulates a [[Scenario]] and streams the [[events.Event Event]]s. * * @param scenario * The [[Scenario]] to simulate. * @return - * A stream of [[Event]]s or `Throwable` errors. + * A stream of [[events.Event Event]]s or `Throwable` errors. */ def stream(scenario: Scenario[F]): Stream[F, Either[Throwable, Event]] = streamState(scenario.name, scenario.state) /** - * Runs a simulation from a given [[Simulation.SimState]]. + * Runs a simulation from a given [[state.Simulation.SimState SimState]]. * * @param name * A name to use for the simulation. @@ -111,14 +111,14 @@ final case class Simulator[F[_] : Concurrent]( } yield (()) /** - * Runs and streams a simulation from a given [[Simulation.SimState]]. + * Runs and streams a simulation from a given [[state.Simulation.SimState SimState]]. * * @param name * A name to use for the simulation. * @param state * The starting state. * @return - * A stream of [[Event]]s or `Throwable` errors. + * A stream of [[events.Event Event]]s or `Throwable` errors. */ def streamState( name: String, @@ -139,7 +139,7 @@ final case class Simulator[F[_] : Concurrent]( .flatten /** - * Runs a [[Simulation.SimState]] with a given [[Publisher]]. + * Runs a [[state.Simulation.SimState SimState]] with a given [[events.Publisher Publisher]]. * * Subscribers should be handled externally. We are only publishing here. * @@ -148,7 +148,7 @@ final case class Simulator[F[_] : Concurrent]( * @param state * The starting state. * @param publisher - * The [[Publisher]] to use. + * The [[events.Publisher Publisher]] to use. * @return * An effect producing `Unit` when the simulation finishes.. */ diff --git a/proter/src/main/scala/com/workflowfm/proter/events/EventHandler.scala b/proter/src/main/scala/com/workflowfm/proter/events/EventHandler.scala index 1ea5500..77b82ba 100644 --- a/proter/src/main/scala/com/workflowfm/proter/events/EventHandler.scala +++ b/proter/src/main/scala/com/workflowfm/proter/events/EventHandler.scala @@ -102,7 +102,7 @@ object CountEvents { * Listens for the end of a specific case and handles its result. * * @param name - * The name of the [[CaseRef]] to listen for. + * The name of the [[cases.CaseRef CaseRef]] to listen for. * @param result * The deferred result output from the case. */ @@ -112,7 +112,7 @@ class GetCaseResult[F[_] : Monad](caseName: String, result: Deferred[F, String]) /** * @inheritdoc * - * If the event is [[ESimEnd]] and the simulation name matches then we record the case result. + * If the event is [[ECaseEnd]] and the simulation name matches then we record the case result. */ override def onEvent(evt: Event): F[Unit] = evt match { case ECaseEnd(_, _, n, r) if n == caseName => { diff --git a/proter/src/main/scala/com/workflowfm/proter/flows/Flow.scala b/proter/src/main/scala/com/workflowfm/proter/flows/Flow.scala index cad74e7..e74ea00 100644 --- a/proter/src/main/scala/com/workflowfm/proter/flows/Flow.scala +++ b/proter/src/main/scala/com/workflowfm/proter/flows/Flow.scala @@ -113,7 +113,7 @@ object Flow { } /** - * A [[CaseRef]] for a [[Flow]]. + * A [[cases.CaseRef CaseRef]] for a [[Flow]]. * * It uses a [[Flow]] structure which describes how and in what order certain tasks should be * executed. A Flow may consist of a single [[FlowTask]] or some combination of [[FlowTask]]s which @@ -124,7 +124,7 @@ object Flow { * @param flow * The flow which describes how the case should behave. * @param callbackMap - * The map of callbacks for an extended [[AsyncCaseRef]] implementation. + * The map of callbacks for an extended [[cases.AsyncCaseRef AsyncCaseRef]] implementation. */ case class FlowCaseRef[F[_] : Monad : UUIDGen : Random]( override val caseName: String, @@ -147,7 +147,7 @@ case class FlowCaseRef[F[_] : Monad : UUIDGen : Random]( /** * Completes an id by executing its callback and then removing it from the map. * - * This overloads the definition of `complete` found in [[AsynCaseRef]] to allow for ''any''' id + * This overloads the definition of `complete` found in [[cases.AsyncCaseRef AsyncCaseRef]] to allow for ''any''' id * to be used in the `tasks` map, and not just [[TaskInstance]]s. * * @param id diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala index 58cc43d..ababcd8 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala @@ -9,17 +9,11 @@ import events.* /** * Collects/aggregates metrics across multiple tasks, resources, and cases. * - * @groupprio Values - * 1 - * @groupprio Start/End - * 2 - * @groupprio Set - * 3 - * @groupprio Update - * 4 - * @groupprio Get - * 5 - * + * @groupprio Start/End 2 + * @groupprio Set 3 + * @groupprio Update 4 + * @groupprio Get 5 + * * @param start * The system time in milliseconds when the simulation started. * @param end @@ -123,7 +117,7 @@ final case class Metrics( this += ResourceMetrics(t, r) /** - * Adds a new [[MetricsException]]. + * Adds a new [[Metrics.MetricsException MetricsException]]. * * @group Set */ @@ -256,7 +250,7 @@ final case class Metrics( def taskSet: Set[String] = tasks.values.map(_.task).toSet[String] /** - * All the tracked [[TaskMetrics]] instances associated with a [[TaskResource]], sorted by + * All the tracked [[TaskMetrics]] instances associated with a [[Resource]], sorted by * starting time. * * @param r @@ -272,14 +266,14 @@ final case class Metrics( * Returns all the tracked instances of [[TaskMetrics]] associated with a particular simulation, * sorted by starting time. * @param r - * the tracked [[SimulationMetrics]] of the resource + * The tracked [[TaskMetrics]] related to the resource. * @group Get */ def taskMetricsOf(s: CaseMetrics): Seq[TaskMetrics] = tasks.values.toSeq.filter(_.caseName.equals(s.name)).sortBy(_.started) /** - * Convert [[Event]]s to metrics updates. + * Convert [[events.Event Event]]s to metrics updates. */ def handle(evt: Event): Metrics = evt match { case EStart(_, t) => this.started(t).updateAllResources(_.start(t)) diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsOutput.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsOutput.scala index 8cf0dd8..21310ca 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsOutput.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsOutput.scala @@ -117,12 +117,12 @@ trait MetricsStringOutput[F[_]] extends MetricsOutput[F] { * String representation of a [[TaskMetrics]] instance. * * @param separator - * A string (such as a space or comma) to separate the values + * A string (such as a space or comma) to separate the values. * @param resSeparator - * A string (such as a space or comma) to separate the list of names of [[TaskResource]]s in - * [[TaskMetrics]] + * A string (such as a space or comma) to separate the list of names of [[Resource]]s in + * [[TaskMetrics]]. * @param m - * the [[TaskMetrics]] instance to be handled + * The [[TaskMetrics]] instance to be handled. */ def taskCSV(separator: String, resSeparator: String)(m: TaskMetrics): String = m match { case TaskMetrics(id, task, sim, priority, ct, st, dur, cost, res, aborted) => @@ -151,12 +151,12 @@ trait MetricsStringOutput[F[_]] extends MetricsOutput[F] { Seq("Name", "Start", "Duration", "Delay", "Tasks", "Cost", "Result").mkString(separator) /** - * String representation of a [[SimulationMetrics]] instance. + * String representation of a [[CaseMetrics]] instance. * * @param separator * A string (such as a space or comma) to separate the values * @param m - * the [[SimulationMetrics]] instance to be handled + * The [[CaseMetrics]] instance to be handled. */ def caseCSV(separator: String)(m: CaseMetrics): String = m match { case CaseMetrics(name, st, dur, delay, ts, c, res) => diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsSubscriber.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsSubscriber.scala index ced7f39..664bc06 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsSubscriber.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsSubscriber.scala @@ -8,7 +8,7 @@ import fs2.Stream import events.{ Event, Subscriber } /** - * A [[Subscriber]] that compiles and outputs [[Metrics]]. + * A [[events.Subscriber Subscriber]] that compiles and outputs [[Metrics]]. * * Runs all outputs concurrently. * @@ -29,7 +29,7 @@ final case class MetricsParSubscriber[F[_] : Concurrent](outputs: MetricsOutput[ } /** - * A [[Subscriber]] that compiles and outputs [[Metrics]]. + * A [[events.Subscriber Subscriber]] that compiles and outputs [[Metrics]]. * * Runs all outputs in sequence. * diff --git a/proter/src/main/scala/com/workflowfm/proter/schedule/Scheduler.scala b/proter/src/main/scala/com/workflowfm/proter/schedule/Scheduler.scala index 9962c8c..13d6d1a 100644 --- a/proter/src/main/scala/com/workflowfm/proter/schedule/Scheduler.scala +++ b/proter/src/main/scala/com/workflowfm/proter/schedule/Scheduler.scala @@ -18,7 +18,7 @@ trait Scheduler { * @param currentTime * The current timestamp. * @param resourceMap - * The map of available [[TaskResource]]s. + * The [[ResourceMap]] of available resources. * @return * The sequence of [[TaskInstance]]s to start now. */ diff --git a/proter/src/main/scala/com/workflowfm/proter/state/CaseState.scala b/proter/src/main/scala/com/workflowfm/proter/state/CaseState.scala index 9e0fa46..eab6a31 100644 --- a/proter/src/main/scala/com/workflowfm/proter/state/CaseState.scala +++ b/proter/src/main/scala/com/workflowfm/proter/state/CaseState.scala @@ -16,7 +16,7 @@ import scala.util.{ Try, Success, Failure } import java.util.UUID /** - * Includes simulation state updates required when executing a [[Case]]/[[CaseRef]]. + * Includes simulation state updates required when executing a [[cases.CaseRef CaseRef]]. */ trait CaseState extends ScenarioState { @@ -26,11 +26,12 @@ trait CaseState extends ScenarioState { * - Uses [[Task.create]] to create a [[TaskInstance]], which will now have a fixed duration * and cost. * - Publishes a [[com.workflowfm.proter.events.ETaskAdd ETaskAdd]]. - * - If the task does not require any resources, it is started immediately using [[startTask]]. + * - If the task does not require any resources, it is started immediately using + * [[Simulation.startTask]]. * * @group tasks * @param caseName - * The name of the [[CaseRef]] that owns the task. + * The name of the [[cases.CaseRef CaseRef]] that owns the task. * @param task * The [[Task]] to be added. * @return @@ -59,7 +60,7 @@ trait CaseState extends ScenarioState { * * @group tasks * @param caseName - * The name of the [[CaseRef]] that owns the task. + * The name of the [[cases.CaseRef CaseRef]] that owns the task. * @param tasks * The [[Task]]s to be added. * @return @@ -87,16 +88,16 @@ trait CaseState extends ScenarioState { Simulation.abortTasks(ids) /** - * Updates the simulation with a completed [[CaseRef]]. + * Updates the simulation with a completed [[cases.CaseRef CaseRef]]. * * @see * [[Simulation.stopCase]] * * @group cases * @param caseName - * The name of the [[CaseRef]]. + * The name of the [[cases.CaseRef CaseRef]]. * @param result - * The result produced by the completed [[CaseRef]]. + * The result produced by the completed [[cases.CaseRef CaseRef]]. * @return * The state update. */ @@ -115,13 +116,13 @@ trait CaseState extends ScenarioState { } /** - * Updates a [[CaseRef]]. + * Updates a [[cases.CaseRef CaseRef]]. * * @group cases * @param caseName - * The name of the [[CaseRef]]. + * The name of the [[cases.CaseRef CaseRef]]. * @param c - * The new [[CaseRef]] reflecting the new state of the case. + * The new [[cases.CaseRef CaseRef]] reflecting the new state of the case. * @return * The state update. */ diff --git a/proter/src/main/scala/com/workflowfm/proter/state/ScenarioState.scala b/proter/src/main/scala/com/workflowfm/proter/state/ScenarioState.scala index 313a665..2fa9c3f 100644 --- a/proter/src/main/scala/com/workflowfm/proter/state/ScenarioState.scala +++ b/proter/src/main/scala/com/workflowfm/proter/state/ScenarioState.scala @@ -23,7 +23,7 @@ trait ScenarioState { /** * Adds a [[Resource]] to the simulation. * - * Produces an [[EResourceAdd]] event. + * Produces an [[events.EResourceAdd EResourceAdd]] event. * * @param r * The [[Resource]] to add. @@ -40,7 +40,7 @@ trait ScenarioState { /** * Adds a collection of [[Resource]]s to the simulation. * - * Produces an [[EResourceAdd]] event for each resource. + * Produces an [[events.EResourceAdd EResourceAdd]] event for each resource. * * @param rs * The [[Resource]]s to add. @@ -53,9 +53,9 @@ trait ScenarioState { }) /** - * Adds a [[CaseRef]] to the simulation. + * Adds a [[cases.CaseRef CaseRef]] to the simulation. * - * Produces an [[ECaseAdd]] event. + * Produces an [[events.ECaseAdd ECaseAdd]] event. * * @param t * The timestamp when the case needs to start. Must be greater or equal to the current @@ -74,9 +74,9 @@ trait ScenarioState { ) /** - * Adds a [[Case]] to the simulation. + * Adds a [[cases.Case Case]] to the simulation. * - * Produces an [[ECaseAdd]] event. + * Produces an [[events.ECaseAdd ECaseAdd]] event. * * @tparam T * The type of the object used for the simulation case. @@ -104,9 +104,9 @@ trait ScenarioState { ) /** - * Adds a [[Case]] to be run in the '''current''' simulation time. + * Adds a [[cases.Case Case]] to be run in the '''current''' simulation time. * - * Produces an [[ECaseAdd]] event. + * Produces an [[events.ECaseAdd ECaseAdd]] event. * * @tparam T * The type of the object used for the simulation case. @@ -123,9 +123,9 @@ trait ScenarioState { StateT.inspect[F, Simulation[F], Long](_.time).flatMap { time => addCase(time, name, t) } /** - * Adds a collection of [[Case]]s to the simulation. + * Adds a collection of [[cases.Case Case]]s to the simulation. * - * Produces an [[ECaseAdd]] event for each case added. + * Produces an [[events.ECaseAdd ECaseAdd]] event for each case added. * * @tparam T * The type of the object used for the simulation case. @@ -141,9 +141,9 @@ trait ScenarioState { cases.map((t, n, c) => addCase(t, n, c)).sequence.map(_.flatten) /** - * Adds a collection of [[Case]]s to be run in the '''current''' simulation time. + * Adds a collection of [[cases.Case Case]]s to be run in the '''current''' simulation time. * - * Produces an [[ECaseAdd]] event for each case added. + * Produces an [[events.ECaseAdd ECaseAdd]] event for each case added. * * @tparam T * The type of the object used for the simulation case. @@ -158,9 +158,9 @@ trait ScenarioState { cases.map((n, c) => addCaseNow(n, c)).sequence.map(_.flatten) /** - * Adds a [[Case]] with an arrival pattern to the simulation. + * Adds a [[cases.Case Case]] with an arrival pattern to the simulation. * - * Produces an [[EArrivalAdd]] event. + * Produces an [[events.EArrivalAdd EArrivalAdd]] event. * * @tparam T * The type of the object used for the simulation cases. @@ -199,9 +199,9 @@ trait ScenarioState { ) /** - * Adds a [[Case]] with an arrival pattern to start in the '''current''' simulation time. + * Adds a [[cases.Case Case]] with an arrival pattern to start in the '''current''' simulation time. * - * Produces an [[EArrivalAdd]] event. + * Produces an [[events.EArrivalAdd EArrivalAdd]] event. * * @tparam T * The type of the object used for the simulation cases. @@ -229,7 +229,7 @@ trait ScenarioState { /** * Sets a time limit for the simulation. * - * Produces an [[ETimeLimit]] event. + * Produces an [[events.ETimeLimit ETimeLimit]] event. * * @note * Once a time limit is placed it cannot be removed. Multiple time limits can be set so that diff --git a/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala b/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala index 69308b1..59aaade 100644 --- a/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala +++ b/proter/src/main/scala/com/workflowfm/proter/state/Simulation.scala @@ -21,7 +21,7 @@ import java.util.UUID * @param id * A name for the entire simulation. * @param scheduler - * The [[Scheduler]] being used. + * The [[schedule.Scheduler Scheduler]] being used. * @param time * The current time. * @param events @@ -29,12 +29,12 @@ import java.util.UUID * @param tasks * Current running [[TaskInstance]]s. * @param cases - * Indexed map of currently running [[CaseRef]]s. + * Indexed map of currently running [[cases.CaseRef CaseRef]]s. * @param resources * The [[ResourceMap]] of the resources used in the simulation. * @param waiting - * Indexed map of [[CaseRef]] names and corresponding finished tasks (if any) from which we are - * expecting a response. + * Indexed map of [[cases.CaseRef CaseRef]] names and corresponding finished tasks (if any) from + * which we are expecting a response. * @param abortedTasks * Set of [[TaskInstance]]s that have been aborted. */ @@ -51,17 +51,18 @@ case class Simulation[F[_]]( ) { /** - * Convenience method to produce an [[EError]] event. + * Convenience method to produce an [[events.EError EError]] event. * * @param description * A description of the error that occurred. * @return - * An [[EError]] event. + * An [[events.EError EError]] event. */ def error(description: String): EError = EError(id, time, description) /** - * Convenience method to produce an [[EError]] event, followed by [[EDone]]. + * Convenience method to produce an [[events.EError EError]] event, followed by + * [[events.EDone EDone]]. * * Essentially tells the event stream that the simulation has completed after the error, * i.e. that the error was unrecoverable. @@ -75,37 +76,37 @@ case class Simulation[F[_]]( Seq(EError(id, time, description), EDone(id, time)) /** - * Removes a [[CaseRef]] name from the waiting list. + * Removes a [[cases.CaseRef CaseRef]] name from the waiting list. * * @param description * A description of the error that occurred. * @return - * An [[EError]] event. + * An [[events.EError EError]] event. */ def ready(name: String): Simulation[F] = copy(waiting = waiting - name) /** - * Uses the [[Scheduler]] to compute the next [[TaskInstance]]s to run based on resource - * availability. + * Uses the [[schedule.Scheduler Scheduler]] to compute the next [[TaskInstance]]s to run based + * on resource availability. * * @param description * A description of the error that occurred. * @return - * An [[EError]] event. + * An [[events.EError EError]] event. */ def nextTasks(): Iterable[TaskInstance] = scheduler.getNextTasks(time, tasks, resources) /** - * Yields a state change from a [[CaseRef]]. + * Yields a state change from a [[cases.CaseRef CaseRef]]. * - * This happens when we are waiting from a response from the [[CaseRef]], either because it has - * just started or because one or more of its [[TaskInstance]]s has completed. + * This happens when we are waiting from a response from the [[cases.CaseRef CaseRef]], either + * because it has just started or because one or more of its [[TaskInstance]]s has completed. * * @param waiting - * The name of the [[CaseRef]] to notify, paired with a sequence of completed [[TaskInstance]]s - * or an empty sequence if the case just started. + * The name of the [[cases.CaseRef CaseRef]] to notify, paired with a sequence of completed + * [[TaskInstance]]s or an empty sequence if the case just started. * @return - * The state update produced by the [[CaseRef]]. + * The state update produced by the [[cases.CaseRef CaseRef]]. */ def notifyCase(waiting: (String, Seq[TaskInstance]))(using Monad[F]): F[Simulation.SimState[F]] = waiting match { @@ -117,15 +118,15 @@ case class Simulation[F[_]]( } /** - * Notifies all [[CaseRef]]s in the waiting list. + * Notifies all [[cases.CaseRef CaseRef]]s in the waiting list. * * @see - * [[notifyCase]] + * [[Simulation.notifyCase notifyCase]] * - * Composes and applies all state updates produced by all notified [[CaseRef]]s. + * Composes and applies all state updates produced by all notified [[cases.CaseRef CaseRef]]s. * * @return - * The updated simulation state and produced [[Event]]s. + * The updated simulation state and produced [[events.Event Event]]s. */ def notifyCases(using Monad[F]): F[(Simulation[F], Seq[Event])] = waiting.map(notifyCase).toSeq.sequence.map(Simulation.compose(_: _*).run(this)).flatten @@ -133,12 +134,12 @@ case class Simulation[F[_]]( /** * Starts the simulation with an initial state update. * - * Produces an [[EStart]] event. + * Produces an [[events.EStart EStart]] event. * * @param state * The state update to apply. * @return - * The updated state and produced [[Event]]s. + * The updated state and produced [[events.Event Event]]s. */ def start( state: StateT[F, Simulation[F], Seq[Event]] @@ -155,18 +156,18 @@ case class Simulation[F[_]]( * Progresses the simulation time. * * This is the main simulation cycle: - * 1. Finish with an [[EDone]] if no events, tasks, or cases remain. + * 1. Finish with an [[events.EDone EDone]] if no events, tasks, or cases remain. * 1. Pop the next group of discrete events in the queue. * 1. Handle the events using [[Simulation.handleDiscreteEvent]]. * 1. Stop any tasks that completed ysing [[Simulation.stopTasks]]. - * 1. Notify the cases that need to be notified with [[notifyCases]]. + * 1. Notify the cases that need to be notified with [[Simulation.notifyCases notifyCases]]. * 1. Allocate new tasks to the resources using [[Simulation.allocateTasks]]. - * 1. Terminate the simulation using [[Simulation.stop()]] if a termination condition (e.g. - * time limit) has been met. + * 1. Terminate the simulation using [[Simulation.stop]] if a termination condition (e.g. time + * limit) has been met. * * @return * Either the updated state or `Unit` if the simulation terminated, and any produced - * [[Event]]s. + * [[events.Event Event]]s. */ def tick(using Monad[F]): F[(Either[Simulation[F], Unit], Seq[Event])] = { /* if !waiting.isEmpty // still waiting for responses! @@ -227,12 +228,12 @@ object Simulation extends StateOps { type SimState[F[_]] = StateT[F, Simulation[F], Seq[Event]] /** - * Initialize a simulation state with a name and [[Scheduler]]. + * Initialize a simulation state with a name and [[schedule.Scheduler Scheduler]]. * * @param id * The name to use for the simulation. * @param scheduler - * The [[Scheduler]] to use. + * The [[schedule.Scheduler Scheduler]] to use. * @return * The initialised [[Simulation]] state. */ @@ -249,15 +250,15 @@ object Simulation extends StateOps { ) /** - * Start a [[CaseRef]]. + * Start a [[cases.CaseRef CaseRef]]. * * Once the case starts, we expect to hear from it in case it wants to add some [[Task]]s. We * therefore add it to the waiting queue. * - * Publishes a [[com.workflowfm.proter.events.ECaseStart ECaseStart]]. + * Publishes a [[events.ECaseStart ECaseStart]]. * * @param caseRef - * The [[CaseRef]] to start. + * The [[cases.CaseRef CaseRef]] to start. * @return * The state update. */ @@ -272,13 +273,13 @@ object Simulation extends StateOps { ) /** - * Stops a [[CaseRef]] when it is done. + * Stops a [[cases.CaseRef CaseRef]] when it is done. * * - Removes it from the list of running cases and the waiting list. - * - Publishes a [[com.workflowfm.proter.events.ECaseEnd ECaseEnd]]. + * - Publishes a [[events.ECaseEnd ECaseEnd]]. * * @param name - * The name of the completed [[CaseRef]]. + * The name of the completed [[cases.CaseRef CaseRef]]. * @param result * A string representation of the resulting output of the case. * @return @@ -301,16 +302,16 @@ object Simulation extends StateOps { // ready(name) /** - * Stops/aborts a [[CaseRef]] before it is done. + * Stops/aborts a [[cases.CaseRef CaseRef]] before it is done. * * - Removes it from the list of running cases and from the waiting list. * - Aborts and removes all tasks of the case. * - Publishes a [[com.workflowfm.proter.events.ECaseEnd ECaseEnd]] with a "Simulation Aborted" * result. - * - Tells the [[CaseRef]] to stop. + * - Tells the [[cases.CaseRef CaseRef]] to stop. * * @param caseRef - * The [[CaseRef]] to stop. + * The [[cases.CaseRef CaseRef]] to stop. * @return * The state update. */ @@ -399,7 +400,7 @@ object Simulation extends StateOps { * - Detaches all associated resources using [[ResourceMap.stopTasks]]. * - Produces an [[com.workflowfm.proter.events.ETaskDetach ETaskDetach]] event for each * resource. - * - Adds the task ID to the [[abortedTasks]] set. + * - Adds the task ID to the `abortedTasks` set. * - Produces an [[com.workflowfm.proter.events.ETaskAbort ETaskAbort]] event. * * @param ids @@ -425,7 +426,7 @@ object Simulation extends StateOps { * - Produces an [[com.workflowfm.proter.events.ETaskDetach ETaskDetach]] event for each * resource. * - Produces an [[com.workflowfm.proter.events.ETaskDone ETaskDone]] event. - * - Adds the corresponding [[CaseRef]]s to the waiting list. + * - Adds the corresponding [[cases.CaseRef CaseRef]]s to the waiting list. * * @param tasks * The [[TaskInstance]]s that need to be stopped. @@ -452,7 +453,7 @@ object Simulation extends StateOps { /** * Allocates and starts new [[TaskInstance]]s. * - * New tasks are decided by the [[Scheduler]] given the resource availability. + * New tasks are decided by the [[schedule.Scheduler Scheduler]] given the resource availability. * * @return * The state update. @@ -556,13 +557,14 @@ object Simulation extends StateOps { } /** - * Produces an [[EError]] indicating a [[CaseRef]] in the waiting list is unknown. + * Produces an [[events.EError EError]] indicating a [[cases.CaseRef CaseRef]] in the waiting + * list is unknown. * * @see - * [[notifyCase]] + * [[Simulation.notifyCase notifyCase]] * * @param caseName - * The name of the [[CaseRef]] we were supposed to notify. + * The name of the [[cases.CaseRef CaseRef]] we were supposed to notify. * @return * The state update. */ From 1d8906465245460beb0326f43281f02404be283f Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Sun, 31 Jul 2022 16:16:16 +0100 Subject: [PATCH 10/31] Updates scaladoc for proter-server --- .../workflowfm/proter/server/Entities.scala | 135 +++++++++++++----- .../proter/server/SimulationRunner.scala | 25 ++-- 2 files changed, 116 insertions(+), 44 deletions(-) diff --git a/proter-server/src/main/scala/com/workflowfm/proter/server/Entities.scala b/proter-server/src/main/scala/com/workflowfm/proter/server/Entities.scala index 842f0aa..6a9cc7e 100644 --- a/proter-server/src/main/scala/com/workflowfm/proter/server/Entities.scala +++ b/proter-server/src/main/scala/com/workflowfm/proter/server/Entities.scala @@ -6,16 +6,20 @@ import flows.{ Flow, FlowTask } /** * This file contains a number of case classes that are used as intermediate objects used in the * process of converting the JSON sent to this system to the objects and structure required by - * Proter to run simulations + * Proter to run simulations. */ /** - * IRequest is the highest level object for encoding a request for proter execution + * The highest level object encoding a request for simulation. * + * @param start + * An optional starting timestamp (default: 0). * @param arrival - * Defines how simulations arrive + * The cases and arrivals to simulate. * @param resources - * Contains the definitions of resources that are referenced in the arrival + * The resources to use in the simulation. + * @param timeLimit + * An optional time limit for the simulation. Must be defined if an infinite arrival is provided. */ final case class IRequest( start: Option[Long], @@ -29,20 +33,18 @@ final case class IRequest( } /** - * Defines how often simulations are to start + * Defines a [[flows.Flow Flow]]-based case or arrival pattern of cases. * - * @param simulation - * The simulation that is to be started - * @param infinite - * If the arrival is infinite then this should be true + * @param name + * A unique name to use for the case(s). + * @param flow + * The flow to run for the case(s). + * @param start + * An optional start time for the case(s) (default: simulation starting time). * @param rate - * The rate at which new simulation should be started - * @param simulationLimit - * If infinite is false then this determines how many simulations should be run in total before - * stopping - * @param timeLimit - * If infinite is true then this determines for how long the simulation should be run before - * stopping + * An optional distribution describing the duration until the next arrival (default: never). + * @param limit + * An optional limit to the number of cases to generate (default: infinite). */ final case class IArrival( name: String, @@ -57,19 +59,34 @@ final case class IArrival( } /** - * A flow describes a number of tasks as well as the order in which they are executed - * - * @param tasks - * A list of tasks - * @param ordering - * The order in which they occur, this is encoded as a string containing the names of the tasks - * separated with "->" to determine order + * A structural representation of a [[flows.Flow Flow]]. */ sealed trait IFlow { + /** + * Retrieve the actual [[flows.Flow Flow]]. + * + * @return + * The flow. + */ def flow: Flow + + /** + * The set of names of [[Resource]]s used in the flow. + * + * This is used for validation. + * + * @return + * A set of [[Resource]] names. + */ def resourceNames: Set[String] } +/** + * A structural representation of a sequential [[flows.Then Then]] flow. + * + * @param args + * The sub-flows to run in sequence. Must be non-empty. + */ final case class IThen(args: List[IFlow]) extends IFlow { if (args.isEmpty) throw new IllegalArgumentException("Empty IThen arguments.") @@ -78,6 +95,12 @@ final case class IThen(args: List[IFlow]) extends IFlow { override def resourceNames: Set[String] = args.flatMap(_.resourceNames).toSet } +/** + * A structural representation of a parallel [[flows.And And]] flow. + * + * @param args + * The sub-flows to run in parallel. Must be non-empty. + */ final case class IPar(args: List[IFlow]) extends IFlow { if (args.isEmpty) throw new IllegalArgumentException("Empty IPar arguments.") @@ -87,19 +110,18 @@ final case class IPar(args: List[IFlow]) extends IFlow { } /** - * This defines a task with all its details + * An intermediate, serializable abstraction of a [[Task]]. * * @param name - * The name of the task + * The name of the task. * @param duration - * A distribution describing the duration of the task + * A distribution describing the duration of the task. * @param cost - * A distribution describing the cost of the task + * A distribution describing the cost of the task. * @param resources - * A string containing the names of the resources the task requires (if multiple they should be - * separated with a comma) + * A list of required resources. * @param priority - * The priority of the task (from -2 being the lowest to 2 being the highest) + * A numerical priority for the task. */ final case class ITask( name: String, @@ -110,10 +132,10 @@ final case class ITask( ) extends IFlow { /** - * This method converts this intermediate task object into a Proter Task + * Converts the intermediate representation to the actual [[Task]]. * * @return - * A proter task + * The [[Task]]. */ lazy val task: Task = { Task(this.name, this.duration.toProterDistribution()) @@ -127,6 +149,15 @@ final case class ITask( } + +/** + * An intermediate, serializable abstraction of a [[Resource]] requirement for a [[Task]]. + * + * @param resource + * The name of the required resource. + * @param quantity + * The amount of resource capacity required. + */ final case class IRequiredResource(resource: String, quantity: Int) { if (quantity <= 0) throw new IllegalArgumentException( @@ -135,12 +166,14 @@ final case class IRequiredResource(resource: String, quantity: Int) { } /** - * This defines a resource + * An intermediate representation of a [[Resource]]. * * @param name - * The name of the resource + * The name of the resource. + * @param capacity + * The units of capacity of the resource. Must be greater than 0. * @param costPerTick - * The Cost per time unit for the resource + * The cost per time unit for the resource. Must be non-negative. */ case class IResource(name: String, capacity: Int, costPerTick: Double) { if (costPerTick < 0) @@ -153,9 +186,10 @@ case class IResource(name: String, capacity: Int, costPerTick: Double) { ) /** - * Converts this intermediate object to a Proter Resource + * Converts this intermediate object to the actual [[Resource]]. * * @return + * The [[Resource]]. */ def toProterResource(): Resource = { new Resource(this.name, this.capacity, this.costPerTick) @@ -163,10 +197,25 @@ case class IResource(name: String, capacity: Int, costPerTick: Double) { } +/** + * An intermediate, serializable representation of a [[Distribution]]. + */ sealed trait IDistribution { + /** + * Converts this intermediate object to the actual [[Distribution]]. + * + * @return + * The [[Distribution]]. + */ def toProterDistribution(): Distribution } +/** + * An intermediate, serializable representation of a [[Constant]] distribution. + * + * @param value + * The constant value. + */ final case class IConstant(value: Double) extends IDistribution { if (value < 0.0) { throw new IllegalArgumentException(s"Constant value must be non-negative: $value") @@ -176,6 +225,12 @@ final case class IConstant(value: Double) extends IDistribution { Constant(value) } +/** + * An intermediate, serializable representation of a [[Exponential]] distribution. + * + * @param value + * The mean value. + */ final case class IExp(value: Double) extends IDistribution { if (value < 0.0) { throw new IllegalArgumentException(s"Exponential value must be non-negative: $value") @@ -185,6 +240,14 @@ final case class IExp(value: Double) extends IDistribution { Exponential(value) } +/** + * An intermediate, serializable representation of a [[Uniform]] distribution. + * + * @param from + * The minimum value. + * @param to + * The maximum value. + */ final case class IUniform(from: Double, to: Double) extends IDistribution { if (from < 0.0 || to < 0.0) { throw new IllegalArgumentException(s"Uniform range must be non-negative: $from-$to") diff --git a/proter-server/src/main/scala/com/workflowfm/proter/server/SimulationRunner.scala b/proter-server/src/main/scala/com/workflowfm/proter/server/SimulationRunner.scala index a8c97e6..6f5d30d 100644 --- a/proter-server/src/main/scala/com/workflowfm/proter/server/SimulationRunner.scala +++ b/proter-server/src/main/scala/com/workflowfm/proter/server/SimulationRunner.scala @@ -26,12 +26,12 @@ class SimulationRunner[F[_] : Random : Async : UUIDGen](using monad: MonadError[ import Entities.given /** - * This top level function should take an IRequest and then return a Results object + * Simulates a scenario described by an [[IRequest]] and returns the calculated [[metrics.Metrics Metrics]]. * * @param request - * The input IRequest + * The input [[IRequest]]. * @return - * A Results object + * The resulting [[metrics.Metrics Metrics]]. */ def handle(request: IRequest): F[Metrics] = { @@ -55,6 +55,14 @@ class SimulationRunner[F[_] : Random : Async : UUIDGen](using monad: MonadError[ } + /** + * Simulates a scenario described by an [[IRequest]] and returns a stream of [[events.Event Event]]s. + * + * @param request + * The input [[IRequest]]. + * @return + * The event stream. + */ def stream(request: IRequest): Stream[F, Event] = { if (!this.matchingResources(request)) { @@ -75,10 +83,12 @@ class SimulationRunner[F[_] : Random : Async : UUIDGen](using monad: MonadError[ } /** - * Method takes a decoded request and adds to the given coordinator the details of the request + * Constructs a simulation [[Scenario]] from an [[IRequest]] object. * - * @param coord * @param requestObj + * The [[IRequest]] object. + * @return + * The constructed [[Scenario]]. */ def getScenario(requestObj: IRequest): Scenario[F] = { @@ -145,11 +155,10 @@ class SimulationRunner[F[_] : Random : Async : UUIDGen](using monad: MonadError[ } /** - * This checks to ensure that the request has matching resources, as in ensuring the resources - * referenced in the Tasks are defined in the resource list + * Validates that the resources referenced in tasks and flows are defined in the resource list. * * @param request - * An IRequest object to check + * An [[IRequest]] object to validate. * @return * a boolean */ From c0aa355e4a546ec8cebfa5134a19fc1c8902b49c Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Sun, 31 Jul 2022 16:26:12 +0100 Subject: [PATCH 11/31] Moves matching resources test directly in `IRequest` Removes related unit tests. We don't have any tests for matching resources now, but that's ok (for now). --- .../workflowfm/proter/server/Entities.scala | 15 ++ .../proter/server/SimulationRunner.scala | 28 --- .../proter/server/EntityTests.scala | 24 +-- .../proter/server/SimulationRunnerTests.scala | 190 ------------------ .../com/workflowfm/proter/Simulator.scala | 1 - 5 files changed, 27 insertions(+), 231 deletions(-) delete mode 100644 proter-server/src/test/scala/com/workflowfm/proter/server/SimulationRunnerTests.scala diff --git a/proter-server/src/main/scala/com/workflowfm/proter/server/Entities.scala b/proter-server/src/main/scala/com/workflowfm/proter/server/Entities.scala index 6a9cc7e..2d8239c 100644 --- a/proter-server/src/main/scala/com/workflowfm/proter/server/Entities.scala +++ b/proter-server/src/main/scala/com/workflowfm/proter/server/Entities.scala @@ -30,6 +30,21 @@ final case class IRequest( if (timeLimit.isEmpty && arrivals.exists(_.infinite)) throw new IllegalArgumentException("Infinite arrivals require a time limit.") + /** + * Validates that the resources referenced in the flow are defined in the resource list. + * + * @return + * true if resource references are valid. + */ + val matchingResources: Boolean = { + val definedResources: Set[String] = resources.map(_.name).toSet + val referencedResources: Set[String] = + arrivals.flatMap(arrival => arrival.flow.resourceNames).toSet + referencedResources.subsetOf(definedResources) + } + + if (!matchingResources) + throw new IllegalArgumentException("Flow resources cannot be matched to the resource list.") } /** diff --git a/proter-server/src/main/scala/com/workflowfm/proter/server/SimulationRunner.scala b/proter-server/src/main/scala/com/workflowfm/proter/server/SimulationRunner.scala index 6f5d30d..e5dd420 100644 --- a/proter-server/src/main/scala/com/workflowfm/proter/server/SimulationRunner.scala +++ b/proter-server/src/main/scala/com/workflowfm/proter/server/SimulationRunner.scala @@ -35,10 +35,6 @@ class SimulationRunner[F[_] : Random : Async : UUIDGen](using monad: MonadError[ */ def handle(request: IRequest): F[Metrics] = { - if (!this.matchingResources(request)) { - monad.raiseError(new IllegalArgumentException("Resources do not match")) - } - for { result <- Deferred[F, Metrics] simulator = Simulator[F](ProterScheduler).withSubs( @@ -65,10 +61,6 @@ class SimulationRunner[F[_] : Random : Async : UUIDGen](using monad: MonadError[ */ def stream(request: IRequest): Stream[F, Event] = { - if (!this.matchingResources(request)) { - monad.raiseError(new IllegalArgumentException("Resources do not match")) - } - val simulator = Simulator[F](ProterScheduler) val scenario = getScenario(request) @@ -153,24 +145,4 @@ class SimulationRunner[F[_] : Random : Async : UUIDGen](using monad: MonadError[ requestObj.timeLimit.map(l => updated.withLimit(l)).getOrElse(updated) } - - /** - * Validates that the resources referenced in tasks and flows are defined in the resource list. - * - * @param request - * An [[IRequest]] object to validate. - * @return - * a boolean - */ - def matchingResources(request: IRequest): Boolean = { - val definedResources: Set[String] = request.resources.map(_.name).toSet - val referencedResources: Set[String] = - request.arrivals.flatMap(arrival => arrival.flow.resourceNames).toSet - if (referencedResources.subsetOf(definedResources)) { - true - } else { - false - } - } - } diff --git a/proter-server/src/test/scala/com/workflowfm/proter/server/EntityTests.scala b/proter-server/src/test/scala/com/workflowfm/proter/server/EntityTests.scala index 26a255e..a51c808 100644 --- a/proter-server/src/test/scala/com/workflowfm/proter/server/EntityTests.scala +++ b/proter-server/src/test/scala/com/workflowfm/proter/server/EntityTests.scala @@ -123,10 +123,10 @@ class EntityTests extends AnyFunSuite with EntityTestHelper { test("Infinite Arrival Correct limit") { val taskList: List[ITask] = List( - ITask("A", IConstant(3.4), IConstant(3.4), require("R1"), 0), - ITask("B", IConstant(3.4), IConstant(3.4), require("R2"), 0), - ITask("C", IConstant(3.4), IConstant(3.4), require("R1", "R2"), 0), - ITask("D", IConstant(3.4), IConstant(3.4), require("R2"), 0) + ITask("A", IConstant(3.4), IConstant(3.4), List(), 0), + ITask("B", IConstant(3.4), IConstant(3.4), List(), 0), + ITask("C", IConstant(3.4), IConstant(3.4), List(), 0), + ITask("D", IConstant(3.4), IConstant(3.4), List(), 0) ) val flow: IFlow = IThen(taskList) val arrival: IArrival = IArrival("Sim Name", flow, None, Some(IConstant(4.3)), None) @@ -135,10 +135,10 @@ class EntityTests extends AnyFunSuite with EntityTestHelper { test("Finite Arrival Correct limit") { val taskList: List[ITask] = List( - ITask("A", IConstant(3.4), IConstant(3.4), require("R1"), 0), - ITask("B", IConstant(3.4), IConstant(3.4), require("R2"), 0), - ITask("C", IConstant(3.4), IConstant(3.4), require("R1", "R2"), 0), - ITask("D", IConstant(3.4), IConstant(3.4), require("R2"), 0) + ITask("A", IConstant(3.4), IConstant(3.4), List(), 0), + ITask("B", IConstant(3.4), IConstant(3.4), List(), 0), + ITask("C", IConstant(3.4), IConstant(3.4), List(), 0), + ITask("D", IConstant(3.4), IConstant(3.4), List(), 0) ) val flow: IFlow = IThen(taskList) val arrival: IArrival = IArrival("Sim Name", flow, None, Some(IConstant(4.3)), Some(10)) @@ -147,10 +147,10 @@ class EntityTests extends AnyFunSuite with EntityTestHelper { test("Infinite Arrival Incorrect limit") { val taskList: List[ITask] = List( - ITask("A", IConstant(3.4), IConstant(3.4), require("R1"), 0), - ITask("B", IConstant(3.4), IConstant(3.4), require("R2"), 0), - ITask("C", IConstant(3.4), IConstant(3.4), require("R1", "R2"), 0), - ITask("D", IConstant(3.4), IConstant(3.4), require("R2"), 0) + ITask("A", IConstant(3.4), IConstant(3.4), List(), 0), + ITask("B", IConstant(3.4), IConstant(3.4), List(), 0), + ITask("C", IConstant(3.4), IConstant(3.4), List(), 0), + ITask("D", IConstant(3.4), IConstant(3.4), List(), 0) ) val flow: IFlow = IThen(taskList) val arrival: IArrival = IArrival("Sim Name", flow, None, Some(IConstant(4.3)), None) diff --git a/proter-server/src/test/scala/com/workflowfm/proter/server/SimulationRunnerTests.scala b/proter-server/src/test/scala/com/workflowfm/proter/server/SimulationRunnerTests.scala deleted file mode 100644 index 0bbfc4a..0000000 --- a/proter-server/src/test/scala/com/workflowfm/proter/server/SimulationRunnerTests.scala +++ /dev/null @@ -1,190 +0,0 @@ -package com.workflowfm.proter.server - -import org.scalatest.funsuite.AnyFunSuite - -import cats.implicits.* -import cats.effect.IO -import cats.effect.unsafe.IORuntime -import cats.effect.implicits.* -import cats.effect.std.Random - -/** - * Contains the partial tests for SimulationRunner primarily testing the validation and utility - * functions of that class - */ -class SimulationRunnerTests extends AnyFunSuite with EntityTestHelper { - - given IORuntime = IORuntime.global - - test("matchingResources, should identify simple matching resource lists") { - Random - .scalaUtilRandom[IO] - .map { r => - given Random[IO] = r - val simRun = new SimulationRunner[IO]() - val externalResourceList: List[IResource] = List( - new IResource("R1", 1, 0.4), - new IResource("R2", 1, 8.3) - ) - val taskList: List[ITask] = List( - new ITask("A", IConstant(3.4), IConstant(3.4), require("R1"), 0), - new ITask("B", IConstant(3.4), IConstant(3.4), require("R2"), 0), - new ITask("C", IConstant(3.4), IConstant(3.4), require("R1"), 0) - ) - val flow: IFlow = IThen(taskList) - val arrival: IArrival = IArrival("Sim Name", flow, None, Some(IConstant(4.3)), Some(10)) - val request: IRequest = IRequest(None, List(arrival), externalResourceList, None) - - assert(simRun.matchingResources(request)) - } - .unsafeRunSync() - } - - test("matchingResources, should identify matching resource list with multiple arrivals") { - Random - .scalaUtilRandom[IO] - .map { r => - given Random[IO] = r - val simRun = new SimulationRunner[IO]() - val externalResourceList: List[IResource] = List( - new IResource("R1", 1, 0.4), - new IResource("R2", 1, 8.3), - new IResource("R3", 1, 11), - new IResource("R4", 1, 0.8) - ) - - val taskList1: List[ITask] = List( - new ITask("A", IConstant(3.4), IConstant(3.4), require("R1"), 0), - new ITask("B", IConstant(3.4), IConstant(3.4), require("R2"), 0), - new ITask("C", IConstant(3.4), IConstant(3.4), require("R1", "R2"), 0) - ) - val flow1: IFlow = IThen(taskList1) - val arrival1: IArrival = IArrival("Sim1", flow1, None, Some(IConstant(4.3)), Some(10)) - - val taskList2: List[ITask] = List( - new ITask("D", IConstant(3.4), IConstant(3.4), require("R3"), 0), - new ITask("E", IConstant(3.4), IConstant(3.4), require("R4"), 0), - new ITask("F", IConstant(3.4), IConstant(3.4), require("R1", "R2"), 0) - ) - val flow2: IFlow = IThen(taskList2) - val arrival2: IArrival = IArrival("Sim2", flow2, None, Some(IConstant(4.3)), Some(10)) - - val request: IRequest = IRequest(None, List(arrival1, arrival2), externalResourceList, None) - - assert(simRun.matchingResources(request)) - } - .unsafeRunSync() - } - - test("matchingResources, multiple resources per task") { - Random - .scalaUtilRandom[IO] - .map { r => - given Random[IO] = r - val simRun = new SimulationRunner[IO]() - - val externalResourceList: List[IResource] = List( - new IResource("R1", 1, 0.4), - new IResource("R2", 1, 8.3) - ) - val taskList: List[ITask] = List( - new ITask("A", IConstant(3.4), IConstant(3.4), require("R1"), 0), - new ITask("B", IConstant(3.4), IConstant(3.4), require("R2"), 0), - new ITask("C", IConstant(3.4), IConstant(3.4), require("R1", "R2"), 0) - ) - val flow: IFlow = IThen(taskList) - val arrival: IArrival = IArrival("Sim Name", flow, None, Some(IConstant(4.3)), Some(10)) - val request: IRequest = IRequest(None, List(arrival), externalResourceList, None) - - assert(simRun.matchingResources(request)) - } - .unsafeRunSync() - } - - test("matchingResources, missing task in defined resources") { - Random - .scalaUtilRandom[IO] - .map { r => - given Random[IO] = r - val simRun = new SimulationRunner[IO]() - - val externalResourceList: List[IResource] = List( - new IResource("R1", 1, 0.4) - ) - val taskList: List[ITask] = List( - new ITask("A", IConstant(3.4), IConstant(3.4), require("R1"), 0), - new ITask("B", IConstant(3.4), IConstant(3.4), require("R2"), 0), - new ITask("C", IConstant(3.4), IConstant(3.4), require("R1", "R2"), 0) - ) - val flow: IFlow = IThen(taskList) - val arrival: IArrival = IArrival("Sim Name", flow, None, Some(IConstant(4.3)), Some(10)) - val request: IRequest = IRequest(None, List(arrival), externalResourceList, None) - - assert(simRun.matchingResources(request) == false) - } - .unsafeRunSync() - } - - test("matchingResources, missing task in defined resources with multiple arrivals") { - Random - .scalaUtilRandom[IO] - .map { r => - given Random[IO] = r - val simRun = new SimulationRunner[IO]() - - val externalResourceList: List[IResource] = List( - new IResource("R1", 1, 0.4), - new IResource("R2", 1, 8.3), - new IResource("R4", 1, 0.8) - ) - - val taskList1: List[ITask] = List( - new ITask("A", IConstant(3.4), IConstant(3.4), require("R1"), 0), - new ITask("B", IConstant(3.4), IConstant(3.4), require("R2"), 0), - new ITask("C", IConstant(3.4), IConstant(3.4), require("R1", "R2"), 0) - ) - val flow1: IFlow = IThen(taskList1) - val arrival1: IArrival = IArrival("Sim1", flow1, None, Some(IConstant(4.3)), Some(10)) - - val taskList2: List[ITask] = List( - new ITask("D", IConstant(3.4), IConstant(3.4), require("R3"), 0), - new ITask("E", IConstant(3.4), IConstant(3.4), require("R4"), 0), - new ITask("F", IConstant(3.4), IConstant(3.4), require("R1", "R2"), 0) - ) - val flow2: IFlow = IThen(taskList2) - val arrival2: IArrival = IArrival("Sim2", flow2, None, Some(IConstant(4.3)), Some(10)) - - val request: IRequest = IRequest(None, List(arrival1, arrival2), externalResourceList, None) - - assert(!simRun.matchingResources(request)) - } - .unsafeRunSync() - } - - test("matchingResources, unused tasks in specified resources") { - Random - .scalaUtilRandom[IO] - .map { r => - given Random[IO] = r - val simRun = new SimulationRunner[IO]() - - val externalResourceList: List[IResource] = List( - new IResource("R1", 1, 0.4), - new IResource("R2", 1, 8.3), - new IResource("R3", 1, 6.2) - ) - val taskList: List[ITask] = List( - new ITask("A", IConstant(3.4), IConstant(3.4), require("R1"), 0), - new ITask("B", IConstant(3.4), IConstant(3.4), require("R2"), 0), - new ITask("C", IConstant(3.4), IConstant(3.4), require("R1", "R2"), 0) - ) - val flow: IFlow = IThen(taskList) - val arrival: IArrival = IArrival("Sim Name", flow, None, Some(IConstant(4.3)), Some(10)) - val request: IRequest = IRequest(None, List(arrival), externalResourceList, None) - - assert(simRun.matchingResources(request)) - } - .unsafeRunSync() - } - -} diff --git a/proter/src/main/scala/com/workflowfm/proter/Simulator.scala b/proter/src/main/scala/com/workflowfm/proter/Simulator.scala index 43a1a3f..0f9dc18 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Simulator.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Simulator.scala @@ -161,7 +161,6 @@ final case class Simulator[F[_] : Concurrent]( for { sResult <- sim.start(state) (updated, events) = sResult - _ = println("hi") _ <- events.map(publisher.publish(_)).sequence x <- updated.tailRecM(simRec(publisher)) } yield (x) From ab5b33c6c8a4d1877d06fe9bb64fe5919e29c306 Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Mon, 1 Aug 2022 11:58:04 +0100 Subject: [PATCH 12/31] Renames `Metrics.start` and `end` to `startTime` and `endTime` --- .../scala/com/workflowfm/proter/metrics/Metrics.scala | 10 +++++----- .../com/workflowfm/proter/metrics/MetricsOutput.scala | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala index ababcd8..1fee75e 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala @@ -32,8 +32,8 @@ import events.* * A queue of all errors caught. */ final case class Metrics( - start: Option[Long], - end: Option[Long], + startTime: Option[Long], + endTime: Option[Long], startTicks: Long, endTicks: Long, tasks: Map[UUID, TaskMetrics], @@ -49,10 +49,10 @@ final case class Metrics( * * @group Start/End */ - def started(t: Long): Metrics = start match { + def started(t: Long): Metrics = startTime match { case None => copy( - start = Some(System.currentTimeMillis()), + startTime = Some(System.currentTimeMillis()), startTicks = t ) case _ => this @@ -64,7 +64,7 @@ final case class Metrics( * @group Start/End */ def ended(t: Long): Metrics = copy( - end = Some(System.currentTimeMillis()), + endTime = Some(System.currentTimeMillis()), endTicks = t ) diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsOutput.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsOutput.scala index 21310ca..8640a7b 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsOutput.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/MetricsOutput.scala @@ -276,9 +276,9 @@ ${resHeader(sep)} ${resources(metrics, sep, lineSep)} --------- -Started: ${MetricsOutput.formatTimeOption(metrics.start, timeFormat, nullTime)} -Ended: ${MetricsOutput.formatTimeOption(metrics.end, timeFormat, nullTime)} -Duration: ${MetricsOutput.formatDuration(metrics.start, metrics.end, durFormat, nullTime)} +Started: ${MetricsOutput.formatTimeOption(metrics.startTime, timeFormat, nullTime)} +Ended: ${MetricsOutput.formatTimeOption(metrics.endTime, timeFormat, nullTime)} +Duration: ${MetricsOutput.formatDuration(metrics.startTime, metrics.endTime, durFormat, nullTime)} """ ) } From 9879ec7fa53ce1b1aa74a1c63fc895c575b9caf8 Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Mon, 1 Aug 2022 12:39:22 +0100 Subject: [PATCH 13/31] Flattens JSON encoding of Maps in `Metrics` --- .../com/workflowfm/proter/metrics/Metrics.scala | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala index 1fee75e..31f6094 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala @@ -319,12 +319,22 @@ object Metrics { final case class ResourceNotFound(name: String) extends MetricsException(s"Tried to update metrics for task that does not exist: $name") - import io.circe.generic.semiauto._ + import io.circe.generic.semiauto.* import io.circe.Encoder + import io.circe.syntax.* given Encoder[TaskMetrics] = deriveEncoder[TaskMetrics] + given taskMapEncoder: Encoder[Map[UUID, TaskMetrics]] = (collection: Map[UUID, TaskMetrics]) => + collection.values.map(_.asJson).toList.asJson + given Encoder[CaseMetrics] = deriveEncoder[CaseMetrics] + given caseMapEncoder: Encoder[Map[String, CaseMetrics]] = (collection: Map[String, CaseMetrics]) => + collection.values.map(_.asJson).toList.asJson + given Encoder[ResourceMetrics] = deriveEncoder[ResourceMetrics] + given resourceMapEncoder: Encoder[Map[String, ResourceMetrics]] = (collection: Map[String, ResourceMetrics]) => + collection.values.map(_.asJson).toList.asJson + given Encoder[MetricsException] = deriveEncoder[MetricsException] given Encoder[Metrics] = deriveEncoder[Metrics] From 5a421abc71d9e8a05e7c9176ac436028e90ab518 Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Mon, 1 Aug 2022 12:55:09 +0100 Subject: [PATCH 14/31] Flattens JSON encoding of `MetricsException` See: https://circe.github.io/circe/codecs/adt.html --- .../com/workflowfm/proter/metrics/Metrics.scala | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala index 31f6094..8b74771 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala @@ -310,14 +310,14 @@ object Metrics { sealed abstract class MetricsException(message: String) extends Exception(message) - final case class TaskNotFound(id: UUID) - extends MetricsException(s"Tried to update metrics for task that does not exist: $id") + final case class TaskNotFound(taskId: UUID) + extends MetricsException(s"Tried to update metrics for task that does not exist: $taskId") final case class CaseNotFound(caseName: String) extends MetricsException(s"Tried to update metrics for task that does not exist: $caseName") - final case class ResourceNotFound(name: String) - extends MetricsException(s"Tried to update metrics for task that does not exist: $name") + final case class ResourceNotFound(resourceName: String) + extends MetricsException(s"Tried to update metrics for task that does not exist: $resourceName") import io.circe.generic.semiauto.* import io.circe.Encoder @@ -335,7 +335,14 @@ object Metrics { given resourceMapEncoder: Encoder[Map[String, ResourceMetrics]] = (collection: Map[String, ResourceMetrics]) => collection.values.map(_.asJson).toList.asJson - given Encoder[MetricsException] = deriveEncoder[MetricsException] + given Encoder[TaskNotFound] = deriveEncoder[TaskNotFound] + given Encoder[CaseNotFound] = deriveEncoder[CaseNotFound] + given Encoder[ResourceNotFound] = deriveEncoder[ResourceNotFound] + given Encoder[MetricsException] = Encoder.instance { + case t @ TaskNotFound(_) => t.asJson + case c @ CaseNotFound(_) => c.asJson + case r @ ResourceNotFound(_) => r.asJson + } given Encoder[Metrics] = deriveEncoder[Metrics] From 3866c9bbfdf77f2d7c7404a745d5f9cfe577147b Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Mon, 1 Aug 2022 14:20:22 +0100 Subject: [PATCH 15/31] Flattens JSON encoding of `TaskInstance` maps in `JsonHandler` --- .../scala/com/workflowfm/proter/events/JsonHandler.scala | 5 +++++ .../main/scala/com/workflowfm/proter/metrics/Metrics.scala | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/proter/src/main/scala/com/workflowfm/proter/events/JsonHandler.scala b/proter/src/main/scala/com/workflowfm/proter/events/JsonHandler.scala index d8eda63..aaff680 100644 --- a/proter/src/main/scala/com/workflowfm/proter/events/JsonHandler.scala +++ b/proter/src/main/scala/com/workflowfm/proter/events/JsonHandler.scala @@ -1,6 +1,7 @@ package com.workflowfm.proter package events +import java.util.UUID import java.text.SimpleDateFormat import cats.Applicative @@ -28,6 +29,10 @@ trait JsonHandler[F[_] : Applicative : Clock] extends TimedHandler[F] { } object JsonHandler { + given resourceStateTaskMapEncoder: Encoder[Map[UUID, (Long, TaskInstance)]] = (collection: Map[UUID, (Long, TaskInstance)]) => + collection.values.map(_.asJson).toList.asJson + + given Encoder[ResourceState] = deriveEncoder[ResourceState] given Encoder[TaskInstance] = deriveEncoder[TaskInstance] // These are redundant, but help the deriveEncoder macro avoid // a "Maximal number of successive inlines exceeded" error diff --git a/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala b/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala index 8b74771..3fcff27 100644 --- a/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala +++ b/proter/src/main/scala/com/workflowfm/proter/metrics/Metrics.scala @@ -324,15 +324,15 @@ object Metrics { import io.circe.syntax.* given Encoder[TaskMetrics] = deriveEncoder[TaskMetrics] - given taskMapEncoder: Encoder[Map[UUID, TaskMetrics]] = (collection: Map[UUID, TaskMetrics]) => + given taskMetricsMapEncoder: Encoder[Map[UUID, TaskMetrics]] = (collection: Map[UUID, TaskMetrics]) => collection.values.map(_.asJson).toList.asJson given Encoder[CaseMetrics] = deriveEncoder[CaseMetrics] - given caseMapEncoder: Encoder[Map[String, CaseMetrics]] = (collection: Map[String, CaseMetrics]) => + given caseMetricsMapEncoder: Encoder[Map[String, CaseMetrics]] = (collection: Map[String, CaseMetrics]) => collection.values.map(_.asJson).toList.asJson given Encoder[ResourceMetrics] = deriveEncoder[ResourceMetrics] - given resourceMapEncoder: Encoder[Map[String, ResourceMetrics]] = (collection: Map[String, ResourceMetrics]) => + given resourceMetricsMapEncoder: Encoder[Map[String, ResourceMetrics]] = (collection: Map[String, ResourceMetrics]) => collection.values.map(_.asJson).toList.asJson given Encoder[TaskNotFound] = deriveEncoder[TaskNotFound] From 7bcbd14aa40e898bea83921a0ca63a48e08e444a Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Mon, 1 Aug 2022 14:51:28 +0100 Subject: [PATCH 16/31] Completes OpenAPI spec --- proter-server/docs/proterapi.yaml | 1043 +++++++++++++++++------------ 1 file changed, 622 insertions(+), 421 deletions(-) diff --git a/proter-server/docs/proterapi.yaml b/proter-server/docs/proterapi.yaml index 4d6dbe3..c1257c3 100644 --- a/proter-server/docs/proterapi.yaml +++ b/proter-server/docs/proterapi.yaml @@ -1,410 +1,136 @@ +--- openapi: 3.0.1 info: - title: defaultTitle - description: defaultDescription - version: '0.1' + title: Proter Server + description: An API for running Flow-based simulations in [Proter](http://docs.workflowfm.com/proter/). + version: "0.8" servers: - - url: http://localhost:8080 +- url: http://localhost:8080 paths: - /API: + /simulate: post: - description: Auto generated using Swagger Inspector + description: Perform a simulation and obtain measured metrics. requestBody: content: application/json: schema: $ref: '#/components/schemas/IRequest' examples: - '0': - value: |- - { - "arrivals" : [ - { - "name" : "Example1", - "flow" : { - "IThen" : { - "args": [ - { - "ITask" : { - "name" : "T1", - "duration" : { - "IConstant" : { - "value" : 5.0 - } - }, - "cost" : { - "IConstant" : { - "value" : 2.0 - } - }, - "resources" : [ - { - "resource": "Resource", - "quantity": 1 - } - ], - "priority" : 0 - } - }, - { - "ITask" : { - "name" : "T2", - "duration" : { - "IConstant" : { - "value" : 1.0 - } - }, - "cost" : { - "IConstant" : { - "value" : 3.0 - } - }, - "resources" : [ - ], - "priority" : 0 - } - } - ] - } - }, - "rate" : { - "IConstant" : { - "value" : 1.0 - } - }, - "limit" : 3 - } - ], - "resources" : [ - { - "name": "Resource", - "capacity": 2, - "costPerTick": 1.0 - } - ], - "timeLimit" : null - } + "0": + value: "{\n \"arrivals\" : [\n {\n \"name\" : \"Example1\",\n \"flow\" : {\n \"IThen\" : { \n \"args\": [\n {\n \"ITask\" : {\n \"name\" : \"T1\",\n \"duration\" : {\n \"IConstant\" : {\n \"value\" : 5.0\n }\n },\n \"cost\" : {\n \"IConstant\" : {\n \"value\" : 2.0\n }\n },\n \"resources\" : [\n {\n \"resource\": \"Resource\",\n \"quantity\": 1\n }\n ],\n \"priority\" : 0\n }\n },\n {\n \"ITask\" : {\n \"name\" : \"T2\",\n \"duration\" : {\n \"IConstant\" : {\n \"value\" : 1.0\n }\n },\n \"cost\" : {\n \"IConstant\" : {\n \"value\" : 3.0\n }\n },\n \"resources\" : [\n ],\n \"priority\" : 0\n }\n }\n ] \n }\n },\n \"rate\" : {\n \"IConstant\" : {\n \"value\" : 1.0\n }\n },\n \"limit\" : 3\n }\n ],\n \"resources\" : [\n {\n \"name\": \"Resource\",\n \"capacity\": 2,\n \"costPerTick\": 1.0\n }\n ]\n} " responses: - '200': - description: "Resulting simulation metrics" + "200": + description: Resulting simulation metrics content: application/json: schema: - type: object - properties: - endTicks: - type: integer - cases: - type: object - properties: - Example1#1: - type: object - properties: - duration: - type: integer - result: - type: string - delay: - type: integer - cost: - type: number - name: - type: string - started: - type: integer - tasks: - type: integer - Example1#2: - type: object - properties: - duration: - type: integer - result: - type: string - delay: - type: integer - cost: - type: number - name: - type: string - started: - type: integer - tasks: - type: integer - Example1#3: - type: object - properties: - duration: - type: integer - result: - type: string - delay: - type: integer - cost: - type: number - name: - type: string - started: - type: integer - tasks: - type: integer - resources: - type: object - properties: - Resource: - type: object - properties: - cost: - type: number - costPerTick: - type: number - load: - type: integer - name: - type: string - idleUpdate: - type: integer - busyTime: - type: integer - idleTime: - type: integer - tasks: - type: integer - capacity: - type: integer - sStart: - type: number - sEnd: - type: number - tasks: - type: object - properties: - 3a92c6b0-6655-4021-a668-183c5244abbf: - type: object - properties: - duration: - type: integer - task: - type: string - cost: - type: number - created: - type: integer - aborted: - type: boolean - caseName: - type: string - resources: - type: object - properties: {} - started: - type: integer - id: - type: string - priority: - type: integer - 277c9078-e625-4097-9486-744677a83f13: - type: object - properties: - duration: - type: integer - task: - type: string - cost: - type: number - created: - type: integer - aborted: - type: boolean - caseName: - type: string - resources: - type: object - properties: {} - started: - type: integer - id: - type: string - priority: - type: integer - cdf2ce2f-618a-4533-ae2c-c4d9d5a3d312: - type: object - properties: - duration: - type: integer - task: - type: string - cost: - type: number - created: - type: integer - aborted: - type: boolean - caseName: - type: string - resources: - type: object - properties: - Resource: - type: integer - started: - type: integer - id: - type: string - priority: - type: integer - 82a20f9a-3e33-46ea-b34a-d23370a75689: - type: object - properties: - duration: - type: integer - task: - type: string - cost: - type: number - created: - type: integer - aborted: - type: boolean - caseName: - type: string - resources: - type: object - properties: - Resource: - type: integer - started: - type: integer - id: - type: string - priority: - type: integer - f4a31554-c116-434f-91d5-217d008d88af: - type: object - properties: - duration: - type: integer - task: - type: string - cost: - type: number - created: - type: integer - aborted: - type: boolean - caseName: - type: string - resources: - type: object - properties: - Resource: - type: integer - started: - type: integer - id: - type: string - priority: - type: integer - c1764abe-5429-4ef1-89c3-66e7f741c17d: - type: object - properties: - duration: - type: integer - task: - type: string - cost: - type: number - created: - type: integer - aborted: - type: boolean - caseName: - type: string - resources: - type: object - properties: {} - started: - type: integer - id: - type: string - priority: - type: integer - errors: - type: array - items: - type: string - startTicks: - type: integer + $ref: '#/components/schemas/Metrics' examples: - '0': - value: >- - {"sStart":1658841712942,"sEnd":1658841712952,"startTicks":0,"endTicks":11,"tasks":{"3a92c6b0-6655-4021-a668-183c5244abbf":{"id":"3a92c6b0-6655-4021-a668-183c5244abbf","task":"T2","caseName":"Example1#2","priority":0,"created":6,"started":6,"duration":1,"cost":3.0,"resources":{},"aborted":false},"c1764abe-5429-4ef1-89c3-66e7f741c17d":{"id":"c1764abe-5429-4ef1-89c3-66e7f741c17d","task":"T2","caseName":"Example1#1","priority":0,"created":5,"started":5,"duration":1,"cost":3.0,"resources":{},"aborted":false},"cdf2ce2f-618a-4533-ae2c-c4d9d5a3d312":{"id":"cdf2ce2f-618a-4533-ae2c-c4d9d5a3d312","task":"T1","caseName":"Example1#1","priority":0,"created":0,"started":0,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},"82a20f9a-3e33-46ea-b34a-d23370a75689":{"id":"82a20f9a-3e33-46ea-b34a-d23370a75689","task":"T1","caseName":"Example1#3","priority":0,"created":2,"started":5,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},"f4a31554-c116-434f-91d5-217d008d88af":{"id":"f4a31554-c116-434f-91d5-217d008d88af","task":"T1","caseName":"Example1#2","priority":0,"created":1,"started":1,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},"277c9078-e625-4097-9486-744677a83f13":{"id":"277c9078-e625-4097-9486-744677a83f13","task":"T2","caseName":"Example1#3","priority":0,"created":10,"started":10,"duration":1,"cost":3.0,"resources":{},"aborted":false}},"cases":{"Example1#1":{"name":"Example1#1","started":0,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},"Example1#2":{"name":"Example1#2","started":1,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},"Example1#3":{"name":"Example1#3","started":2,"duration":9,"delay":3,"tasks":2,"cost":10.0,"result":"()"}},"resources":{"Resource":{"name":"Resource","capacity":2,"costPerTick":1.0,"idleUpdate":11,"load":0,"busyTime":15,"idleTime":7,"tasks":3,"cost":15.0}},"errors":[]} + "0": + value: '{"startTime":1659355815687,"endTime":1659355815744,"startTicks":0,"endTicks":11,"tasks":[{"id":"baf4ebff-5338-472e-b2d6-9fad1a41e71f","task":"T1","caseName":"Example1#3","priority":0,"created":2,"started":5,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"a922a37e-f03f-4445-9ef1-da7bbaf46150","task":"T2","caseName":"Example1#1","priority":0,"created":5,"started":5,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"0cb717df-8808-4ea0-8539-3b04cd0d970f","task":"T2","caseName":"Example1#2","priority":0,"created":6,"started":6,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"c40a5714-f95c-423d-a60d-71a58d55350c","task":"T1","caseName":"Example1#1","priority":0,"created":0,"started":0,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"6a8cc9a6-2196-4b23-9169-3268982e5f62","task":"T2","caseName":"Example1#3","priority":0,"created":10,"started":10,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"a88f379a-d4c1-41c0-a397-78c62212c438","task":"T1","caseName":"Example1#2","priority":0,"created":1,"started":1,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false}],"cases":[{"name":"Example1#1","started":0,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#2","started":1,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#3","started":2,"duration":9,"delay":3,"tasks":2,"cost":10.0,"result":"()"}],"resources":[{"name":"Resource","capacity":2,"costPerTick":1.0,"idleUpdate":11,"load":0,"busyTime":15,"idleTime":7,"tasks":3,"cost":15.0}],"errors":[]}' + "422": + description: Unpocessable Entity - Error in requested scenario + content: + application/json: + schema: + type: string + example: Flow resources cannot be matched to the resource list. + /stream: + post: + description: Perform a simulation and obtain simulation events in chunks. + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/IRequest' + examples: + "0": + value: "{\n \"arrivals\" : [\n {\n \"name\" : \"Example1\",\n \"flow\" : {\n \"IThen\" : { \n \"args\": [\n {\n \"ITask\" : {\n \"name\" : \"T1\",\n \"duration\" : {\n \"IConstant\" : {\n \"value\" : 5.0\n }\n },\n \"cost\" : {\n \"IConstant\" : {\n \"value\" : 2.0\n }\n },\n \"resources\" : [\n {\n \"resource\": \"Resource\",\n \"quantity\": 1\n }\n ],\n \"priority\" : 0\n }\n },\n {\n \"ITask\" : {\n \"name\" : \"T2\",\n \"duration\" : {\n \"IConstant\" : {\n \"value\" : 1.0\n }\n },\n \"cost\" : {\n \"IConstant\" : {\n \"value\" : 3.0\n }\n },\n \"resources\" : [\n ],\n \"priority\" : 0\n }\n }\n ] \n }\n },\n \"rate\" : {\n \"IConstant\" : {\n \"value\" : 1.0\n }\n },\n \"limit\" : 3\n }\n ],\n \"resources\" : [\n {\n \"name\": \"Resource\",\n \"capacity\": 2,\n \"costPerTick\": 1.0\n }\n ]\n} " + responses: + "200": + description: Resulting simulation metrics + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Event' + examples: + "0": + value: '{"startTime":1659355815687,"endTime":1659355815744,"startTicks":0,"endTicks":11,"tasks":[{"id":"baf4ebff-5338-472e-b2d6-9fad1a41e71f","task":"T1","caseName":"Example1#3","priority":0,"created":2,"started":5,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"a922a37e-f03f-4445-9ef1-da7bbaf46150","task":"T2","caseName":"Example1#1","priority":0,"created":5,"started":5,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"0cb717df-8808-4ea0-8539-3b04cd0d970f","task":"T2","caseName":"Example1#2","priority":0,"created":6,"started":6,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"c40a5714-f95c-423d-a60d-71a58d55350c","task":"T1","caseName":"Example1#1","priority":0,"created":0,"started":0,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"6a8cc9a6-2196-4b23-9169-3268982e5f62","task":"T2","caseName":"Example1#3","priority":0,"created":10,"started":10,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"a88f379a-d4c1-41c0-a397-78c62212c438","task":"T1","caseName":"Example1#2","priority":0,"created":1,"started":1,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false}],"cases":[{"name":"Example1#1","started":0,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#2","started":1,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#3","started":2,"duration":9,"delay":3,"tasks":2,"cost":10.0,"result":"()"}],"resources":[{"name":"Resource","capacity":2,"costPerTick":1.0,"idleUpdate":11,"load":0,"busyTime":15,"idleTime":7,"tasks":3,"cost":15.0}],"errors":[]}' + "422": + description: Unpocessable Entity - Error in requested scenario + content: + application/json: + schema: + type: string + example: Flow resources cannot be matched to the resource list. components: schemas: IRequest: - description: "A request for a simulation." required: - - arrivals - - resources + - arrivals + - resources type: object properties: arrivals: type: array + description: The arrivals of cases to simulate. items: $ref: '#/components/schemas/IArrival' - description: "The arrivals of cases to simulate." resources: type: array + description: The persistent resources to use. items: $ref: '#/components/schemas/IResource' - description: "The persistent resources to use." - start: + start: type: integer + description: The initial timestamp when the simulation starts. format: int64 - description: "The initial timestamp when the simulation starts." default: 0 - timeLimit: + timeLimit: type: integer + description: The maximum timestamp after which the simulation should stop. A limit MUST be provided if at least one arrival is infinite. format: int64 - description: "The maximum timestamp after which the simulation should stop. A limit MUST be provided if at least one arrival is infinite." + description: A request for a simulation. IArrival: - description: "An object describing the arrival of cases in the simulation at a certain rate. If no rate is provided, then a single case is generated. Each case consists of a specified flow of tasks." required: - - name - - flow + - flow + - name type: object properties: - name: + name: type: string - description: "A unique name for the arriving cases." + description: A unique name for the arriving cases. flow: $ref: '#/components/schemas/IFlow' - start: + start: type: integer + description: An optional starting time for the arrival of cases. format: int64 - description: "An optional starting time for the arrival of cases." rate: $ref: '#/components/schemas/IDistribution' limit: type: integer + description: An optional limit of how many cases to generate. format: int32 - description: "An optional limit of how many cases to generate." + description: An object describing the arrival of cases in the simulation at a certain rate. If no rate is provided, then a single case is generated. Each case consists of a specified flow of tasks. IFlow: description: "" oneOf: - - $ref: '#/components/schemas/IPar' - - $ref: '#/components/schemas/IThen' - - $ref: '#/components/schemas/ITask' + - $ref: '#/components/schemas/IPar' + - $ref: '#/components/schemas/IThen' + - $ref: '#/components/schemas/ITask' IThen: - description: "Execution of a list of flows in sequence." required: - - args + - args type: object properties: args: type: array - items: + items: $ref: '#/components/schemas/IFlow' + description: Execution of a list of flows in sequence. example: | "IThen": { args: [ @@ -413,15 +139,15 @@ components: ] } IPar: - description: "Execution of a list of flows in parallel." required: - - args + - args type: object properties: args: type: array - items: + items: $ref: '#/components/schemas/IFlow' + description: Execution of a list of flows in parallel. example: | "IPar": { args: [ @@ -430,143 +156,618 @@ components: ] } ITask: - description: "A simulated task." required: - - name - - duration - - cost - - resources - - priority + - cost + - duration + - name + - priority + - resources type: object properties: name: type: string - description: "A name for the task. Must be unique compared to other tasks in the same flow." + description: A name for the task. Must be unique compared to other tasks in the same flow. duration: $ref: '#/components/schemas/IDistribution' cost: $ref: '#/components/schemas/IDistribution' resources: type: array + description: The resources required for this task. items: $ref: '#/components/schemas/IRequiredResource' - description: "The resources required for this task." priority: type: integer + description: The priority of this task relatively to all other tasks. format: int32 - description: "The priority of this task relatively to all other tasks." - example: | - { - name: "Some Task", - duration: - "IUniform": { - "from": 3.0, - "to": 5.0 - }, - cost: - "IConstant": { - "value": 10.0 - }, - resources: [{ - resource: "Some Resource", - quantity: 1 - }], - priority: 3 - } + description: A simulated task. + example: "{\n name: \"Some Task\",\n duration:\n \"IUniform\": {\n \"from\": 3.0,\n \"to\": 5.0\n },\n cost: \n \"IConstant\": {\n \"value\": 10.0\n }, \n resources: [{\n resource: \"Some Resource\",\n quantity: 1\n }],\n priority: 3\n}\n" IResource: - description: "A persistent resource." required: - - name - - capacity - - costPerTick + - capacity + - costPerTick + - name type: object properties: name: type: string - description: "A unique name for the resource." + description: A unique name for the resource. capacity: + minimum: 1 type: integer + description: The capacity of the resource. format: int32 - minimum: 1 - description: "The capacity of the resource." costPerTick: + minimum: 0 type: number + description: The cost of using the resource per unit of time (tick). format: double - minimum: 0.0 - description: "The cost of using the resource per unit of time (tick)." + description: A persistent resource. example: - name: "Some Resource" + name: Some Resource capacity: 5 costPerTick: 4.5 IRequiredResource: - description: "A resource requirement for a task." required: - - resource - - quantity + - quantity + - resource type: object properties: resource: type: string - description: "The name of the required resource." + description: The name of the required resource. quantity: + minimum: 1 type: integer + description: The quantity (part of the capacity) of the resource required. format: int32 - minimum: 1 - description: "The quantity (part of the capacity) of the resource required." + description: A resource requirement for a task. example: - resource: "Some Resource" + resource: Some Resource quantity: 1 IDistribution: - description: "A probability distribution to produce the required value. Can either be constant, exponential, or uniform." + description: A probability distribution to produce the required value. Can either be constant, exponential, or uniform. oneOf: - - $ref: '#/components/schemas/IConstant' - - $ref: '#/components/schemas/IExp' - - $ref: '#/components/schemas/IUniform' + - $ref: '#/components/schemas/IConstant' + - $ref: '#/components/schemas/IExp' + - $ref: '#/components/schemas/IUniform' IConstant: - description: "A distribution that produces a constant number." required: - - value + - IConstant type: object properties: - value: - type: number - format: double - description: "The constant number to be produced." + IConstant: + $ref: '#/components/schemas/IConstant_IConstant' + description: A distribution that produces a constant number. example: | "IConstant": { "value": 3.0 } IExp: - description: "An exponential probability distribution." required: - - value + - IExp type: object properties: - value: - type: number - format: double - description: "The mean (lambda) value of the exponential distribution." + IExp: + $ref: '#/components/schemas/IExp_IExp' + description: An exponential probability distribution. example: | "IExp": { "value": 3.0 } IUniform: - description: "A uniform probability distribution between 2 numbers." required: - - from - - to + - IUniform + type: object + properties: + IUniform: + $ref: '#/components/schemas/IUniform_IUniform' + description: A uniform probability distribution between 2 numbers. + example: | + "IUniform": { + "from": 2.0, + "to": 10.0 + } + Metrics: + type: object + properties: + startTime: + type: integer + description: The system time in milliseconds when the simulation started (null if it never did). + format: int64 + nullable: true + endTime: + type: integer + description: The system time in milliseconds when the simulation ended (null if it never did). + format: int64 + nullable: true + startTicks: + type: integer + description: The starting simulation time. + format: int64 + endTicks: + type: integer + description: The final simulation time. + format: int64 + tasks: + type: array + description: An array of task metrics, indexed by task UUID. + items: + $ref: '#/components/schemas/TaskMetrics' + cases: + type: array + description: An array case metrics, indexed by case name. + items: + $ref: '#/components/schemas/CaseMetrics' + resources: + type: array + description: An array of resource metrics, indexed by resource name. + items: + $ref: '#/components/schemas/ResourceMetrics' + errors: + type: array + description: Errors that occurred during metrics measurement. + items: + $ref: '#/components/schemas/MetricsException' + description: Metrics related to the entire simulation. + TaskMetrics: + type: object + properties: + id: + type: string + description: The UUID of the task. + format: uuid + task: + type: string + description: The name of the task. + caseName: + type: string + description: The name of the case to which the task belongs. + priority: + type: integer + description: The numerical priority of the task. + format: int32 + created: + type: integer + description: The time when the task was created/added. + format: int64 + started: + type: integer + description: The time when the task was started or null if it never started. + format: int64 + nullable: true + duration: + type: integer + description: The actual duration of the task from start to end. + format: int64 + cost: + type: number + description: The total cost of the task, including resource costs. + format: double + resources: + type: object + additionalProperties: + type: integer + format: int32 + description: An array of resource names and corresponding capacities used. + aborted: + type: boolean + description: A flag that is true if the task was aborted and false otherwise. + description: Metrics related to individual tasks. + CaseMetrics: + type: object + properties: + name: + type: string + description: The name of the case. + started: + type: integer + description: The time when the case started. + format: int64 + duration: + type: integer + description: The total duration of the case. + format: int64 + delay: + type: integer + description: The total duration of delays (difference between created and start time) of all the tasks in this case. + format: int64 + tasks: + type: integer + description: The total number of tasks associated with the case. + format: int32 + cost: + type: number + description: The total cost of the all tasks of the case, including resource costs. + format: double + result: + type: string + description: The final output generated when the case completes. + nullable: true + description: Metrics related to individual cases. + ResourceMetrics: + type: object + properties: + name: + type: string + description: The name of the resource. + capacity: + type: integer + description: The total capacity of the resource. + format: int32 + costPerTick: + type: number + description: The cost of using the resource per unit of time (tick). + format: double + idleUpdate: + type: integer + description: Internal variable to calculate idle time. + format: int64 + load: + type: integer + description: Internal variable to calculate idle time. + format: int32 + busyTime: + type: integer + description: The total time the resource was busy multiplied per unit of capacity that was used. + format: int64 + idleTime: + type: integer + description: The total time the resource was idle multiplied per unit of capacity that was unused. + format: int64 + tasks: + type: integer + description: The total number of tasks that were attached to this resource. + format: int32 + cost: + type: number + description: The total running cost of the resource. + format: double + description: Metrics related to individual resources. + MetricsException: + description: Error thrown when encountering simulation events for an unknown object. + oneOf: + - $ref: '#/components/schemas/TaskNotFound' + - $ref: '#/components/schemas/CaseNotFound' + - $ref: '#/components/schemas/ResourceNotFound' + TaskNotFound: + type: object + properties: + taskId: + type: string + description: The UUID of the task. + format: uuid + description: Encountered simulation events for an unknown task. + CaseNotFound: + type: object + properties: + caseName: + type: string + description: The name of the case. + description: Encountered simulation events for an unknown case. + ResourceNotFound: + type: object + properties: + resourceName: + type: string + description: The name of the resource. + description: Encountered simulation events for an unknown resource. + Event: + oneOf: + - $ref: '#/components/schemas/EStart' + - $ref: '#/components/schemas/EDone' + - $ref: '#/components/schemas/ETimeLimit' + - $ref: '#/components/schemas/EResourceAdd' + - $ref: '#/components/schemas/ECaseAdd' + - $ref: '#/components/schemas/EArrivalAdd' + - $ref: '#/components/schemas/ECaseStart' + - $ref: '#/components/schemas/ECaseEnd' + - $ref: '#/components/schemas/ETaskAdd' + - $ref: '#/components/schemas/ETaskStart' + - $ref: '#/components/schemas/ETaskAttach' + - $ref: '#/components/schemas/ETaskDetach' + - $ref: '#/components/schemas/ETaskDone' + - $ref: '#/components/schemas/ETaskAbort' + - $ref: '#/components/schemas/EError' + BasicEvent: + type: object + properties: + source: + type: string + description: A name given to the simulation scenario. + default: Server Scenario + time: + type: integer + description: The simulation time when the event occurred. + format: int64 + EStart: + type: object + properties: + EStart: + allOf: + - $ref: '#/components/schemas/BasicEvent' + description: The simulation started. + EDone: + type: object + properties: + EDone: + allOf: + - $ref: '#/components/schemas/BasicEvent' + description: The simulation finished. + EError: + type: object + properties: + EError: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: string + description: A description of the error. + description: An error occurred during simulation. + ETimeLimit: + type: object + properties: + ETimeLimit: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + limit: + type: integer + description: The time limit in time units (ticks). + format: int64 + description: A time limit was set. + EResourceAdd: + type: object + properties: + EResourceAdd: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + limit: + $ref: '#/components/schemas/IResource' + description: A resource was added. + ECaseAdd: + type: object + properties: + ECaseAdd: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + name: + type: string + description: The unique name of the case instance. + start: + type: integer + description: The timestamp when the case is scheduled to start. + format: int64 + description: A case instance was added. + EArrivalAdd: + type: object + properties: + EArrivalAdd: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + name: + type: string + description: The name of the arriving cases. + start: + type: integer + description: The timestamp when arrivals are scheduled to start. + format: int64 + limit: + type: integer + description: An optional limit of the number of cases that will be generated. + format: int32 + nullable: true + description: An arrival was added. + ECaseStart: + type: object + properties: + ECaseStart: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + name: + type: string + description: The unique name of the case instance. + description: A case instance was started. + ECaseEnd: + type: object + properties: + ECaseEnd: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + name: + type: string + description: The unique name of the case instance. + result: + type: string + description: The resulting output of the case. + description: A case instance was started. + ETaskAdd: + type: object + properties: + ETaskAdd: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + task: + $ref: '#/components/schemas/TaskInstance' + description: A task instance was added in the queue. + ETaskStart: + type: object + properties: + ETaskStart: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + task: + $ref: '#/components/schemas/TaskInstance' + description: A task instance was started. + ETaskAttach: + type: object + properties: + ETaskAttach: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + task: + $ref: '#/components/schemas/TaskInstance' + resource: + $ref: '#/components/schemas/ResourceState' + description: A task instance was attached to a resource. + ETaskDetach: + type: object + properties: + ETaskDetach: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + start: + type: integer + description: The timestamp when the task was attached. + format: int64 + task: + $ref: '#/components/schemas/TaskInstance' + resource: + $ref: '#/components/schemas/ResourceState' + description: A task instance was detached from a resource. + ETaskDone: + type: object + properties: + ETaskDone: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + task: + $ref: '#/components/schemas/TaskInstance' + description: A task instance was completed. + ETaskAbort: + type: object + properties: + ETaskAbort: + allOf: + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + id: + type: string + description: The UUID of the task instance. + format: uuid + description: A task instance was aborted. + TaskInstance: + type: object + properties: + id: + type: string + description: The UUID of the task instance. + format: uuid + name: + type: string + description: The name of the task. + caseName: + type: string + description: The name of the corresponding case. + created: + type: integer + description: The timestamp when the instance was created. + format: int64 + minStartTime: + type: integer + description: The minimum time when the task can start. + format: int64 + default: 0 + resources: + type: object + additionalProperties: + type: integer + format: int32 + description: An array of resource names and corresponding capacities required. + duration: + type: integer + description: The actual duration of the task instance. + format: int64 + estimatedDuration: + type: integer + description: The a-priori estimated duration of the task instance. + format: int64 + cost: + type: number + description: The cost of the task (excluding resource costs). + format: double + interrupt: + type: integer + description: (unused) + format: int32 + default: -1 + priority: + type: integer + description: The relevant priority of this task. + format: int32 + description: An instance of a task. + ResourceState: + type: object + properties: + resource: + $ref: '#/components/schemas/IResource' + currentTasks: + type: array + description: A list of currently attached tasks and their starting times. + items: + maxItems: 2 + minItems: 2 + type: array + items: + oneOf: + - type: integer + description: The starting time of the task. + format: int64 + - $ref: '#/components/schemas/TaskInstance' + description: A description of the current state of a resource. + IConstant_IConstant: + required: + - value + type: object + properties: + value: + type: number + description: The constant number to be produced. + format: double + example: null + IExp_IExp: + required: + - value + type: object + properties: + value: + type: number + description: The mean (lambda) value of the exponential distribution. + format: double + example: null + IUniform_IUniform: + required: + - from + - to type: object properties: from: - description: "The start of the uniform range of values." type: number + description: The start of the uniform range of values. format: double to: - description: "The end of the uniform range of values." type: number + description: The end of the uniform range of values. format: double - example: | - "IUniform": { - "from": 2.0, - "to": 10.0 - } + example: null From 7f3021c119ef39f50beef0e370b116e77d67aea0 Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Mon, 1 Aug 2022 23:20:01 +0100 Subject: [PATCH 17/31] Improves `Simulator.stream` to ensure we get all the events through Reverts to `Topic.subscribeAwait`, making use of `Stream.resource`. --- .../com/workflowfm/proter/Simulator.scala | 63 ++++++++++++------- .../workflowfm/proter/events/Publisher.scala | 4 +- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/proter/src/main/scala/com/workflowfm/proter/Simulator.scala b/proter/src/main/scala/com/workflowfm/proter/Simulator.scala index 0f9dc18..2e6b5a7 100644 --- a/proter/src/main/scala/com/workflowfm/proter/Simulator.scala +++ b/proter/src/main/scala/com/workflowfm/proter/Simulator.scala @@ -100,15 +100,9 @@ final case class Simulator[F[_] : Concurrent]( */ def simulateState(name: String, state: StateT[F, Simulation[F], Seq[Event]]): F[Unit] = for { publisher <- Publisher.build[F]() - subresource = subscribers.map(publisher.subscribe(_)).parSequence - _ <- subresource.use { subs => - { - val subio = subs.map(_.compile.drain).parSequence - val pubio = simulateStateWithPublisher(name, state, publisher) - (pubio, subio).parTupled - } - } - } yield (()) + stream = getPubSubStream(name, state, publisher) + _ <- stream.compile.drain + } yield () /** * Runs and streams a simulation from a given [[state.Simulation.SimState SimState]]. @@ -123,20 +117,43 @@ final case class Simulator[F[_] : Concurrent]( def streamState( name: String, state: StateT[F, Simulation[F], Seq[Event]] - ): Stream[F, Either[Throwable, Event]] = Stream - .eval(for { - publisher <- Publisher.build[F]() - subresource = subscribers.map(publisher.subscribe(_)).parSequence - result = Stream.eval(subresource.use { subs => - { - val subio = subs.map(_.compile.drain).parSequence - val pubio = simulateStateWithPublisher(name, state, publisher) - (pubio, subio).parTupled - } - }) - stream = publisher.stream.concurrently(result) - } yield (stream)) - .flatten + ): Stream[F, Either[Throwable, Event]] = for { + publisher <- Stream.eval(Publisher.build[F]()) + stream = getPubSubStream(name, state, publisher) + ret <- Stream.resource(publisher.stream) + e <- ret.concurrently(stream) + } yield (e) + + + /** + * Creates a stream where the publisher and all subscribers run concurrently. + * + * We return the publisher stream directly if there are no subscribers as the subscriber + * stream ends immediately and blocks everything. + * + * @param name + * A name to use for the simulation. + * @param state + * The starting state. + * @param publisher + * The [[Publisher]] to use. + * @return + * A stream running the simulation and all subscribers. + */ + protected def getPubSubStream( + name: String, + state: StateT[F, Simulation[F], Seq[Event]], + publisher: Publisher[F] + ): Stream[F, Unit] = { + val pubStream = Stream.eval(simulateStateWithPublisher(name, state, publisher)) + if (subscribers.isEmpty) then pubStream + else { + val subresource = subscribers.map(publisher.subscribe(_)).parSequence + Stream.resource(subresource).flatMap( subs => + Stream(subs: _*).parJoinUnbounded.concurrently(pubStream) + ) + } + } /** * Runs a [[state.Simulation.SimState SimState]] with a given [[events.Publisher Publisher]]. diff --git a/proter/src/main/scala/com/workflowfm/proter/events/Publisher.scala b/proter/src/main/scala/com/workflowfm/proter/events/Publisher.scala index 61893fb..7e3e6c9 100644 --- a/proter/src/main/scala/com/workflowfm/proter/events/Publisher.scala +++ b/proter/src/main/scala/com/workflowfm/proter/events/Publisher.scala @@ -63,8 +63,8 @@ case class Publisher[F[_]](topic: Topic[F, Either[Throwable, Event]], maxQueued: /** * Yields a subscriber stream of [[Event]]s directly. */ - def stream: Stream[F, Either[Throwable, Event]] = - topic.subscribe(maxQueued) + def stream: Resource[F, Stream[F, Either[Throwable, Event]]] = + topic.subscribeAwait(maxQueued) } object Publisher { From 1a7afe24cd610d717df70085131e21615b5e6200 Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Mon, 1 Aug 2022 23:23:56 +0100 Subject: [PATCH 18/31] Adds small additions and improvements to the OpenAPI spec --- proter-server/docs/proterapi.yaml | 820 ++++++++++++++++++------------ 1 file changed, 484 insertions(+), 336 deletions(-) diff --git a/proter-server/docs/proterapi.yaml b/proter-server/docs/proterapi.yaml index c1257c3..e5eff7a 100644 --- a/proter-server/docs/proterapi.yaml +++ b/proter-server/docs/proterapi.yaml @@ -1,54 +1,193 @@ ---- openapi: 3.0.1 info: - title: Proter Server - description: An API for running Flow-based simulations in [Proter](http://docs.workflowfm.com/proter/). - version: "0.8" + title: "Proter Server" + description: "An API for running Flow-based simulations in Proter](http://docs.workflowfm.com/proter/)." + version: '0.8' + contact: + name: "Proter" + url: "http://docs.workflowfm.com/proter" + license: + name: "Apache 2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" servers: -- url: http://localhost:8080 + - url: http://localhost:8080 + description: "Typical localhost test server" paths: /simulate: post: - description: Perform a simulation and obtain measured metrics. + description: "Perform a simulation and obtain measured metrics." requestBody: content: application/json: schema: $ref: '#/components/schemas/IRequest' examples: - "0": - value: "{\n \"arrivals\" : [\n {\n \"name\" : \"Example1\",\n \"flow\" : {\n \"IThen\" : { \n \"args\": [\n {\n \"ITask\" : {\n \"name\" : \"T1\",\n \"duration\" : {\n \"IConstant\" : {\n \"value\" : 5.0\n }\n },\n \"cost\" : {\n \"IConstant\" : {\n \"value\" : 2.0\n }\n },\n \"resources\" : [\n {\n \"resource\": \"Resource\",\n \"quantity\": 1\n }\n ],\n \"priority\" : 0\n }\n },\n {\n \"ITask\" : {\n \"name\" : \"T2\",\n \"duration\" : {\n \"IConstant\" : {\n \"value\" : 1.0\n }\n },\n \"cost\" : {\n \"IConstant\" : {\n \"value\" : 3.0\n }\n },\n \"resources\" : [\n ],\n \"priority\" : 0\n }\n }\n ] \n }\n },\n \"rate\" : {\n \"IConstant\" : {\n \"value\" : 1.0\n }\n },\n \"limit\" : 3\n }\n ],\n \"resources\" : [\n {\n \"name\": \"Resource\",\n \"capacity\": 2,\n \"costPerTick\": 1.0\n }\n ]\n} " + '0': + value: |- + { + "arrivals" : [ + { + "name" : "Example1", + "flow" : { + "IThen" : { + "args": [ + { + "ITask" : { + "name" : "T1", + "duration" : { + "IConstant" : { + "value" : 5.0 + } + }, + "cost" : { + "IConstant" : { + "value" : 2.0 + } + }, + "resources" : [ + { + "resource": "Resource", + "quantity": 1 + } + ], + "priority" : 0 + } + }, + { + "ITask" : { + "name" : "T2", + "duration" : { + "IConstant" : { + "value" : 1.0 + } + }, + "cost" : { + "IConstant" : { + "value" : 3.0 + } + }, + "resources" : [ + ], + "priority" : 0 + } + } + ] + } + }, + "rate" : { + "IConstant" : { + "value" : 1.0 + } + }, + "limit" : 3 + } + ], + "resources" : [ + { + "name": "Resource", + "capacity": 2, + "costPerTick": 1.0 + } + ] + } responses: - "200": - description: Resulting simulation metrics + '200': + description: "Resulting simulation metrics" content: application/json: schema: $ref: '#/components/schemas/Metrics' examples: - "0": - value: '{"startTime":1659355815687,"endTime":1659355815744,"startTicks":0,"endTicks":11,"tasks":[{"id":"baf4ebff-5338-472e-b2d6-9fad1a41e71f","task":"T1","caseName":"Example1#3","priority":0,"created":2,"started":5,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"a922a37e-f03f-4445-9ef1-da7bbaf46150","task":"T2","caseName":"Example1#1","priority":0,"created":5,"started":5,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"0cb717df-8808-4ea0-8539-3b04cd0d970f","task":"T2","caseName":"Example1#2","priority":0,"created":6,"started":6,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"c40a5714-f95c-423d-a60d-71a58d55350c","task":"T1","caseName":"Example1#1","priority":0,"created":0,"started":0,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"6a8cc9a6-2196-4b23-9169-3268982e5f62","task":"T2","caseName":"Example1#3","priority":0,"created":10,"started":10,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"a88f379a-d4c1-41c0-a397-78c62212c438","task":"T1","caseName":"Example1#2","priority":0,"created":1,"started":1,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false}],"cases":[{"name":"Example1#1","started":0,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#2","started":1,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#3","started":2,"duration":9,"delay":3,"tasks":2,"cost":10.0,"result":"()"}],"resources":[{"name":"Resource","capacity":2,"costPerTick":1.0,"idleUpdate":11,"load":0,"busyTime":15,"idleTime":7,"tasks":3,"cost":15.0}],"errors":[]}' - "422": - description: Unpocessable Entity - Error in requested scenario + '0': + value: |- + {"startTime":1659355815687,"endTime":1659355815744,"startTicks":0,"endTicks":11,"tasks":[{"id":"baf4ebff-5338-472e-b2d6-9fad1a41e71f","task":"T1","caseName":"Example1#3","priority":0,"created":2,"started":5,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"a922a37e-f03f-4445-9ef1-da7bbaf46150","task":"T2","caseName":"Example1#1","priority":0,"created":5,"started":5,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"0cb717df-8808-4ea0-8539-3b04cd0d970f","task":"T2","caseName":"Example1#2","priority":0,"created":6,"started":6,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"c40a5714-f95c-423d-a60d-71a58d55350c","task":"T1","caseName":"Example1#1","priority":0,"created":0,"started":0,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"6a8cc9a6-2196-4b23-9169-3268982e5f62","task":"T2","caseName":"Example1#3","priority":0,"created":10,"started":10,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"a88f379a-d4c1-41c0-a397-78c62212c438","task":"T1","caseName":"Example1#2","priority":0,"created":1,"started":1,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false}],"cases":[{"name":"Example1#1","started":0,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#2","started":1,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#3","started":2,"duration":9,"delay":3,"tasks":2,"cost":10.0,"result":"()"}],"resources":[{"name":"Resource","capacity":2,"costPerTick":1.0,"idleUpdate":11,"load":0,"busyTime":15,"idleTime":7,"tasks":3,"cost":15.0}],"errors":[]} + '422': + description: "Unpocessable Entity - Error in requested scenario" content: application/json: schema: type: string - example: Flow resources cannot be matched to the resource list. + example: "Flow resources cannot be matched to the resource list." /stream: post: - description: Perform a simulation and obtain simulation events in chunks. + description: "Perform a simulation and obtain simulation events in chunks." requestBody: content: application/json: schema: $ref: '#/components/schemas/IRequest' examples: - "0": - value: "{\n \"arrivals\" : [\n {\n \"name\" : \"Example1\",\n \"flow\" : {\n \"IThen\" : { \n \"args\": [\n {\n \"ITask\" : {\n \"name\" : \"T1\",\n \"duration\" : {\n \"IConstant\" : {\n \"value\" : 5.0\n }\n },\n \"cost\" : {\n \"IConstant\" : {\n \"value\" : 2.0\n }\n },\n \"resources\" : [\n {\n \"resource\": \"Resource\",\n \"quantity\": 1\n }\n ],\n \"priority\" : 0\n }\n },\n {\n \"ITask\" : {\n \"name\" : \"T2\",\n \"duration\" : {\n \"IConstant\" : {\n \"value\" : 1.0\n }\n },\n \"cost\" : {\n \"IConstant\" : {\n \"value\" : 3.0\n }\n },\n \"resources\" : [\n ],\n \"priority\" : 0\n }\n }\n ] \n }\n },\n \"rate\" : {\n \"IConstant\" : {\n \"value\" : 1.0\n }\n },\n \"limit\" : 3\n }\n ],\n \"resources\" : [\n {\n \"name\": \"Resource\",\n \"capacity\": 2,\n \"costPerTick\": 1.0\n }\n ]\n} " + '0': + value: |- + { + "arrivals" : [ + { + "name" : "Example1", + "flow" : { + "IThen" : { + "args": [ + { + "ITask" : { + "name" : "T1", + "duration" : { + "IConstant" : { + "value" : 5.0 + } + }, + "cost" : { + "IConstant" : { + "value" : 2.0 + } + }, + "resources" : [ + { + "resource": "Resource", + "quantity": 1 + } + ], + "priority" : 0 + } + }, + { + "ITask" : { + "name" : "T2", + "duration" : { + "IConstant" : { + "value" : 1.0 + } + }, + "cost" : { + "IConstant" : { + "value" : 3.0 + } + }, + "resources" : [ + ], + "priority" : 0 + } + } + ] + } + }, + "rate" : { + "IConstant" : { + "value" : 1.0 + } + }, + "limit" : 3 + } + ], + "resources" : [ + { + "name": "Resource", + "capacity": 2, + "costPerTick": 1.0 + } + ] + } responses: - "200": - description: Resulting simulation metrics + '200': + description: "Resulting simulation metrics" content: application/json: schema: @@ -56,81 +195,82 @@ paths: items: $ref: '#/components/schemas/Event' examples: - "0": - value: '{"startTime":1659355815687,"endTime":1659355815744,"startTicks":0,"endTicks":11,"tasks":[{"id":"baf4ebff-5338-472e-b2d6-9fad1a41e71f","task":"T1","caseName":"Example1#3","priority":0,"created":2,"started":5,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"a922a37e-f03f-4445-9ef1-da7bbaf46150","task":"T2","caseName":"Example1#1","priority":0,"created":5,"started":5,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"0cb717df-8808-4ea0-8539-3b04cd0d970f","task":"T2","caseName":"Example1#2","priority":0,"created":6,"started":6,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"c40a5714-f95c-423d-a60d-71a58d55350c","task":"T1","caseName":"Example1#1","priority":0,"created":0,"started":0,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"6a8cc9a6-2196-4b23-9169-3268982e5f62","task":"T2","caseName":"Example1#3","priority":0,"created":10,"started":10,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"a88f379a-d4c1-41c0-a397-78c62212c438","task":"T1","caseName":"Example1#2","priority":0,"created":1,"started":1,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false}],"cases":[{"name":"Example1#1","started":0,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#2","started":1,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#3","started":2,"duration":9,"delay":3,"tasks":2,"cost":10.0,"result":"()"}],"resources":[{"name":"Resource","capacity":2,"costPerTick":1.0,"idleUpdate":11,"load":0,"busyTime":15,"idleTime":7,"tasks":3,"cost":15.0}],"errors":[]}' - "422": - description: Unpocessable Entity - Error in requested scenario + '0': + value: |- + {"startTime":1659355815687,"endTime":1659355815744,"startTicks":0,"endTicks":11,"tasks":[{"id":"baf4ebff-5338-472e-b2d6-9fad1a41e71f","task":"T1","caseName":"Example1#3","priority":0,"created":2,"started":5,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"a922a37e-f03f-4445-9ef1-da7bbaf46150","task":"T2","caseName":"Example1#1","priority":0,"created":5,"started":5,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"0cb717df-8808-4ea0-8539-3b04cd0d970f","task":"T2","caseName":"Example1#2","priority":0,"created":6,"started":6,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"c40a5714-f95c-423d-a60d-71a58d55350c","task":"T1","caseName":"Example1#1","priority":0,"created":0,"started":0,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"6a8cc9a6-2196-4b23-9169-3268982e5f62","task":"T2","caseName":"Example1#3","priority":0,"created":10,"started":10,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"a88f379a-d4c1-41c0-a397-78c62212c438","task":"T1","caseName":"Example1#2","priority":0,"created":1,"started":1,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false}],"cases":[{"name":"Example1#1","started":0,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#2","started":1,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#3","started":2,"duration":9,"delay":3,"tasks":2,"cost":10.0,"result":"()"}],"resources":[{"name":"Resource","capacity":2,"costPerTick":1.0,"idleUpdate":11,"load":0,"busyTime":15,"idleTime":7,"tasks":3,"cost":15.0}],"errors":[]} + '422': + description: "Unpocessable Entity - Error in requested scenario" content: application/json: schema: type: string - example: Flow resources cannot be matched to the resource list. + example: "Flow resources cannot be matched to the resource list." components: schemas: IRequest: + description: "A request for a simulation." required: - - arrivals - - resources + - arrivals + - resources type: object properties: arrivals: type: array - description: The arrivals of cases to simulate. items: $ref: '#/components/schemas/IArrival' + description: "The arrivals of cases to simulate." resources: type: array - description: The persistent resources to use. items: $ref: '#/components/schemas/IResource' - start: + description: "The persistent resources to use." + start: type: integer - description: The initial timestamp when the simulation starts. format: int64 + description: "The initial timestamp when the simulation starts." default: 0 - timeLimit: + timeLimit: type: integer - description: The maximum timestamp after which the simulation should stop. A limit MUST be provided if at least one arrival is infinite. format: int64 - description: A request for a simulation. + description: "The maximum timestamp after which the simulation should stop. A limit MUST be provided if at least one arrival is infinite." IArrival: + description: "An object describing the arrival of cases in the simulation at a certain rate. If no rate is provided, then a single case is generated. Each case consists of a specified flow of tasks." required: - - flow - - name + - name + - flow type: object properties: - name: + name: type: string - description: A unique name for the arriving cases. + description: "A unique name for the arriving cases." flow: $ref: '#/components/schemas/IFlow' - start: + start: type: integer - description: An optional starting time for the arrival of cases. format: int64 + description: "An optional starting time for the arrival of cases." rate: $ref: '#/components/schemas/IDistribution' limit: type: integer - description: An optional limit of how many cases to generate. format: int32 - description: An object describing the arrival of cases in the simulation at a certain rate. If no rate is provided, then a single case is generated. Each case consists of a specified flow of tasks. + description: "An optional limit of how many cases to generate." IFlow: description: "" oneOf: - - $ref: '#/components/schemas/IPar' - - $ref: '#/components/schemas/IThen' - - $ref: '#/components/schemas/ITask' + - $ref: '#/components/schemas/IPar' + - $ref: '#/components/schemas/IThen' + - $ref: '#/components/schemas/ITask' IThen: + description: "Execution of a list of flows in sequence." required: - - args + - args type: object properties: args: type: array - items: + items: $ref: '#/components/schemas/IFlow' - description: Execution of a list of flows in sequence. example: | "IThen": { args: [ @@ -139,15 +279,15 @@ components: ] } IPar: + description: "Execution of a list of flows in parallel." required: - - args + - args type: object properties: args: type: array - items: + items: $ref: '#/components/schemas/IFlow' - description: Execution of a list of flows in parallel. example: | "IPar": { args: [ @@ -156,618 +296,626 @@ components: ] } ITask: + description: "A simulated task." required: - - cost - - duration - - name - - priority - - resources + - name + - duration + - cost + - resources + - priority type: object properties: name: type: string - description: A name for the task. Must be unique compared to other tasks in the same flow. + description: "A name for the task. Must be unique compared to other tasks in the same flow." duration: $ref: '#/components/schemas/IDistribution' cost: $ref: '#/components/schemas/IDistribution' resources: type: array - description: The resources required for this task. items: $ref: '#/components/schemas/IRequiredResource' + description: "The resources required for this task." priority: type: integer - description: The priority of this task relatively to all other tasks. format: int32 - description: A simulated task. - example: "{\n name: \"Some Task\",\n duration:\n \"IUniform\": {\n \"from\": 3.0,\n \"to\": 5.0\n },\n cost: \n \"IConstant\": {\n \"value\": 10.0\n }, \n resources: [{\n resource: \"Some Resource\",\n quantity: 1\n }],\n priority: 3\n}\n" + description: "The priority of this task relatively to all other tasks." + example: | + { + name: "Some Task", + duration: + "IUniform": { + "from": 3.0, + "to": 5.0 + }, + cost: + "IConstant": { + "value": 10.0 + }, + resources: [{ + resource: "Some Resource", + quantity: 1 + }], + priority: 3 + } IResource: + description: "A persistent resource." required: - - capacity - - costPerTick - - name + - name + - capacity + - costPerTick type: object properties: name: type: string - description: A unique name for the resource. + description: "A unique name for the resource." capacity: - minimum: 1 type: integer - description: The capacity of the resource. format: int32 + minimum: 1 + description: "The capacity of the resource." costPerTick: - minimum: 0 type: number - description: The cost of using the resource per unit of time (tick). format: double - description: A persistent resource. + minimum: 0.0 + description: "The cost of using the resource per unit of time (tick)." example: - name: Some Resource + name: "Some Resource" capacity: 5 costPerTick: 4.5 IRequiredResource: + description: "A resource requirement for a task." required: - - quantity - - resource + - resource + - quantity type: object properties: resource: type: string - description: The name of the required resource. + description: "The name of the required resource." quantity: - minimum: 1 type: integer - description: The quantity (part of the capacity) of the resource required. format: int32 - description: A resource requirement for a task. + minimum: 1 + description: "The quantity (part of the capacity) of the resource required." example: - resource: Some Resource + resource: "Some Resource" quantity: 1 IDistribution: - description: A probability distribution to produce the required value. Can either be constant, exponential, or uniform. + description: "A probability distribution to produce the required value. Can either be constant, exponential, or uniform." oneOf: - - $ref: '#/components/schemas/IConstant' - - $ref: '#/components/schemas/IExp' - - $ref: '#/components/schemas/IUniform' + - $ref: '#/components/schemas/IConstant' + - $ref: '#/components/schemas/IExp' + - $ref: '#/components/schemas/IUniform' IConstant: + description: "A distribution that produces a constant number." required: - - IConstant + - IConstant type: object properties: IConstant: - $ref: '#/components/schemas/IConstant_IConstant' - description: A distribution that produces a constant number. + type: object + required: + - value + properties: + value: + type: number + format: double + description: "The constant number to be produced." example: | "IConstant": { "value": 3.0 } IExp: + description: "An exponential probability distribution." required: - - IExp + - IExp type: object properties: IExp: - $ref: '#/components/schemas/IExp_IExp' - description: An exponential probability distribution. + type: object + required: + - value + properties: + value: + type: number + format: double + description: "The mean (lambda) value of the exponential distribution." example: | "IExp": { "value": 3.0 } IUniform: + description: "A uniform probability distribution between 2 numbers." required: - - IUniform + - IUniform type: object properties: IUniform: - $ref: '#/components/schemas/IUniform_IUniform' - description: A uniform probability distribution between 2 numbers. + type: object + required: + - from + - to + properties: + from: + description: "The start of the uniform range of values." + type: number + format: double + to: + description: "The end of the uniform range of values." + type: number + format: double example: | "IUniform": { "from": 2.0, "to": 10.0 } Metrics: + description: "Metrics related to the entire simulation." type: object properties: startTime: + description: "The system time in milliseconds when the simulation started (null if it never did)." type: integer - description: The system time in milliseconds when the simulation started (null if it never did). format: int64 - nullable: true + nullable: true endTime: + description: "The system time in milliseconds when the simulation ended (null if it never did)." type: integer - description: The system time in milliseconds when the simulation ended (null if it never did). format: int64 - nullable: true + nullable: true startTicks: + description: "The starting simulation time." type: integer - description: The starting simulation time. format: int64 endTicks: + description: "The final simulation time." type: integer - description: The final simulation time. format: int64 tasks: + description: "An array of task metrics, indexed by task UUID." type: array - description: An array of task metrics, indexed by task UUID. items: $ref: '#/components/schemas/TaskMetrics' cases: + description: "An array case metrics, indexed by case name." type: array - description: An array case metrics, indexed by case name. items: $ref: '#/components/schemas/CaseMetrics' resources: + description: "An array of resource metrics, indexed by resource name." type: array - description: An array of resource metrics, indexed by resource name. items: $ref: '#/components/schemas/ResourceMetrics' errors: + description: "Errors that occurred during metrics measurement." type: array - description: Errors that occurred during metrics measurement. items: $ref: '#/components/schemas/MetricsException' - description: Metrics related to the entire simulation. TaskMetrics: + description: "Metrics related to individual tasks." type: object properties: id: + description: "The UUID of the task." type: string - description: The UUID of the task. format: uuid task: + description: "The name of the task." type: string - description: The name of the task. caseName: + description: "The name of the case to which the task belongs." type: string - description: The name of the case to which the task belongs. priority: + description: "The numerical priority of the task." type: integer - description: The numerical priority of the task. format: int32 created: + description: "The time when the task was created/added." type: integer - description: The time when the task was created/added. format: int64 started: + description: "The time when the task was started or null if it never started." type: integer - description: The time when the task was started or null if it never started. format: int64 nullable: true duration: + description: "The actual duration of the task from start to end." type: integer - description: The actual duration of the task from start to end. format: int64 cost: + description: "The total cost of the task, including resource costs." type: number - description: The total cost of the task, including resource costs. format: double resources: + description: "An array of resource names and corresponding capacities used." type: object additionalProperties: type: integer format: int32 - description: An array of resource names and corresponding capacities used. aborted: + description: "A flag that is true if the task was aborted and false otherwise." type: boolean - description: A flag that is true if the task was aborted and false otherwise. - description: Metrics related to individual tasks. CaseMetrics: + description: "Metrics related to individual cases." type: object properties: name: + description: "The name of the case." type: string - description: The name of the case. started: + description: "The time when the case started." type: integer - description: The time when the case started. format: int64 duration: + description: "The total duration of the case." type: integer - description: The total duration of the case. - format: int64 + format: int64 delay: + description: "The total duration of delays (difference between created and start time) of all the tasks in this case." type: integer - description: The total duration of delays (difference between created and start time) of all the tasks in this case. - format: int64 + format: int64 tasks: + description: "The total number of tasks associated with the case." type: integer - description: The total number of tasks associated with the case. format: int32 cost: + description: "The total cost of the all tasks of the case, including resource costs." type: number - description: The total cost of the all tasks of the case, including resource costs. format: double result: + description: "The final output generated when the case completes." type: string - description: The final output generated when the case completes. nullable: true - description: Metrics related to individual cases. ResourceMetrics: + description: "Metrics related to individual resources." type: object properties: name: + description: "The name of the resource." type: string - description: The name of the resource. capacity: + description: "The total capacity of the resource." type: integer - description: The total capacity of the resource. format: int32 costPerTick: + description: "The cost of using the resource per unit of time (tick)." type: number - description: The cost of using the resource per unit of time (tick). format: double idleUpdate: + description: "Internal variable to calculate idle time." type: integer - description: Internal variable to calculate idle time. format: int64 load: + description: "Internal variable to calculate idle time." type: integer - description: Internal variable to calculate idle time. format: int32 busyTime: + description: "The total time the resource was busy multiplied per unit of capacity that was used." type: integer - description: The total time the resource was busy multiplied per unit of capacity that was used. format: int64 idleTime: + description: "The total time the resource was idle multiplied per unit of capacity that was unused." type: integer - description: The total time the resource was idle multiplied per unit of capacity that was unused. format: int64 tasks: + description: "The total number of tasks that were attached to this resource." type: integer - description: The total number of tasks that were attached to this resource. format: int32 cost: + description: "The total running cost of the resource." type: number - description: The total running cost of the resource. format: double - description: Metrics related to individual resources. MetricsException: - description: Error thrown when encountering simulation events for an unknown object. + description: "Error thrown when encountering simulation events for an unknown object." oneOf: - - $ref: '#/components/schemas/TaskNotFound' - - $ref: '#/components/schemas/CaseNotFound' - - $ref: '#/components/schemas/ResourceNotFound' + - $ref: '#/components/schemas/TaskNotFound' + - $ref: '#/components/schemas/CaseNotFound' + - $ref: '#/components/schemas/ResourceNotFound' TaskNotFound: + description: "Encountered simulation events for an unknown task." type: object properties: taskId: + description: "The UUID of the task." type: string - description: The UUID of the task. format: uuid - description: Encountered simulation events for an unknown task. CaseNotFound: + description: "Encountered simulation events for an unknown case." type: object properties: caseName: + description: "The name of the case." type: string - description: The name of the case. - description: Encountered simulation events for an unknown case. ResourceNotFound: + description: "Encountered simulation events for an unknown resource." type: object properties: resourceName: + description: "The name of the resource." type: string - description: The name of the resource. - description: Encountered simulation events for an unknown resource. Event: oneOf: - - $ref: '#/components/schemas/EStart' - - $ref: '#/components/schemas/EDone' - - $ref: '#/components/schemas/ETimeLimit' - - $ref: '#/components/schemas/EResourceAdd' - - $ref: '#/components/schemas/ECaseAdd' - - $ref: '#/components/schemas/EArrivalAdd' - - $ref: '#/components/schemas/ECaseStart' - - $ref: '#/components/schemas/ECaseEnd' - - $ref: '#/components/schemas/ETaskAdd' - - $ref: '#/components/schemas/ETaskStart' - - $ref: '#/components/schemas/ETaskAttach' - - $ref: '#/components/schemas/ETaskDetach' - - $ref: '#/components/schemas/ETaskDone' - - $ref: '#/components/schemas/ETaskAbort' - - $ref: '#/components/schemas/EError' + - $ref: '#/components/schemas/EStart' + - $ref: '#/components/schemas/EDone' + - $ref: '#/components/schemas/ETimeLimit' + - $ref: '#/components/schemas/EResourceAdd' + - $ref: '#/components/schemas/ECaseAdd' + - $ref: '#/components/schemas/EArrivalAdd' + - $ref: '#/components/schemas/ECaseStart' + - $ref: '#/components/schemas/ECaseEnd' + - $ref: '#/components/schemas/ETaskAdd' + - $ref: '#/components/schemas/ETaskStart' + - $ref: '#/components/schemas/ETaskAttach' + - $ref: '#/components/schemas/ETaskDetach' + - $ref: '#/components/schemas/ETaskDone' + - $ref: '#/components/schemas/ETaskAbort' + - $ref: '#/components/schemas/EError' BasicEvent: type: object properties: source: + description: "A name given to the simulation scenario." + default: "Server Scenario" type: string - description: A name given to the simulation scenario. - default: Server Scenario time: + description: "The simulation time when the event occurred." type: integer - description: The simulation time when the event occurred. format: int64 EStart: + description: "The simulation started." type: object properties: EStart: allOf: - - $ref: '#/components/schemas/BasicEvent' - description: The simulation started. + - $ref: '#/components/schemas/BasicEvent' EDone: + description: "The simulation finished." type: object properties: EDone: allOf: - - $ref: '#/components/schemas/BasicEvent' - description: The simulation finished. + - $ref: '#/components/schemas/BasicEvent' EError: + description: "An error occurred during simulation." type: object properties: EError: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: string - description: A description of the error. - description: An error occurred during simulation. + - $ref: '#/components/schemas/BasicEvent' + - type: string + description: "A description of the error." ETimeLimit: + description: "A time limit was set." type: object properties: ETimeLimit: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: object - properties: - limit: - type: integer - description: The time limit in time units (ticks). - format: int64 - description: A time limit was set. + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + limit: + description: "The time limit in time units (ticks)." + type: integer + format: int64 EResourceAdd: + description: "A resource was added." type: object properties: EResourceAdd: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: object - properties: - limit: - $ref: '#/components/schemas/IResource' - description: A resource was added. + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + limit: + $ref: '#/components/schemas/IResource' ECaseAdd: + description: "A case instance was added." type: object properties: ECaseAdd: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: object - properties: - name: - type: string - description: The unique name of the case instance. - start: - type: integer - description: The timestamp when the case is scheduled to start. - format: int64 - description: A case instance was added. + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + name: + description: "The unique name of the case instance." + type: string + start: + description: "The timestamp when the case is scheduled to start." + type: integer + format: int64 EArrivalAdd: + description: "An arrival was added." type: object properties: EArrivalAdd: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: object - properties: - name: - type: string - description: The name of the arriving cases. - start: - type: integer - description: The timestamp when arrivals are scheduled to start. - format: int64 - limit: - type: integer - description: An optional limit of the number of cases that will be generated. - format: int32 - nullable: true - description: An arrival was added. + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + name: + description: "The name of the arriving cases." + type: string + start: + description: "The timestamp when arrivals are scheduled to start." + type: integer + format: int64 + limit: + description: "An optional limit of the number of cases that will be generated." + type: integer + format: int32 + nullable: true ECaseStart: + description: "A case instance was started." type: object properties: ECaseStart: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: object - properties: - name: - type: string - description: The unique name of the case instance. - description: A case instance was started. + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + name: + description: "The unique name of the case instance." + type: string ECaseEnd: + description: "A case instance was started." type: object properties: ECaseEnd: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: object - properties: - name: - type: string - description: The unique name of the case instance. - result: - type: string - description: The resulting output of the case. - description: A case instance was started. + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + name: + description: "The unique name of the case instance." + type: string + result: + description: "The resulting output of the case." + type: string ETaskAdd: + description: "A task instance was added in the queue." type: object properties: ETaskAdd: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: object - properties: - task: - $ref: '#/components/schemas/TaskInstance' - description: A task instance was added in the queue. + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + task: + $ref: '#/components/schemas/TaskInstance' ETaskStart: + description: "A task instance was started." type: object properties: ETaskStart: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: object - properties: - task: - $ref: '#/components/schemas/TaskInstance' - description: A task instance was started. + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + task: + $ref: '#/components/schemas/TaskInstance' ETaskAttach: + description: "A task instance was attached to a resource." type: object properties: ETaskAttach: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: object - properties: - task: - $ref: '#/components/schemas/TaskInstance' - resource: - $ref: '#/components/schemas/ResourceState' - description: A task instance was attached to a resource. + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + task: + $ref: '#/components/schemas/TaskInstance' + resource: + $ref: '#/components/schemas/ResourceState' ETaskDetach: + description: "A task instance was detached from a resource." type: object properties: ETaskDetach: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: object - properties: - start: - type: integer - description: The timestamp when the task was attached. - format: int64 - task: - $ref: '#/components/schemas/TaskInstance' - resource: - $ref: '#/components/schemas/ResourceState' - description: A task instance was detached from a resource. + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + start: + description: "The timestamp when the task was attached." + type: integer + format: int64 + task: + $ref: '#/components/schemas/TaskInstance' + resource: + $ref: '#/components/schemas/ResourceState' ETaskDone: + description: "A task instance was completed." type: object properties: ETaskDone: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: object - properties: - task: - $ref: '#/components/schemas/TaskInstance' - description: A task instance was completed. + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + task: + $ref: '#/components/schemas/TaskInstance' ETaskAbort: + description: "A task instance was aborted." type: object properties: ETaskAbort: allOf: - - $ref: '#/components/schemas/BasicEvent' - - type: object - properties: - id: - type: string - description: The UUID of the task instance. - format: uuid - description: A task instance was aborted. + - $ref: '#/components/schemas/BasicEvent' + - type: object + properties: + id: + description: "The UUID of the task instance." + type: string + format: uuid TaskInstance: + description: "An instance of a task." type: object properties: id: + description: "The UUID of the task instance." type: string - description: The UUID of the task instance. format: uuid name: + description: "The name of the task." type: string - description: The name of the task. caseName: + description: "The name of the corresponding case." type: string - description: The name of the corresponding case. created: + description: "The timestamp when the instance was created." type: integer - description: The timestamp when the instance was created. format: int64 minStartTime: + description: "The minimum time when the task can start." type: integer - description: The minimum time when the task can start. format: int64 default: 0 resources: + description: "An array of resource names and corresponding capacities required." type: object additionalProperties: type: integer format: int32 - description: An array of resource names and corresponding capacities required. duration: + description: "The actual duration of the task instance." type: integer - description: The actual duration of the task instance. format: int64 estimatedDuration: + description: "The a-priori estimated duration of the task instance." type: integer - description: The a-priori estimated duration of the task instance. format: int64 cost: + description: "The cost of the task (excluding resource costs)." type: number - description: The cost of the task (excluding resource costs). format: double interrupt: + description: "(unused)" type: integer - description: (unused) format: int32 default: -1 priority: + description: "The relevant priority of this task." type: integer - description: The relevant priority of this task. format: int32 - description: An instance of a task. ResourceState: - type: object - properties: - resource: - $ref: '#/components/schemas/IResource' - currentTasks: - type: array - description: A list of currently attached tasks and their starting times. - items: - maxItems: 2 - minItems: 2 + description: "A description of the current state of a resource." + type: object + properties: + resource: + $ref: '#/components/schemas/IResource' + currentTasks: + description: "A list of currently attached tasks and their starting times." type: array items: - oneOf: - - type: integer - description: The starting time of the task. - format: int64 - - $ref: '#/components/schemas/TaskInstance' - description: A description of the current state of a resource. - IConstant_IConstant: - required: - - value - type: object - properties: - value: - type: number - description: The constant number to be produced. - format: double - example: null - IExp_IExp: - required: - - value - type: object - properties: - value: - type: number - description: The mean (lambda) value of the exponential distribution. - format: double - example: null - IUniform_IUniform: - required: - - from - - to - type: object - properties: - from: - type: number - description: The start of the uniform range of values. - format: double - to: - type: number - description: The end of the uniform range of values. - format: double - example: null + type: array + minItems: 2 + maxItems: 2 + items: + oneOf: + - type: integer + format: int64 + description: "The starting time of the task." + - $ref: '#/components/schemas/TaskInstance' \ No newline at end of file From 2f3a1f1e40acdf25260d1fbe3ecaaa45da260050 Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Tue, 2 Aug 2022 14:26:02 +0100 Subject: [PATCH 19/31] Adds sbt-swagger-ui - to be tested Does not work on Windows :( --- build.sbt | 16 ++++++++++++++-- project/plugins.sbt | 1 + .../{proterapi.yaml => proter-server-api.yaml} | 0 3 files changed, 15 insertions(+), 2 deletions(-) rename proter-server/docs/{proterapi.yaml => proter-server-api.yaml} (100%) diff --git a/build.sbt b/build.sbt index 598f453..4aee2ec 100644 --- a/build.sbt +++ b/build.sbt @@ -99,15 +99,27 @@ def proterModule(name: String): Project = .settings(libraryDependencies ++= Dependencies.testAll) .dependsOn(proter % "compile->compile;test->test") +import com.fgrutsch.sbt.swaggerui.SwaggerUiConfig + lazy val root = Project(id = "proter-root", base = file(".")) + .enablePlugins(ScalaUnidocPlugin, SwaggerUiPlugin) .settings(commonSettings) .settings( publishArtifact := false, ScalaUnidoc / siteSubdirName := "api", - addMappingsToSiteDir(ScalaUnidoc / packageDoc / mappings, ScalaUnidoc / siteSubdirName) + addMappingsToSiteDir(ScalaUnidoc / packageDoc / mappings, ScalaUnidoc / siteSubdirName), + swaggerUiConfig := swaggerUiConfig.value.addUrls( + SwaggerUiConfig.Url.File( + "Proter Server", + proterServer.base / "docs" / "proter-server-api.yaml" + ), + ), + swaggerUiVersion := "4.13.0", + makeSite / siteSubdirName := "server-api", + addMappingsToSiteDir(swaggerUiGenerate / mappings, makeSite / siteSubdirName), ) .aggregate(aggregatedProjects: _*) - .enablePlugins(ScalaUnidocPlugin) + lazy val proter = Project(id = "proter", base = file("proter")) .settings(commonSettings) diff --git a/project/plugins.sbt b/project/plugins.sbt index d7a0dbd..e61aea9 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,5 +5,6 @@ addSbtPlugin("com.github.sbt" % "sbt-unidoc" % "0.5.0") addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.10") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.4.1") +addSbtPlugin("com.fgrutsch" % "sbt-swagger-ui" % "0.1.0") addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.3") addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.2.0") diff --git a/proter-server/docs/proterapi.yaml b/proter-server/docs/proter-server-api.yaml similarity index 100% rename from proter-server/docs/proterapi.yaml rename to proter-server/docs/proter-server-api.yaml From 6abdac2f25a8777508e565fa45b9bd55194eb5ac Mon Sep 17 00:00:00 2001 From: Petros Papapanagiotou Date: Tue, 2 Aug 2022 22:37:20 +0100 Subject: [PATCH 20/31] Reverts to a static swagger ui deployment --- build.sbt | 12 +-- docs/static/server-api/absolute-path.js | 14 ++++ docs/static/server-api/favicon-16x16.png | Bin 0 -> 665 bytes docs/static/server-api/favicon-32x32.png | Bin 0 -> 628 bytes docs/static/server-api/index.css | 16 ++++ docs/static/server-api/index.html | 40 +++++++++ docs/static/server-api/index.js | 17 ++++ docs/static/server-api/oauth2-redirect.html | 79 ++++++++++++++++++ .../static/server-api}/proter-server-api.yaml | 6 +- docs/static/server-api/swagger-initializer.js | 20 +++++ docs/static/server-api/swagger-ui-bundle.js | 3 + .../server-api/swagger-ui-es-bundle-core.js | 3 + .../static/server-api/swagger-ui-es-bundle.js | 3 + .../swagger-ui-standalone-preset.js | 3 + docs/static/server-api/swagger-ui.css | 4 + docs/static/server-api/swagger-ui.js | 2 + project/plugins.sbt | 1 - 17 files changed, 208 insertions(+), 15 deletions(-) create mode 100644 docs/static/server-api/absolute-path.js create mode 100644 docs/static/server-api/favicon-16x16.png create mode 100644 docs/static/server-api/favicon-32x32.png create mode 100644 docs/static/server-api/index.css create mode 100644 docs/static/server-api/index.html create mode 100644 docs/static/server-api/index.js create mode 100644 docs/static/server-api/oauth2-redirect.html rename {proter-server/docs => docs/static/server-api}/proter-server-api.yaml (76%) create mode 100644 docs/static/server-api/swagger-initializer.js create mode 100644 docs/static/server-api/swagger-ui-bundle.js create mode 100644 docs/static/server-api/swagger-ui-es-bundle-core.js create mode 100644 docs/static/server-api/swagger-ui-es-bundle.js create mode 100644 docs/static/server-api/swagger-ui-standalone-preset.js create mode 100644 docs/static/server-api/swagger-ui.css create mode 100644 docs/static/server-api/swagger-ui.js diff --git a/build.sbt b/build.sbt index 4aee2ec..6e3bd72 100644 --- a/build.sbt +++ b/build.sbt @@ -99,24 +99,14 @@ def proterModule(name: String): Project = .settings(libraryDependencies ++= Dependencies.testAll) .dependsOn(proter % "compile->compile;test->test") -import com.fgrutsch.sbt.swaggerui.SwaggerUiConfig lazy val root = Project(id = "proter-root", base = file(".")) - .enablePlugins(ScalaUnidocPlugin, SwaggerUiPlugin) + .enablePlugins(ScalaUnidocPlugin) .settings(commonSettings) .settings( publishArtifact := false, ScalaUnidoc / siteSubdirName := "api", addMappingsToSiteDir(ScalaUnidoc / packageDoc / mappings, ScalaUnidoc / siteSubdirName), - swaggerUiConfig := swaggerUiConfig.value.addUrls( - SwaggerUiConfig.Url.File( - "Proter Server", - proterServer.base / "docs" / "proter-server-api.yaml" - ), - ), - swaggerUiVersion := "4.13.0", - makeSite / siteSubdirName := "server-api", - addMappingsToSiteDir(swaggerUiGenerate / mappings, makeSite / siteSubdirName), ) .aggregate(aggregatedProjects: _*) diff --git a/docs/static/server-api/absolute-path.js b/docs/static/server-api/absolute-path.js new file mode 100644 index 0000000..af42bc8 --- /dev/null +++ b/docs/static/server-api/absolute-path.js @@ -0,0 +1,14 @@ +/* + * getAbsoluteFSPath + * @return {string} When run in NodeJS env, returns the absolute path to the current directory + * When run outside of NodeJS, will return an error message + */ +const getAbsoluteFSPath = function () { + // detect whether we are running in a browser or nodejs + if (typeof module !== "undefined" && module.exports) { + return require("path").resolve(__dirname) + } + throw new Error('getAbsoluteFSPath can only be called within a Nodejs environment'); +} + +module.exports = getAbsoluteFSPath diff --git a/docs/static/server-api/favicon-16x16.png b/docs/static/server-api/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..8b194e617af1c135e6b37939591d24ac3a5efa18 GIT binary patch literal 665 zcmV;K0%rY*P)}JKSduyL>)s!A4EhTMMEM%Q;aL6%l#xiZiF>S;#Y{N2Zz%pvTGHJduXuC6Lx-)0EGfRy*N{Tv4i8@4oJ41gw zKzThrcRe|7J~(YYIBq{SYCkn-KQm=N8$CrEK1CcqMI1dv9z#VRL_{D)L|`QmF8}}l zJ9JV`Q}p!p_4f7m_U`WQ@apR4;o;!mnU<7}iG_qr zF(e)x9~BG-3IzcG2M4an0002kNkl41`ZiN1i62V%{PM@Ry|IS_+Yc7{bb`MM~xm(7p4|kMHP&!VGuDW4kFixat zXw43VmgwEvB$hXt_u=vZ>+v4i7E}n~eG6;n4Z=zF1n?T*yg<;W6kOfxpC6nao>VR% z?fpr=asSJ&`L*wu^rLJ5Peq*PB0;alL#XazZCBxJLd&giTfw@!hW167F^`7kobi;( ze<<>qNlP|xy7S1zl@lZNIBR7#o9ybJsptO#%}P0hz~sBp00000NkvXXu0mjfUsDF? literal 0 HcmV?d00001 diff --git a/docs/static/server-api/favicon-32x32.png b/docs/static/server-api/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..249737fe44558e679f0b67134e274461d988fa98 GIT binary patch literal 628 zcmV-)0*n2LP)Ma*GM0}OV<074bNCP7P7GVd{iMr*I6y~TMLss@FjvgL~HxU z%Vvj33AwpD(Z4*$Mfx=HaU16axM zt2xG_rloN<$iy9j9I5 + + + + Swagger UI + + + + + + +
+ + + + + \ No newline at end of file diff --git a/docs/static/server-api/index.js b/docs/static/server-api/index.js new file mode 100644 index 0000000..c229ec4 --- /dev/null +++ b/docs/static/server-api/index.js @@ -0,0 +1,17 @@ +try { + module.exports.SwaggerUIBundle = require("./swagger-ui-bundle.js") + module.exports.SwaggerUIStandalonePreset = require("./swagger-ui-standalone-preset.js") +} catch(e) { + // swallow the error if there's a problem loading the assets. + // allows this module to support providing the assets for browserish contexts, + // without exploding in a Node context. + // + // see https://github.com/swagger-api/swagger-ui/issues/3291#issuecomment-311195388 + // for more information. +} + +// `absolutePath` and `getAbsoluteFSPath` are both here because at one point, +// we documented having one and actually implemented the other. +// They were both retained so we don't break anyone's code. +module.exports.absolutePath = require("./absolute-path.js") +module.exports.getAbsoluteFSPath = require("./absolute-path.js") diff --git a/docs/static/server-api/oauth2-redirect.html b/docs/static/server-api/oauth2-redirect.html new file mode 100644 index 0000000..9a25c9e --- /dev/null +++ b/docs/static/server-api/oauth2-redirect.html @@ -0,0 +1,79 @@ + + + + Swagger UI: OAuth2 Redirect + + + + + diff --git a/proter-server/docs/proter-server-api.yaml b/docs/static/server-api/proter-server-api.yaml similarity index 76% rename from proter-server/docs/proter-server-api.yaml rename to docs/static/server-api/proter-server-api.yaml index e5eff7a..ceb8775 100644 --- a/proter-server/docs/proter-server-api.yaml +++ b/docs/static/server-api/proter-server-api.yaml @@ -1,7 +1,7 @@ openapi: 3.0.1 info: title: "Proter Server" - description: "An API for running Flow-based simulations in Proter](http://docs.workflowfm.com/proter/)." + description: "An API for running Flow-based simulations in Proter." version: '0.8' contact: name: "Proter" @@ -187,7 +187,7 @@ paths: } responses: '200': - description: "Resulting simulation metrics" + description: "A list of simulation events in chunks." content: application/json: schema: @@ -197,7 +197,7 @@ paths: examples: '0': value: |- - {"startTime":1659355815687,"endTime":1659355815744,"startTicks":0,"endTicks":11,"tasks":[{"id":"baf4ebff-5338-472e-b2d6-9fad1a41e71f","task":"T1","caseName":"Example1#3","priority":0,"created":2,"started":5,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"a922a37e-f03f-4445-9ef1-da7bbaf46150","task":"T2","caseName":"Example1#1","priority":0,"created":5,"started":5,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"0cb717df-8808-4ea0-8539-3b04cd0d970f","task":"T2","caseName":"Example1#2","priority":0,"created":6,"started":6,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"c40a5714-f95c-423d-a60d-71a58d55350c","task":"T1","caseName":"Example1#1","priority":0,"created":0,"started":0,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false},{"id":"6a8cc9a6-2196-4b23-9169-3268982e5f62","task":"T2","caseName":"Example1#3","priority":0,"created":10,"started":10,"duration":1,"cost":3.0,"resources":{},"aborted":false},{"id":"a88f379a-d4c1-41c0-a397-78c62212c438","task":"T1","caseName":"Example1#2","priority":0,"created":1,"started":1,"duration":5,"cost":7.0,"resources":{"Resource":1},"aborted":false}],"cases":[{"name":"Example1#1","started":0,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#2","started":1,"duration":6,"delay":0,"tasks":2,"cost":10.0,"result":"()"},{"name":"Example1#3","started":2,"duration":9,"delay":3,"tasks":2,"cost":10.0,"result":"()"}],"resources":[{"name":"Resource","capacity":2,"costPerTick":1.0,"idleUpdate":11,"load":0,"busyTime":15,"idleTime":7,"tasks":3,"cost":15.0}],"errors":[]} + [{"EResourceAdd":{"source":"Server Scenario","time":0,"resource":{"name":"Resource","capacity":2,"costPerTick":1.0}}},{"EArrivalAdd":{"source":"Server Scenario","time":0,"name":"Example1","start":0,"limit":3}},{"EStart":{"source":"Server Scenario","time":0}},{"ECaseStart":{"source":"Server Scenario","time":0,"name":"Example1#1"}},{"ETaskAdd":{"source":"Server Scenario","time":0,"task":{"id":"2b7aade5-f291-4991-8d14-ee0f78c8e5a5","name":"T1","caseName":"Example1#1","created":0,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}}},{"ETaskStart":{"source":"Server Scenario","time":0,"task":{"id":"2b7aade5-f291-4991-8d14-ee0f78c8e5a5","name":"T1","caseName":"Example1#1","created":0,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}}},{"ETaskAttach":{"source":"Server Scenario","time":0,"task":{"id":"2b7aade5-f291-4991-8d14-ee0f78c8e5a5","name":"T1","caseName":"Example1#1","created":0,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0},"resource":{"resource":{"name":"Resource","capacity":2,"costPerTick":1.0},"currentTasks":[[0,{"id":"2b7aade5-f291-4991-8d14-ee0f78c8e5a5","name":"T1","caseName":"Example1#1","created":0,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}]]}}},{"ECaseStart":{"source":"Server Scenario","time":1,"name":"Example1#2"}},{"ETaskAdd":{"source":"Server Scenario","time":1,"task":{"id":"c2bd8eb6-a809-4178-aeb3-7f787e7dc49f","name":"T1","caseName":"Example1#2","created":1,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}}},{"ETaskStart":{"source":"Server Scenario","time":1,"task":{"id":"c2bd8eb6-a809-4178-aeb3-7f787e7dc49f","name":"T1","caseName":"Example1#2","created":1,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}}},{"ETaskAttach":{"source":"Server Scenario","time":1,"task":{"id":"c2bd8eb6-a809-4178-aeb3-7f787e7dc49f","name":"T1","caseName":"Example1#2","created":1,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0},"resource":{"resource":{"name":"Resource","capacity":2,"costPerTick":1.0},"currentTasks":[[0,{"id":"2b7aade5-f291-4991-8d14-ee0f78c8e5a5","name":"T1","caseName":"Example1#1","created":0,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}],[1,{"id":"c2bd8eb6-a809-4178-aeb3-7f787e7dc49f","name":"T1","caseName":"Example1#2","created":1,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}]]}}},{"ECaseStart":{"source":"Server Scenario","time":2,"name":"Example1#3"}},{"ETaskAdd":{"source":"Server Scenario","time":2,"task":{"id":"911890e0-10da-4daa-b8f2-e87a755d97ff","name":"T1","caseName":"Example1#3","created":2,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}}},{"ETaskDetach":{"source":"Server Scenario","time":5,"start":0,"task":{"id":"2b7aade5-f291-4991-8d14-ee0f78c8e5a5","name":"T1","caseName":"Example1#1","created":0,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0},"resource":{"resource":{"name":"Resource","capacity":2,"costPerTick":1.0},"currentTasks":[[1,{"id":"c2bd8eb6-a809-4178-aeb3-7f787e7dc49f","name":"T1","caseName":"Example1#2","created":1,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}]]}}},{"ETaskDone":{"source":"Server Scenario","time":5,"task":{"id":"2b7aade5-f291-4991-8d14-ee0f78c8e5a5","name":"T1","caseName":"Example1#1","created":0,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}}},{"ETaskAdd":{"source":"Server Scenario","time":5,"task":{"id":"c18c5bb2-58f0-47ff-8cef-cf83800581d7","name":"T2","caseName":"Example1#1","created":5,"minStartTime":0,"resources":{},"duration":1,"estimatedDuration":1,"cost":3.0,"interrupt":-1,"priority":0}}},{"ETaskStart":{"source":"Server Scenario","time":5,"task":{"id":"c18c5bb2-58f0-47ff-8cef-cf83800581d7","name":"T2","caseName":"Example1#1","created":5,"minStartTime":0,"resources":{},"duration":1,"estimatedDuration":1,"cost":3.0,"interrupt":-1,"priority":0}}},{"ETaskStart":{"source":"Server Scenario","time":5,"task":{"id":"911890e0-10da-4daa-b8f2-e87a755d97ff","name":"T1","caseName":"Example1#3","created":2,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}}},{"ETaskAttach":{"source":"Server Scenario","time":5,"task":{"id":"911890e0-10da-4daa-b8f2-e87a755d97ff","name":"T1","caseName":"Example1#3","created":2,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0},"resource":{"resource":{"name":"Resource","capacity":2,"costPerTick":1.0},"currentTasks":[[1,{"id":"c2bd8eb6-a809-4178-aeb3-7f787e7dc49f","name":"T1","caseName":"Example1#2","created":1,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}],[5,{"id":"911890e0-10da-4daa-b8f2-e87a755d97ff","name":"T1","caseName":"Example1#3","created":2,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}]]}}},{"ETaskDetach":{"source":"Server Scenario","time":6,"start":1,"task":{"id":"c2bd8eb6-a809-4178-aeb3-7f787e7dc49f","name":"T1","caseName":"Example1#2","created":1,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0},"resource":{"resource":{"name":"Resource","capacity":2,"costPerTick":1.0},"currentTasks":[[5,{"id":"911890e0-10da-4daa-b8f2-e87a755d97ff","name":"T1","caseName":"Example1#3","created":2,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}]]}}},{"ETaskDone":{"source":"Server Scenario","time":6,"task":{"id":"c2bd8eb6-a809-4178-aeb3-7f787e7dc49f","name":"T1","caseName":"Example1#2","created":1,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}}},{"ETaskDone":{"source":"Server Scenario","time":6,"task":{"id":"c18c5bb2-58f0-47ff-8cef-cf83800581d7","name":"T2","caseName":"Example1#1","created":5,"minStartTime":0,"resources":{},"duration":1,"estimatedDuration":1,"cost":3.0,"interrupt":-1,"priority":0}}},{"ETaskAdd":{"source":"Server Scenario","time":6,"task":{"id":"fb8970fb-13c8-426a-a7cc-665304e36fad","name":"T2","caseName":"Example1#2","created":6,"minStartTime":0,"resources":{},"duration":1,"estimatedDuration":1,"cost":3.0,"interrupt":-1,"priority":0}}},{"ETaskStart":{"source":"Server Scenario","time":6,"task":{"id":"fb8970fb-13c8-426a-a7cc-665304e36fad","name":"T2","caseName":"Example1#2","created":6,"minStartTime":0,"resources":{},"duration":1,"estimatedDuration":1,"cost":3.0,"interrupt":-1,"priority":0}}},{"ECaseEnd":{"source":"Server Scenario","time":6,"name":"Example1#1","result":"()"}},{"ETaskDone":{"source":"Server Scenario","time":7,"task":{"id":"fb8970fb-13c8-426a-a7cc-665304e36fad","name":"T2","caseName":"Example1#2","created":6,"minStartTime":0,"resources":{},"duration":1,"estimatedDuration":1,"cost":3.0,"interrupt":-1,"priority":0}}},{"ECaseEnd":{"source":"Server Scenario","time":7,"name":"Example1#2","result":"()"}},{"ETaskDetach":{"source":"Server Scenario","time":10,"start":5,"task":{"id":"911890e0-10da-4daa-b8f2-e87a755d97ff","name":"T1","caseName":"Example1#3","created":2,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0},"resource":{"resource":{"name":"Resource","capacity":2,"costPerTick":1.0},"currentTasks":[]}}},{"ETaskDone":{"source":"Server Scenario","time":10,"task":{"id":"911890e0-10da-4daa-b8f2-e87a755d97ff","name":"T1","caseName":"Example1#3","created":2,"minStartTime":0,"resources":{"Resource":1},"duration":5,"estimatedDuration":5,"cost":2.0,"interrupt":-1,"priority":0}}},{"ETaskAdd":{"source":"Server Scenario","time":10,"task":{"id":"9f7ac6dc-3279-4e85-8f72-9d4387b934a4","name":"T2","caseName":"Example1#3","created":10,"minStartTime":0,"resources":{},"duration":1,"estimatedDuration":1,"cost":3.0,"interrupt":-1,"priority":0}}},{"ETaskStart":{"source":"Server Scenario","time":10,"task":{"id":"9f7ac6dc-3279-4e85-8f72-9d4387b934a4","name":"T2","caseName":"Example1#3","created":10,"minStartTime":0,"resources":{},"duration":1,"estimatedDuration":1,"cost":3.0,"interrupt":-1,"priority":0}}},{"ETaskDone":{"source":"Server Scenario","time":11,"task":{"id":"9f7ac6dc-3279-4e85-8f72-9d4387b934a4","name":"T2","caseName":"Example1#3","created":10,"minStartTime":0,"resources":{},"duration":1,"estimatedDuration":1,"cost":3.0,"interrupt":-1,"priority":0}}},{"ECaseEnd":{"source":"Server Scenario","time":11,"name":"Example1#3","result":"()"}},{"EDone":{"source":"Server Scenario","time":11}}] '422': description: "Unpocessable Entity - Error in requested scenario" content: diff --git a/docs/static/server-api/swagger-initializer.js b/docs/static/server-api/swagger-initializer.js new file mode 100644 index 0000000..ca9256b --- /dev/null +++ b/docs/static/server-api/swagger-initializer.js @@ -0,0 +1,20 @@ +window.onload = function() { + // + + // the following lines will be replaced by docker/configurator, when it runs in a docker-container + window.ui = SwaggerUIBundle({ + url: "proter-server-api.yaml", + dom_id: '#swagger-ui', + deepLinking: true, + presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIStandalonePreset + ], + plugins: [ + SwaggerUIBundle.plugins.DownloadUrl + ], + layout: "StandaloneLayout" + }); + + // +}; diff --git a/docs/static/server-api/swagger-ui-bundle.js b/docs/static/server-api/swagger-ui-bundle.js new file mode 100644 index 0000000..50be00f --- /dev/null +++ b/docs/static/server-api/swagger-ui-bundle.js @@ -0,0 +1,3 @@ +/*! For license information please see swagger-ui-bundle.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SwaggerUIBundle=t():e.SwaggerUIBundle=t()}(this,(function(){return(()=>{var e={66419:(e,t,n)=>{e.exports=n(24848)},41511:(e,t,n)=>{e.exports=n(83363)},11128:(e,t,n)=>{e.exports=n(57784)},54103:(e,t,n)=>{e.exports=n(28196)},77766:(e,t,n)=>{e.exports=n(8065)},72119:(e,t,n)=>{e.exports=n(57448)},10062:(e,t,n)=>{e.exports=n(29455)},44494:(e,t,n)=>{e.exports=n(69743)},20116:(e,t,n)=>{e.exports=n(11955)},62462:(e,t,n)=>{e.exports=n(96064)},94473:(e,t,n)=>{e.exports=n(61577)},78914:(e,t,n)=>{e.exports=n(46279)},78580:(e,t,n)=>{e.exports=n(33778)},81643:(e,t,n)=>{e.exports=n(19373)},69301:(e,t,n)=>{e.exports=n(73819)},23054:(e,t,n)=>{e.exports=n(11022)},2991:(e,t,n)=>{e.exports=n(61798)},32366:(e,t,n)=>{e.exports=n(52527)},39291:(e,t,n)=>{e.exports=n(36857)},3649:(e,t,n)=>{e.exports=n(82073)},77149:(e,t,n)=>{e.exports=n(45286)},47302:(e,t,n)=>{e.exports=n(62856)},92762:(e,t,n)=>{e.exports=n(2348)},29828:(e,t,n)=>{e.exports=n(35178)},25843:(e,t,n)=>{e.exports=n(76361)},89400:(e,t,n)=>{e.exports=n(71815)},59340:(e,t,n)=>{e.exports=n(8933)},39392:(e,t,n)=>{e.exports=n(15868)},51942:(e,t,n)=>{e.exports=n(63383)},63978:(e,t,n)=>{e.exports=n(41910)},26295:(e,t,n)=>{e.exports=n(86209)},86902:(e,t,n)=>{e.exports=n(23059)},20455:(e,t,n)=>{e.exports=n(47795)},93476:(e,t,n)=>{e.exports=n(27460)},33032:(e,t,n)=>{e.exports=n(27989)},94435:(e,t,n)=>{e.exports=n(73926)},39969:(e,t,n)=>{e.exports=n(57641)},52424:(e,t,n)=>{e.exports=n(72010)},53592:(e,t,n)=>{e.exports=n(27385)},78363:(e,t,n)=>{e.exports=n(81522)},19996:(e,t,n)=>{e.exports=n(32209)},90149:(e,t,n)=>{e.exports=n(30888)},51445:(e,t,n)=>{e.exports=n(14122)},30699:(e,t,n)=>{e.exports=n(44442)},28834:(e,t,n)=>{e.exports=n(57152)},95683:(e,t,n)=>{e.exports=n(69447)},95238:(e,t,n)=>{e.exports=n(81493)},90:(e,t,n)=>{e.exports=n(86672)},12088:(e,t,n)=>{e.exports=n(60269)},189:(e,t,n)=>{e.exports=n(76094)},32752:(e,t,n)=>{e.exports=n(70573)},44341:(e,t,n)=>{e.exports=n(73685)},58377:(e,t,n)=>{e.exports=n(27533)},13038:(e,t,n)=>{e.exports=n(39057)},63263:(e,t,n)=>{e.exports=n(84710)},24889:(e,t,n)=>{e.exports=n(74303)},89356:(e,t,n)=>{e.exports=n(93799)},79542:(e,t,n)=>{e.exports=n(55122)},69798:(e,t,n)=>{e.exports=n(29531)},13535:(e,t,n)=>{e.exports=n(10856)},83863:(e,t,n)=>{e.exports=n(31524)},51446:(e,t,n)=>{e.exports=n(86600)},23882:(e,t,n)=>{e.exports=n(9759)},34243:e=>{e.exports=function(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n{var r=n(78363);e.exports=function(e){if(r(e))return e},e.exports.__esModule=!0,e.exports.default=e.exports},46868:(e,t,n)=>{var r=n(78363),o=n(34243);e.exports=function(e){if(r(e))return o(e)},e.exports.__esModule=!0,e.exports.default=e.exports},5824:e=>{e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e},e.exports.__esModule=!0,e.exports.default=e.exports},51161:(e,t,n)=>{var r=n(69798);function o(e,t,n,o,a,i,s){try{var u=e[i](s),l=u.value}catch(e){return void n(e)}u.done?t(l):r.resolve(l).then(o,a)}e.exports=function(e){return function(){var t=this,n=arguments;return new r((function(r,a){var i=e.apply(t,n);function s(e){o(i,r,a,s,u,"next",e)}function u(e){o(i,r,a,s,u,"throw",e)}s(void 0)}))}},e.exports.__esModule=!0,e.exports.default=e.exports},26394:e=>{e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},e.exports.__esModule=!0,e.exports.default=e.exports},74003:(e,t,n)=>{var r=n(13535),o=n(51445),a=n(5613),i=n(8647);function s(t,n,u){return i()?(e.exports=s=r,e.exports.__esModule=!0,e.exports.default=e.exports):(e.exports=s=function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(o(Function).apply(e,r));return n&&a(i,n.prototype),i},e.exports.__esModule=!0,e.exports.default=e.exports),s.apply(null,arguments)}e.exports=s,e.exports.__esModule=!0,e.exports.default=e.exports},69198:(e,t,n)=>{var r=n(44341);function o(e,t){for(var n=0;n{var r=n(51446),o=n(19996),a=n(78363),i=n(79299);e.exports=function(e,t){var n=void 0!==r&&o(e)||e["@@iterator"];if(!n){if(a(e)||(n=i(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var s=0,u=function(){};return{s:u,n:function(){return s>=e.length?{done:!0}:{done:!1,value:e[s++]}},e:function(e){throw e},f:u}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var l,c=!0,p=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return c=e.done,e},e:function(e){p=!0,l=e},f:function(){try{c||null==n.return||n.return()}finally{if(p)throw l}}}},e.exports.__esModule=!0,e.exports.default=e.exports},10098:(e,t,n)=>{var r=n(13535),o=n(66380),a=n(8647),i=n(214);e.exports=function(e){var t=a();return function(){var n,a=o(e);if(t){var s=o(this).constructor;n=r(a,arguments,s)}else n=a.apply(this,arguments);return i(this,n)}},e.exports.__esModule=!0,e.exports.default=e.exports},87672:(e,t,n)=>{var r=n(44341);e.exports=function(e,t,n){return t in e?r(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e},e.exports.__esModule=!0,e.exports.default=e.exports},5872:(e,t,n)=>{var r=n(12088);function o(){return e.exports=o=r||function(e){for(var t=1;t{var r=n(83863),o=n(58377),a=n(16649);function i(){return"undefined"!=typeof Reflect&&r?(e.exports=i=r,e.exports.__esModule=!0,e.exports.default=e.exports):(e.exports=i=function(e,t,n){var r=a(e,t);if(r){var i=o(r,t);return i.get?i.get.call(arguments.length<3?e:n):i.value}},e.exports.__esModule=!0,e.exports.default=e.exports),i.apply(this,arguments)}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},66380:(e,t,n)=>{var r=n(79542),o=n(24889);function a(t){return e.exports=a=r?o:function(e){return e.__proto__||o(e)},e.exports.__esModule=!0,e.exports.default=e.exports,a(t)}e.exports=a,e.exports.__esModule=!0,e.exports.default=e.exports},51379:(e,t,n)=>{var r=n(189),o=n(44341),a=n(5613);e.exports=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=r(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),o(e,"prototype",{writable:!1}),t&&a(e,t)},e.exports.__esModule=!0,e.exports.default=e.exports},3807:(e,t,n)=>{var r=n(95683);e.exports=function(e){var t;return-1!==r(t=Function.toString.call(e)).call(t,"[native code]")},e.exports.__esModule=!0,e.exports.default=e.exports},8647:(e,t,n)=>{var r=n(13535);e.exports=function(){if("undefined"==typeof Reflect||!r)return!1;if(r.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(r(Boolean,[],(function(){}))),!0}catch(e){return!1}},e.exports.__esModule=!0,e.exports.default=e.exports},85400:(e,t,n)=>{var r=n(51446),o=n(19996),a=n(53592);e.exports=function(e){if(void 0!==r&&null!=o(e)||null!=e["@@iterator"])return a(e)},e.exports.__esModule=!0,e.exports.default=e.exports},65056:(e,t,n)=>{var r=n(51446),o=n(19996);e.exports=function(e,t){var n=null==e?null:void 0!==r&&o(e)||e["@@iterator"];if(null!=n){var a,i,s=[],u=!0,l=!1;try{for(n=n.call(e);!(u=(a=n.next()).done)&&(s.push(a.value),!t||s.length!==t);u=!0);}catch(e){l=!0,i=e}finally{try{u||null==n.return||n.return()}finally{if(l)throw i}}return s}},e.exports.__esModule=!0,e.exports.default=e.exports},79736:e=>{e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},e.exports.__esModule=!0,e.exports.default=e.exports},76670:e=>{e.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},e.exports.__esModule=!0,e.exports.default=e.exports},95945:(e,t,n)=>{var r=n(89356),o=n(63263),a=n(30699),i=n(58377),s=n(28834),u=n(13038),l=n(32752),c=n(44341),p=n(87672);function f(e,t){var n=r(e);if(o){var s=o(e);t&&(s=a(s).call(s,(function(t){return i(e,t).enumerable}))),n.push.apply(n,s)}return n}e.exports=function(e){for(var t=1;t{var r=n(63263),o=n(95683),a=n(44590);e.exports=function(e,t){if(null==e)return{};var n,i,s=a(e,t);if(r){var u=r(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s},e.exports.__esModule=!0,e.exports.default=e.exports},44590:(e,t,n)=>{var r=n(89356),o=n(95683);e.exports=function(e,t){if(null==e)return{};var n,a,i={},s=r(e);for(a=0;a=0||(i[n]=e[n]);return i},e.exports.__esModule=!0,e.exports.default=e.exports},214:(e,t,n)=>{var r=n(23765).default,o=n(5824);e.exports=function(e,t){if(t&&("object"===r(t)||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return o(e)},e.exports.__esModule=!0,e.exports.default=e.exports},5613:(e,t,n)=>{var r=n(79542);function o(t,n){return e.exports=o=r||function(e,t){return e.__proto__=t,e},e.exports.__esModule=!0,e.exports.default=e.exports,o(t,n)}e.exports=o,e.exports.__esModule=!0,e.exports.default=e.exports},18777:(e,t,n)=>{var r=n(57726),o=n(65056),a=n(79299),i=n(79736);e.exports=function(e,t){return r(e)||o(e,t)||a(e,t)||i()},e.exports.__esModule=!0,e.exports.default=e.exports},16649:(e,t,n)=>{var r=n(66380);e.exports=function(e,t){for(;!Object.prototype.hasOwnProperty.call(e,t)&&null!==(e=r(e)););return e},e.exports.__esModule=!0,e.exports.default=e.exports},71064:(e,t,n)=>{var r=n(57726),o=n(85400),a=n(79299),i=n(79736);e.exports=function(e){return r(e)||o(e)||a(e)||i()},e.exports.__esModule=!0,e.exports.default=e.exports},59036:(e,t,n)=>{var r=n(46868),o=n(85400),a=n(79299),i=n(76670);e.exports=function(e){return r(e)||o(e)||a(e)||i()},e.exports.__esModule=!0,e.exports.default=e.exports},23765:(e,t,n)=>{var r=n(51446),o=n(23882);function a(t){return e.exports=a="function"==typeof r&&"symbol"==typeof o?function(e){return typeof e}:function(e){return e&&"function"==typeof r&&e.constructor===r&&e!==r.prototype?"symbol":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,a(t)}e.exports=a,e.exports.__esModule=!0,e.exports.default=e.exports},79299:(e,t,n)=>{var r=n(95238),o=n(53592),a=n(34243);e.exports=function(e,t){var n;if(e){if("string"==typeof e)return a(e,t);var i=r(n=Object.prototype.toString.call(e)).call(n,8,-1);return"Object"===i&&e.constructor&&(i=e.constructor.name),"Map"===i||"Set"===i?o(e):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?a(e,t):void 0}},e.exports.__esModule=!0,e.exports.default=e.exports},74803:(e,t,n)=>{var r=n(90),o=n(189),a=n(66380),i=n(5613),s=n(3807),u=n(74003);function l(t){var n="function"==typeof r?new r:void 0;return e.exports=l=function(e){if(null===e||!s(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==n){if(n.has(e))return n.get(e);n.set(e,t)}function t(){return u(e,arguments,a(this).constructor)}return t.prototype=o(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),i(t,e)},e.exports.__esModule=!0,e.exports.default=e.exports,l(t)}e.exports=l,e.exports.__esModule=!0,e.exports.default=e.exports},63109:(e,t,n)=>{e.exports=n(35666)},17967:(e,t)=>{"use strict";t.N=void 0;var n=/^([^\w]*)(javascript|data|vbscript)/im,r=/&#(\w+)(^\w|;)?/g,o=/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim,a=/^([^:]+):/gm,i=[".","/"];t.N=function(e){var t,s=(t=e||"",t.replace(r,(function(e,t){return String.fromCharCode(t)}))).replace(o,"").trim();if(!s)return"about:blank";if(function(e){return i.indexOf(e[0])>-1}(s))return s;var u=s.match(a);if(!u)return s;var l=u[0];return n.test(l)?"about:blank":s}},53795:(e,t,n)=>{"use strict";n.d(t,{Z:()=>H});var r=n(5872),o=n.n(r),a=n(26394),i=n.n(a),s=n(69198),u=n.n(s),l=n(5824),c=n.n(l),p=n(51379),f=n.n(p),h=n(10098),d=n.n(h),m=n(87672),v=n.n(m),g=n(77766),y=n.n(g),b=n(81643),w=n.n(b),E=n(2991),x=n.n(E),_=n(67294),S=n(43393);function k(e){return k="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},k(e)}function A(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function C(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=B(t,n),o=e||Object.keys(I({},n,{},t));return o.every(r)}function B(e,t){return function(n){if("string"==typeof n)return(0,S.is)(t[n],e[n]);if(Array.isArray(n))return(0,S.is)(D(t,n),D(e,n));throw new TypeError("Invalid key: expected Array or string: "+n)}}var F=function(e){function t(){return A(this,t),P(this,T(t).apply(this,arguments))}var n,r,o;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&N(e,t)}(t,e),n=t,r=[{key:"shouldComponentUpdate",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return!L(this.updateOnProps,this.props,e,"updateOnProps")||!L(this.updateOnStates,this.state,t,"updateOnStates")}}],r&&C(n.prototype,r),o&&C(n,o),t}(_.Component);const z=F;var U=n(23930),q=n.n(U),V=n(45697),W=n.n(V),H=function(e){f()(r,e);var t=d()(r);function r(){var e,n;i()(this,r);for(var o=arguments.length,a=new Array(o),s=0;s{"use strict";n.d(t,{Z:()=>A});var r=n(23765),o=n.n(r),a=n(26394),i=n.n(a),s=n(69198),u=n.n(s),l=n(5824),c=n.n(l),p=n(51379),f=n.n(p),h=n(10098),d=n.n(h),m=n(87672),v=n.n(m),g=n(86902),y=n.n(g),b=n(77766),w=n.n(b),E=n(67294),x=n(84564),_=n.n(x),S=n(90242),k=n(27504),A=function(e){f()(n,e);var t=d()(n);function n(e,r){var o;i()(this,n),o=t.call(this,e,r),v()(c()(o),"getDefinitionUrl",(function(){var e=o.props.specSelectors;return new(_())(e.url(),k.Z.location).toString()}));var a=(0,e.getConfigs)().validatorUrl;return o.state={url:o.getDefinitionUrl(),validatorUrl:void 0===a?"https://validator.swagger.io/validator":a},o}return u()(n,[{key:"UNSAFE_componentWillReceiveProps",value:function(e){var t=(0,e.getConfigs)().validatorUrl;this.setState({url:this.getDefinitionUrl(),validatorUrl:void 0===t?"https://validator.swagger.io/validator":t})}},{key:"render",value:function(){var e,t,n=(0,this.props.getConfigs)().spec,r=(0,S.Nm)(this.state.validatorUrl);return"object"===o()(n)&&y()(n).length?null:this.state.url&&(0,S.hW)(this.state.validatorUrl)&&(0,S.hW)(this.state.url)?E.createElement("span",{className:"float-right"},E.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:w()(e="".concat(r,"/debug?url=")).call(e,encodeURIComponent(this.state.url))},E.createElement(C,{src:w()(t="".concat(r,"?url=")).call(t,encodeURIComponent(this.state.url)),alt:"Online validator badge"}))):null}}]),n}(E.Component),C=function(e){f()(n,e);var t=d()(n);function n(e){var r;return i()(this,n),(r=t.call(this,e)).state={loaded:!1,error:!1},r}return u()(n,[{key:"componentDidMount",value:function(){var e=this,t=new Image;t.onload=function(){e.setState({loaded:!0})},t.onerror=function(){e.setState({error:!0})},t.src=this.props.src}},{key:"UNSAFE_componentWillReceiveProps",value:function(e){var t=this;if(e.src!==this.props.src){var n=new Image;n.onload=function(){t.setState({loaded:!0})},n.onerror=function(){t.setState({error:!0})},n.src=e.src}}},{key:"render",value:function(){return this.state.error?E.createElement("img",{alt:"Error"}):this.state.loaded?E.createElement("img",{src:this.props.src,alt:this.props.alt}):null}}]),n}(E.Component)},86019:(e,t,n)=>{"use strict";n.d(t,{Z:()=>me,s:()=>ve});var r=n(67294),o=n(89927);function a(e,t){if(Array.prototype.indexOf)return e.indexOf(t);for(var n=0,r=e.length;n=0;n--)!0===t(e[n])&&e.splice(n,1)}function s(e){throw new Error("Unhandled case for value: '"+e+"'")}var u=function(){function e(e){void 0===e&&(e={}),this.tagName="",this.attrs={},this.innerHTML="",this.whitespaceRegex=/\s+/,this.tagName=e.tagName||"",this.attrs=e.attrs||{},this.innerHTML=e.innerHtml||e.innerHTML||""}return e.prototype.setTagName=function(e){return this.tagName=e,this},e.prototype.getTagName=function(){return this.tagName||""},e.prototype.setAttr=function(e,t){return this.getAttrs()[e]=t,this},e.prototype.getAttr=function(e){return this.getAttrs()[e]},e.prototype.setAttrs=function(e){return Object.assign(this.getAttrs(),e),this},e.prototype.getAttrs=function(){return this.attrs||(this.attrs={})},e.prototype.setClass=function(e){return this.setAttr("class",e)},e.prototype.addClass=function(e){for(var t,n=this.getClass(),r=this.whitespaceRegex,o=n?n.split(r):[],i=e.split(r);t=i.shift();)-1===a(o,t)&&o.push(t);return this.getAttrs().class=o.join(" "),this},e.prototype.removeClass=function(e){for(var t,n=this.getClass(),r=this.whitespaceRegex,o=n?n.split(r):[],i=e.split(r);o.length&&(t=i.shift());){var s=a(o,t);-1!==s&&o.splice(s,1)}return this.getAttrs().class=o.join(" "),this},e.prototype.getClass=function(){return this.getAttrs().class||""},e.prototype.hasClass=function(e){return-1!==(" "+this.getClass()+" ").indexOf(" "+e+" ")},e.prototype.setInnerHTML=function(e){return this.innerHTML=e,this},e.prototype.setInnerHtml=function(e){return this.setInnerHTML(e)},e.prototype.getInnerHTML=function(){return this.innerHTML||""},e.prototype.getInnerHtml=function(){return this.getInnerHTML()},e.prototype.toAnchorString=function(){var e=this.getTagName(),t=this.buildAttrsStr();return["<",e,t=t?" "+t:"",">",this.getInnerHtml(),""].join("")},e.prototype.buildAttrsStr=function(){if(!this.attrs)return"";var e=this.getAttrs(),t=[];for(var n in e)e.hasOwnProperty(n)&&t.push(n+'="'+e[n]+'"');return t.join(" ")},e}();var l=function(){function e(e){void 0===e&&(e={}),this.newWindow=!1,this.truncate={},this.className="",this.newWindow=e.newWindow||!1,this.truncate=e.truncate||{},this.className=e.className||""}return e.prototype.build=function(e){return new u({tagName:"a",attrs:this.createAttrs(e),innerHtml:this.processAnchorText(e.getAnchorText())})},e.prototype.createAttrs=function(e){var t={href:e.getAnchorHref()},n=this.createCssClass(e);return n&&(t.class=n),this.newWindow&&(t.target="_blank",t.rel="noopener noreferrer"),this.truncate&&this.truncate.length&&this.truncate.length=s)return u.host.length==t?(u.host.substr(0,t-o)+n).substr(0,s+r):i(c,s).substr(0,s+r);var p="";if(u.path&&(p+="/"+u.path),u.query&&(p+="?"+u.query),p){if((c+p).length>=s)return(c+p).length==t?(c+p).substr(0,t):(c+i(p,s-c.length)).substr(0,s+r);c+=p}if(u.fragment){var f="#"+u.fragment;if((c+f).length>=s)return(c+f).length==t?(c+f).substr(0,t):(c+i(f,s-c.length)).substr(0,s+r);c+=f}if(u.scheme&&u.host){var h=u.scheme+"://";if((c+h).length0&&(d=c.substr(-1*Math.floor(s/2))),(c.substr(0,Math.ceil(s/2))+n+d).substr(0,s+r)}(e,n):"middle"===r?function(e,t,n){if(e.length<=t)return e;var r,o;null==n?(n="…",r=8,o=3):(r=n.length,o=n.length);var a=t-o,i="";return a>0&&(i=e.substr(-1*Math.floor(a/2))),(e.substr(0,Math.ceil(a/2))+n+i).substr(0,a+r)}(e,n):function(e,t,n){return function(e,t,n){var r;return e.length>t&&(null==n?(n="…",r=3):r=n.length,e=e.substring(0,t-r)+n),e}(e,t,n)}(e,n)},e}(),c=function(){function e(e){this.__jsduckDummyDocProp=null,this.matchedText="",this.offset=0,this.tagBuilder=e.tagBuilder,this.matchedText=e.matchedText,this.offset=e.offset}return e.prototype.getMatchedText=function(){return this.matchedText},e.prototype.setOffset=function(e){this.offset=e},e.prototype.getOffset=function(){return this.offset},e.prototype.getCssClassSuffixes=function(){return[this.getType()]},e.prototype.buildTag=function(){return this.tagBuilder.build(this)},e}(),p=function(e,t){return p=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},p(e,t)};function f(e,t){function n(){this.constructor=e}p(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var h=function(){return h=Object.assign||function(e){for(var t,n=1,r=arguments.length;n-1},e.isValidUriScheme=function(e){var t=e.match(this.uriSchemeRegex),n=t&&t[0].toLowerCase();return"javascript:"!==n&&"vbscript:"!==n},e.urlMatchDoesNotHaveProtocolOrDot=function(e,t){return!(!e||t&&this.hasFullProtocolRegex.test(t)||-1!==e.indexOf("."))},e.urlMatchDoesNotHaveAtLeastOneWordChar=function(e,t){return!(!e||!t)&&(!this.hasFullProtocolRegex.test(t)&&!this.hasWordCharAfterProtocolRegex.test(e))},e.hasFullProtocolRegex=/^[A-Za-z][-.+A-Za-z0-9]*:\/\//,e.uriSchemeRegex=/^[A-Za-z][-.+A-Za-z0-9]*:/,e.hasWordCharAfterProtocolRegex=new RegExp(":[^\\s]*?["+C+"]"),e.ipRegex=/[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?(:[0-9]*)?\/?$/,e}(),V=(d=new RegExp("[/?#](?:["+T+"\\-+&@#/%=~_()|'$*\\[\\]{}?!:,.;^✓]*["+T+"\\-+&@#/%=~_()|'$*\\[\\]{}✓])?"),new RegExp(["(?:","(",/(?:[A-Za-z][-.+A-Za-z0-9]{0,63}:(?![A-Za-z][-.+A-Za-z0-9]{0,63}:\/\/)(?!\d+\/?)(?:\/\/)?)/.source,M(2),")","|","(","(//)?",/(?:www\.)/.source,M(6),")","|","(","(//)?",M(10)+"\\.",L.source,"(?![-"+I+"])",")",")","(?::[0-9]+)?","(?:"+d.source+")?"].join(""),"gi")),W=new RegExp("["+T+"]"),H=function(e){function t(t){var n=e.call(this,t)||this;return n.stripPrefix={scheme:!0,www:!0},n.stripTrailingSlash=!0,n.decodePercentEncoding=!0,n.matcherRegex=V,n.wordCharRegExp=W,n.stripPrefix=t.stripPrefix,n.stripTrailingSlash=t.stripTrailingSlash,n.decodePercentEncoding=t.decodePercentEncoding,n}return f(t,e),t.prototype.parseMatches=function(e){for(var t,n=this.matcherRegex,r=this.stripPrefix,o=this.stripTrailingSlash,a=this.decodePercentEncoding,i=this.tagBuilder,s=[],u=function(){var n=t[0],u=t[1],c=t[4],p=t[5],f=t[9],h=t.index,d=p||f,m=e.charAt(h-1);if(!q.isValid(n,u))return"continue";if(h>0&&"@"===m)return"continue";if(h>0&&d&&l.wordCharRegExp.test(m))return"continue";if(/\?$/.test(n)&&(n=n.substr(0,n.length-1)),l.matchHasUnbalancedClosingParen(n))n=n.substr(0,n.length-1);else{var v=l.matchHasInvalidCharAfterTld(n,u);v>-1&&(n=n.substr(0,v))}var g=["http://","https://"].find((function(e){return!!u&&-1!==u.indexOf(e)}));if(g){var y=n.indexOf(g);n=n.substr(y),u=u.substr(y),h+=y}var w=u?"scheme":c?"www":"tld",E=!!u;s.push(new b({tagBuilder:i,matchedText:n,offset:h,urlMatchType:w,url:n,protocolUrlMatch:E,protocolRelativeMatch:!!d,stripPrefix:r,stripTrailingSlash:o,decodePercentEncoding:a}))},l=this;null!==(t=n.exec(e));)u();return s},t.prototype.matchHasUnbalancedClosingParen=function(e){var t,n=e.charAt(e.length-1);if(")"===n)t="(";else if("]"===n)t="[";else{if("}"!==n)return!1;t="{"}for(var r=0,o=0,a=e.length-1;o"===e?(m=new re(h(h({},m),{name:$()})),H()):E.test(e)||x.test(e)||":"===e||V()}function w(e){">"===e?V():E.test(e)?f=3:V()}function _(e){S.test(e)||("/"===e?f=12:">"===e?H():"<"===e?W():"="===e||k.test(e)||A.test(e)?V():f=5)}function C(e){S.test(e)?f=6:"/"===e?f=12:"="===e?f=7:">"===e?H():"<"===e?W():k.test(e)&&V()}function O(e){S.test(e)||("/"===e?f=12:"="===e?f=7:">"===e?H():"<"===e?W():k.test(e)?V():f=5)}function j(e){S.test(e)||('"'===e?f=8:"'"===e?f=9:/[>=`]/.test(e)?V():"<"===e?W():f=10)}function I(e){'"'===e&&(f=11)}function T(e){"'"===e&&(f=11)}function N(e){S.test(e)?f=4:">"===e?H():"<"===e&&W()}function P(e){S.test(e)?f=4:"/"===e?f=12:">"===e?H():"<"===e?W():(f=4,c--)}function R(e){">"===e?(m=new re(h(h({},m),{isClosing:!0})),H()):f=4}function M(t){"--"===e.substr(c,2)?(c+=2,m=new re(h(h({},m),{type:"comment"})),f=14):"DOCTYPE"===e.substr(c,7).toUpperCase()?(c+=7,m=new re(h(h({},m),{type:"doctype"})),f=20):V()}function D(e){"-"===e?f=15:">"===e?V():f=16}function L(e){"-"===e?f=18:">"===e?V():f=16}function B(e){"-"===e&&(f=17)}function F(e){f="-"===e?18:16}function z(e){">"===e?H():"!"===e?f=19:"-"===e||(f=16)}function U(e){"-"===e?f=17:">"===e?H():f=16}function q(e){">"===e?H():"<"===e&&W()}function V(){f=0,m=l}function W(){f=1,m=new re({idx:c})}function H(){var t=e.slice(d,m.idx);t&&a(t,d),"comment"===m.type?i(m.idx):"doctype"===m.type?u(m.idx):(m.isOpening&&r(m.name,m.idx),m.isClosing&&o(m.name,m.idx)),V(),d=c+1}function $(){var t=m.idx+(m.isClosing?2:1);return e.slice(t,c).toLowerCase()}d=0&&r++},onText:function(e,n){if(0===r){var a=function(e,t){if(!t.global)throw new Error("`splitRegex` must have the 'g' flag set");for(var n,r=[],o=0;n=t.exec(e);)r.push(e.substring(o,n.index)),r.push(n[0]),o=n.index+n[0].length;return r.push(e.substring(o)),r}(e,/( | |<|<|>|>|"|"|')/gi),i=n;a.forEach((function(e,n){if(n%2==0){var r=t.parseText(e,i);o.push.apply(o,r)}i+=e.length}))}},onCloseTag:function(e){n.indexOf(e)>=0&&(r=Math.max(r-1,0))},onComment:function(e){},onDoctype:function(e){}}),o=this.compactMatches(o),o=this.removeUnwantedMatches(o)},e.prototype.compactMatches=function(e){e.sort((function(e,t){return e.getOffset()-t.getOffset()}));for(var t=0;to?t:t+1;e.splice(i,1);continue}e[t+1].getOffset()/g,">"));for(var t=this.parse(e),n=[],r=0,o=0,a=t.length;o/i.test(e)}function se(){var e=[],t=new oe({stripPrefix:!1,url:!0,email:!0,replaceFn:function(t){switch(t.getType()){case"url":e.push({text:t.matchedText,url:t.getUrl()});break;case"email":e.push({text:t.matchedText,url:"mailto:"+t.getEmail().replace(/^mailto:/i,"")})}return!1}});return{links:e,autolinker:t}}function ue(e){var t,n,r,o,a,i,s,u,l,c,p,f,h,d,m=e.tokens,v=null;for(n=0,r=m.length;n=0;t--)if("link_close"!==(a=o[t]).type){if("htmltag"===a.type&&(d=a.content,/^\s]/i.test(d)&&p>0&&p--,ie(a.content)&&p++),!(p>0)&&"text"===a.type&&ae.test(a.content)){if(v||(f=(v=se()).links,h=v.autolinker),i=a.content,f.length=0,h.link(i),!f.length)continue;for(s=[],c=a.level,u=0;u1&&void 0!==arguments[1]?arguments[1]:{},n=t.useUnsafeMarkdown,r=void 0!==n&&n,o=r,a=r?[]:["style","class"];return r&&!ve.hasWarnedAboutDeprecation&&(console.warn("useUnsafeMarkdown display configuration parameter is deprecated since >3.26.0 and will be removed in v4.0.0."),ve.hasWarnedAboutDeprecation=!0),pe().sanitize(e,{ADD_ATTR:["target"],FORBID_TAGS:["style","form"],ALLOW_DATA_ATTR:o,FORBID_ATTR:a})}ve.hasWarnedAboutDeprecation=!1},45308:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>f});var r,o=n(78914),a=n.n(o),i=n(69301),s=n.n(i),u=n(90242),l=n(27621),c=n(95102),p={};const f=p;a()(r=s()(c).call(c)).call(r,(function(e){if("./index.js"!==e){var t=c(e);p[(0,u.Zl)(e)]=t.default?t.default:t}})),p.SafeRender=l.default},55812:(e,t,n)=>{"use strict";n.r(t),n.d(t,{SHOW_AUTH_POPUP:()=>h,AUTHORIZE:()=>d,LOGOUT:()=>m,PRE_AUTHORIZE_OAUTH2:()=>v,AUTHORIZE_OAUTH2:()=>g,VALIDATE:()=>y,CONFIGURE_AUTH:()=>b,RESTORE_AUTHORIZATION:()=>w,showDefinitions:()=>E,authorize:()=>x,authorizeWithPersistOption:()=>_,logout:()=>S,logoutWithPersistOption:()=>k,preAuthorizeImplicit:()=>A,authorizeOauth2:()=>C,authorizeOauth2WithPersistOption:()=>O,authorizePassword:()=>j,authorizeApplication:()=>I,authorizeAccessCodeWithFormParams:()=>T,authorizeAccessCodeWithBasicAuthentication:()=>N,authorizeRequest:()=>P,configureAuth:()=>R,restoreAuthorization:()=>M,persistAuthorizationIfNeeded:()=>D,authPopup:()=>L});var r=n(23765),o=n.n(r),a=n(59340),i=n.n(a),s=n(51942),u=n.n(s),l=n(84564),c=n.n(l),p=n(27504),f=n(90242),h="show_popup",d="authorize",m="logout",v="pre_authorize_oauth2",g="authorize_oauth2",y="validate",b="configure_auth",w="restore_authorization";function E(e){return{type:h,payload:e}}function x(e){return{type:d,payload:e}}var _=function(e){return function(t){var n=t.authActions;n.authorize(e),n.persistAuthorizationIfNeeded()}};function S(e){return{type:m,payload:e}}var k=function(e){return function(t){var n=t.authActions;n.logout(e),n.persistAuthorizationIfNeeded()}},A=function(e){return function(t){var n=t.authActions,r=t.errActions,o=e.auth,a=e.token,s=e.isValid,u=o.schema,l=o.name,c=u.get("flow");delete p.Z.swaggerUIRedirectOauth2,"accessCode"===c||s||r.newAuthErr({authId:l,source:"auth",level:"warning",message:"Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"}),a.error?r.newAuthErr({authId:l,source:"auth",level:"error",message:i()(a)}):n.authorizeOauth2WithPersistOption({auth:o,token:a})}};function C(e){return{type:g,payload:e}}var O=function(e){return function(t){var n=t.authActions;n.authorizeOauth2(e),n.persistAuthorizationIfNeeded()}},j=function(e){return function(t){var n=t.authActions,r=e.schema,o=e.name,a=e.username,i=e.password,s=e.passwordType,l=e.clientId,c=e.clientSecret,p={grant_type:"password",scope:e.scopes.join(" "),username:a,password:i},h={};switch(s){case"request-body":!function(e,t,n){t&&u()(e,{client_id:t});n&&u()(e,{client_secret:n})}(p,l,c);break;case"basic":h.Authorization="Basic "+(0,f.r3)(l+":"+c);break;default:console.warn("Warning: invalid passwordType ".concat(s," was passed, not including client id and secret"))}return n.authorizeRequest({body:(0,f.GZ)(p),url:r.get("tokenUrl"),name:o,headers:h,query:{},auth:e})}};var I=function(e){return function(t){var n=t.authActions,r=e.schema,o=e.scopes,a=e.name,i=e.clientId,s=e.clientSecret,u={Authorization:"Basic "+(0,f.r3)(i+":"+s)},l={grant_type:"client_credentials",scope:o.join(" ")};return n.authorizeRequest({body:(0,f.GZ)(l),name:a,url:r.get("tokenUrl"),auth:e,headers:u})}},T=function(e){var t=e.auth,n=e.redirectUrl;return function(e){var r=e.authActions,o=t.schema,a=t.name,i=t.clientId,s=t.clientSecret,u=t.codeVerifier,l={grant_type:"authorization_code",code:t.code,client_id:i,client_secret:s,redirect_uri:n,code_verifier:u};return r.authorizeRequest({body:(0,f.GZ)(l),name:a,url:o.get("tokenUrl"),auth:t})}},N=function(e){var t=e.auth,n=e.redirectUrl;return function(e){var r=e.authActions,o=t.schema,a=t.name,i=t.clientId,s=t.clientSecret,u=t.codeVerifier,l={Authorization:"Basic "+(0,f.r3)(i+":"+s)},c={grant_type:"authorization_code",code:t.code,client_id:i,redirect_uri:n,code_verifier:u};return r.authorizeRequest({body:(0,f.GZ)(c),name:a,url:o.get("tokenUrl"),auth:t,headers:l})}},P=function(e){return function(t){var n,r=t.fn,a=t.getConfigs,s=t.authActions,l=t.errActions,p=t.oas3Selectors,f=t.specSelectors,h=t.authSelectors,d=e.body,m=e.query,v=void 0===m?{}:m,g=e.headers,y=void 0===g?{}:g,b=e.name,w=e.url,E=e.auth,x=(h.getConfigs()||{}).additionalQueryStringParams;if(f.isOAS3()){var _=p.serverEffectiveValue(p.selectedServer());n=c()(w,_,!0)}else n=c()(w,f.url(),!0);"object"===o()(x)&&(n.query=u()({},n.query,x));var S=n.toString(),k=u()({Accept:"application/json, text/plain, */*","Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"},y);r.fetch({url:S,method:"post",headers:k,query:v,body:d,requestInterceptor:a().requestInterceptor,responseInterceptor:a().responseInterceptor}).then((function(e){var t=JSON.parse(e.data),n=t&&(t.error||""),r=t&&(t.parseError||"");e.ok?n||r?l.newAuthErr({authId:b,level:"error",source:"auth",message:i()(t)}):s.authorizeOauth2WithPersistOption({auth:E,token:t}):l.newAuthErr({authId:b,level:"error",source:"auth",message:e.statusText})})).catch((function(e){var t=new Error(e).message;if(e.response&&e.response.data){var n=e.response.data;try{var r="string"==typeof n?JSON.parse(n):n;r.error&&(t+=", error: ".concat(r.error)),r.error_description&&(t+=", description: ".concat(r.error_description))}catch(e){}}l.newAuthErr({authId:b,level:"error",source:"auth",message:t})}))}};function R(e){return{type:b,payload:e}}function M(e){return{type:w,payload:e}}var D=function(){return function(e){var t=e.authSelectors;if((0,e.getConfigs)().persistAuthorization){var n=t.authorized();localStorage.setItem("authorized",i()(n.toJS()))}}},L=function(e,t){return function(){p.Z.swaggerUIRedirectOauth2=t,p.Z.open(e)}}},93705:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>h,preauthorizeBasic:()=>d,preauthorizeApiKey:()=>m});var r=n(87672),o=n.n(r),a=n(54103),i=n.n(a),s=n(77766),u=n.n(s),l=n(43962),c=n(55812),p=n(60035),f=n(48302);function h(){return{afterLoad:function(e){this.rootInjects=this.rootInjects||{},this.rootInjects.initOAuth=e.authActions.configureAuth,this.rootInjects.preauthorizeApiKey=i()(m).call(m,null,e),this.rootInjects.preauthorizeBasic=i()(d).call(d,null,e)},statePlugins:{auth:{reducers:l.default,actions:c,selectors:p},spec:{wrapActions:f}}}}function d(e,t,n,r){var a,i=e.authActions.authorize,s=e.specSelectors,l=s.specJson,c=(0,s.isOAS3)()?["components","securitySchemes"]:["securityDefinitions"],p=l().getIn(u()(a=[]).call(a,c,[t]));return p?i(o()({},t,{value:{username:n,password:r},schema:p.toJS()})):null}function m(e,t,n){var r,a=e.authActions.authorize,i=e.specSelectors,s=i.specJson,l=(0,i.isOAS3)()?["components","securitySchemes"]:["securityDefinitions"],c=s().getIn(u()(r=[]).call(r,l,[t]));return c?a(o()({},t,{value:n,schema:c.toJS()})):null}},43962:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>m});var r,o=n(87672),a=n.n(o),i=n(18777),s=n.n(i),u=n(78914),l=n.n(u),c=n(51942),p=n.n(c),f=n(43393),h=n(90242),d=n(55812);const m=(r={},a()(r,d.SHOW_AUTH_POPUP,(function(e,t){var n=t.payload;return e.set("showDefinitions",n)})),a()(r,d.AUTHORIZE,(function(e,t){var n,r=t.payload,o=(0,f.fromJS)(r),a=e.get("authorized")||(0,f.Map)();return l()(n=o.entrySeq()).call(n,(function(t){var n=s()(t,2),r=n[0],o=n[1];if(!(0,h.Wl)(o.getIn))return e.set("authorized",a);var i=o.getIn(["schema","type"]);if("apiKey"===i||"http"===i)a=a.set(r,o);else if("basic"===i){var u=o.getIn(["value","username"]),l=o.getIn(["value","password"]);a=(a=a.setIn([r,"value"],{username:u,header:"Basic "+(0,h.r3)(u+":"+l)})).setIn([r,"schema"],o.get("schema"))}})),e.set("authorized",a)})),a()(r,d.AUTHORIZE_OAUTH2,(function(e,t){var n,r=t.payload,o=r.auth,a=r.token;o.token=p()({},a),n=(0,f.fromJS)(o);var i=e.get("authorized")||(0,f.Map)();return i=i.set(n.get("name"),n),e.set("authorized",i)})),a()(r,d.LOGOUT,(function(e,t){var n=t.payload,r=e.get("authorized").withMutations((function(e){l()(n).call(n,(function(t){e.delete(t)}))}));return e.set("authorized",r)})),a()(r,d.CONFIGURE_AUTH,(function(e,t){var n=t.payload;return e.set("configs",n)})),a()(r,d.RESTORE_AUTHORIZATION,(function(e,t){var n=t.payload;return e.set("authorized",(0,f.fromJS)(n.authorized))})),r)},60035:(e,t,n)=>{"use strict";n.r(t),n.d(t,{shownDefinitions:()=>w,definitionsToAuthorize:()=>E,getDefinitionsByNames:()=>x,definitionsForRequirements:()=>_,authorized:()=>S,isAuthorized:()=>k,getConfigs:()=>A});var r=n(18777),o=n.n(r),a=n(78914),i=n.n(a),s=n(20116),u=n.n(s),l=n(77149),c=n.n(l),p=n(81643),f=n.n(p),h=n(2991),d=n.n(h),m=n(86902),v=n.n(m),g=n(20573),y=n(43393),b=function(e){return e},w=(0,g.P1)(b,(function(e){return e.get("showDefinitions")})),E=(0,g.P1)(b,(function(){return function(e){var t,n=e.specSelectors.securityDefinitions()||(0,y.Map)({}),r=(0,y.List)();return i()(t=n.entrySeq()).call(t,(function(e){var t=o()(e,2),n=t[0],a=t[1],i=(0,y.Map)();i=i.set(n,a),r=r.push(i)})),r}})),x=function(e,t){return function(e){var n,r=e.specSelectors;console.warn("WARNING: getDefinitionsByNames is deprecated and will be removed in the next major version.");var a=r.securityDefinitions(),s=(0,y.List)();return i()(n=t.valueSeq()).call(n,(function(e){var t,n=(0,y.Map)();i()(t=e.entrySeq()).call(t,(function(e){var t,r,s=o()(e,2),u=s[0],l=s[1],c=a.get(u);"oauth2"===c.get("type")&&l.size&&(t=c.get("scopes"),i()(r=t.keySeq()).call(r,(function(e){l.contains(e)||(t=t.delete(e))})),c=c.set("allowedScopes",t));n=n.set(u,c)})),s=s.push(n)})),s}},_=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:(0,y.List)();return function(e){var n=e.authSelectors.definitionsToAuthorize()||(0,y.List)();return u()(n).call(n,(function(e){return c()(t).call(t,(function(t){return t.get(e.keySeq().first())}))}))}},S=(0,g.P1)(b,(function(e){return e.get("authorized")||(0,y.Map)()})),k=function(e,t){return function(e){var n,r=e.authSelectors.authorized();return y.List.isList(t)?!!u()(n=t.toJS()).call(n,(function(e){var t,n;return-1===f()(t=d()(n=v()(e)).call(n,(function(e){return!!r.get(e)}))).call(t,!1)})).length:null}},A=(0,g.P1)(b,(function(e){return e.get("configs")}))},48302:(e,t,n)=>{"use strict";n.r(t),n.d(t,{execute:()=>a});var r=n(95945),o=n.n(r),a=function(e,t){var n=t.authSelectors,r=t.specSelectors;return function(t){var a=t.path,i=t.method,s=t.operation,u=t.extras,l={authorized:n.authorized()&&n.authorized().toJS(),definitions:r.securityDefinitions()&&r.securityDefinitions().toJS(),specSecurity:r.security()&&r.security().toJS()};return e(o()({path:a,method:i,operation:s,securities:l},u))}}},70714:(e,t,n)=>{"use strict";n.r(t),n.d(t,{UPDATE_CONFIGS:()=>a,TOGGLE_CONFIGS:()=>i,update:()=>s,toggle:()=>u,loaded:()=>l});var r=n(87672),o=n.n(r),a="configs_update",i="configs_toggle";function s(e,t){return{type:a,payload:o()({},e,t)}}function u(e){return{type:i,payload:e}}var l=function(){return function(e){var t=e.getConfigs,n=e.authActions;if(t().persistAuthorization){var r=localStorage.getItem("authorized");r&&n.restoreAuthorization({authorized:JSON.parse(r)})}}}},92256:(e,t,n)=>{"use strict";n.r(t),n.d(t,{parseYamlConfig:()=>o});var r=n(1272),o=function(e,t){try{return r.ZP.load(e)}catch(e){return t&&t.errActions.newThrownErr(new Error(e)),{}}}},1661:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>c});var r=n(15163),o=n(92256),a=n(70714),i=n(22698),s=n(69018),u=n(37743),l={getLocalConfig:function(){return(0,o.parseYamlConfig)(r)}};function c(){return{statePlugins:{spec:{actions:i,selectors:l},configs:{reducers:u.default,actions:a,selectors:s}}}}},37743:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>u});var r,o=n(87672),a=n.n(o),i=n(43393),s=n(70714);const u=(r={},a()(r,s.UPDATE_CONFIGS,(function(e,t){return e.merge((0,i.fromJS)(t.payload))})),a()(r,s.TOGGLE_CONFIGS,(function(e,t){var n=t.payload,r=e.get(n);return e.set(n,!r)})),r)},69018:(e,t,n)=>{"use strict";n.r(t),n.d(t,{get:()=>a});var r=n(41511),o=n.n(r),a=function(e,t){return e.getIn(o()(t)?t:[t])}},22698:(e,t,n)=>{"use strict";n.r(t),n.d(t,{downloadConfig:()=>o,getConfigByUrl:()=>a});var r=n(92256),o=function(e){return function(t){return(0,t.fn.fetch)(e)}},a=function(e,t){return function(n){var o=n.specActions;if(e)return o.downloadConfig(e).then(a,a);function a(n){n instanceof Error||n.status>=400?(o.updateLoadingStatus("failedConfig"),o.updateLoadingStatus("failedConfig"),o.updateUrl(""),console.error(n.statusText+" "+e.url),t(null)):t((0,r.parseYamlConfig)(n.text))}}}},31970:(e,t,n)=>{"use strict";n.r(t),n.d(t,{setHash:()=>r});var r=function(e){return e?history.pushState(null,null,"#".concat(e)):window.location.hash=""}},34980:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>i});var r=n(41599),o=n(60877),a=n(34584);function i(){return[r.default,{statePlugins:{configs:{wrapActions:{loaded:function(e,t){return function(){e.apply(void 0,arguments);var n=decodeURIComponent(window.location.hash);t.layoutActions.parseDeepLinkHash(n)}}}}},wrapComponents:{operation:o.default,OperationTag:a.default}}]}},41599:(e,t,n)=>{"use strict";n.r(t),n.d(t,{show:()=>A,scrollTo:()=>C,parseDeepLinkHash:()=>O,readyToScroll:()=>j,scrollToElement:()=>I,clearScrollTo:()=>T,default:()=>N});var r,o=n(87672),a=n.n(o),i=n(18777),s=n.n(i),u=n(41511),l=n.n(u),c=n(77766),p=n.n(c),f=n(3649),h=n.n(f),d=n(2991),m=n.n(d),v=n(81643),g=n.n(v),y=n(31970),b=n(45172),w=n.n(b),E=n(90242),x=n(43393),_=n.n(x),S="layout_scroll_to",k="layout_clear_scroll",A=function(e,t){var n=t.getConfigs,r=t.layoutSelectors;return function(){for(var t=arguments.length,o=new Array(t),a=0;a-1&&(console.warn("Warning: escaping deep link whitespace with `_` will be unsupported in v4.0, use `%20` instead."),n.show(m()(y).call(y,(function(e){return e.replace(/_/g," ")})),!0)),n.show(y,!0)}(g()(f).call(f,"_")>-1||g()(v).call(v,"_")>-1)&&(console.warn("Warning: escaping deep link whitespace with `_` will be unsupported in v4.0, use `%20` instead."),n.show(m()(u).call(u,(function(e){return e.replace(/_/g," ")})),!0)),n.show(u,!0),n.scrollTo(u)}}},j=function(e,t){return function(n){var r=n.layoutSelectors.getScrollToKey();_().is(r,(0,x.fromJS)(e))&&(n.layoutActions.scrollToElement(t),n.layoutActions.clearScrollTo())}},I=function(e,t){return function(n){try{t=t||n.fn.getScrollParent(e),w().createScroller(t).to(e)}catch(e){console.error(e)}}},T=function(){return{type:k}};const N={fn:{getScrollParent:function(e,t){var n=document.documentElement,r=getComputedStyle(e),o="absolute"===r.position,a=t?/(auto|scroll|hidden)/:/(auto|scroll)/;if("fixed"===r.position)return n;for(var i=e;i=i.parentElement;)if(r=getComputedStyle(i),(!o||"static"!==r.position)&&a.test(r.overflow+r.overflowY+r.overflowX))return i;return n}},statePlugins:{layout:{actions:{scrollToElement:I,scrollTo:C,clearScrollTo:T,readyToScroll:j,parseDeepLinkHash:O},selectors:{getScrollToKey:function(e){return e.get("scrollToKey")},isShownKeyFromUrlHashArray:function(e,t){var n=s()(t,2),r=n[0],o=n[1];return o?["operations",r,o]:r?["operations-tag",r]:[]},urlHashArrayFromIsShownKey:function(e,t){var n=s()(t,3),r=n[0],o=n[1],a=n[2];return"operations"==r?[o,a]:"operations-tag"==r?[o]:[]}},reducers:(r={},a()(r,S,(function(e,t){return e.set("scrollToKey",_().fromJS(t.payload))})),a()(r,k,(function(e){return e.delete("scrollToKey")})),r),wrapActions:{show:A}}}}},34584:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>y});var r=n(26394),o=n.n(r),a=n(69198),i=n.n(a),s=n(5824),u=n.n(s),l=n(51379),c=n.n(l),p=n(10098),f=n.n(p),h=n(87672),d=n.n(h),m=n(77766),v=n.n(m),g=n(67294);const y=function(e,t){return function(n){c()(a,n);var r=f()(a);function a(){var e,n;o()(this,a);for(var i=arguments.length,s=new Array(i),l=0;l{"use strict";n.r(t),n.d(t,{default:()=>y});var r=n(26394),o=n.n(r),a=n(69198),i=n.n(a),s=n(5824),u=n.n(s),l=n(51379),c=n.n(l),p=n(10098),f=n.n(p),h=n(87672),d=n.n(h),m=n(77766),v=n.n(m),g=n(67294);n(23930);const y=function(e,t){return function(n){c()(a,n);var r=f()(a);function a(){var e,n;o()(this,a);for(var i=arguments.length,s=new Array(i),l=0;l{"use strict";n.r(t),n.d(t,{default:()=>v});var r=n(51942),o=n.n(r),a=n(39969),i=n.n(a),s=n(77766),u=n.n(s),l=n(81643),c=n.n(l),p=n(59340),f=n.n(p),h=n(20573),d=n(43393),m=n(27504);function v(e){var t=e.fn;return{statePlugins:{spec:{actions:{download:function(e){return function(n){var r=n.errActions,a=n.specSelectors,s=n.specActions,l=n.getConfigs,c=t.fetch,p=l();function f(t){if(t instanceof Error||t.status>=400)return s.updateLoadingStatus("failed"),r.newThrownErr(o()(new Error((t.message||t.statusText)+" "+e),{source:"fetch"})),void(!t.status&&t instanceof Error&&function(){try{var t;if("URL"in m.Z?t=new(i())(e):(t=document.createElement("a")).href=e,"https:"!==t.protocol&&"https:"===m.Z.location.protocol){var n=o()(new Error("Possible mixed-content issue? The page was loaded over https:// but a ".concat(t.protocol,"// URL was specified. Check that you are not attempting to load mixed content.")),{source:"fetch"});return void r.newThrownErr(n)}if(t.origin!==m.Z.location.origin){var a,s=o()(new Error(u()(a="Possible cross-origin (CORS) issue? The URL origin (".concat(t.origin,") does not match the page (")).call(a,m.Z.location.origin,"). Check the server returns the correct 'Access-Control-Allow-*' headers.")),{source:"fetch"});r.newThrownErr(s)}}catch(e){return}}());s.updateLoadingStatus("success"),s.updateSpec(t.text),a.url()!==e&&s.updateUrl(e)}e=e||a.url(),s.updateLoadingStatus("loading"),r.clear({source:"fetch"}),c({url:e,loadSpec:!0,requestInterceptor:p.requestInterceptor||function(e){return e},responseInterceptor:p.responseInterceptor||function(e){return e},credentials:"same-origin",headers:{Accept:"application/json,*/*"}}).then(f,f)}},updateLoadingStatus:function(e){var t,n=[null,"loading","failed","success","failedConfig"];-1===c()(n).call(n,e)&&console.error(u()(t="Error: ".concat(e," is not one of ")).call(t,f()(n)));return{type:"spec_update_loading_status",payload:e}}},reducers:{spec_update_loading_status:function(e,t){return"string"==typeof t.payload?e.set("loadingStatus",t.payload):e}},selectors:{loadingStatus:(0,h.P1)((function(e){return e||(0,d.Map)()}),(function(e){return e.get("loadingStatus")||null}))}}}}}},34966:(e,t,n)=>{"use strict";n.r(t),n.d(t,{NEW_THROWN_ERR:()=>o,NEW_THROWN_ERR_BATCH:()=>a,NEW_SPEC_ERR:()=>i,NEW_SPEC_ERR_BATCH:()=>s,NEW_AUTH_ERR:()=>u,CLEAR:()=>l,CLEAR_BY:()=>c,newThrownErr:()=>p,newThrownErrBatch:()=>f,newSpecErr:()=>h,newSpecErrBatch:()=>d,newAuthErr:()=>m,clear:()=>v,clearBy:()=>g});var r=n(7710),o="err_new_thrown_err",a="err_new_thrown_err_batch",i="err_new_spec_err",s="err_new_spec_err_batch",u="err_new_auth_err",l="err_clear",c="err_clear_by";function p(e){return{type:o,payload:(0,r.serializeError)(e)}}function f(e){return{type:a,payload:e}}function h(e){return{type:i,payload:e}}function d(e){return{type:s,payload:e}}function m(e){return{type:u,payload:e}}function v(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return{type:l,payload:e}}function g(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){return!0};return{type:c,payload:e}}},56982:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>c});var r=n(20116),o=n.n(r),a=n(2991),i=n.n(a),s=n(54061),u=n.n(s),l=[n(2392),n(21835)];function c(e){var t,n={jsSpec:{}},r=u()(l,(function(e,t){try{var r=t.transform(e,n);return o()(r).call(r,(function(e){return!!e}))}catch(t){return console.error("Transformer error:",t),e}}),e);return i()(t=o()(r).call(r,(function(e){return!!e}))).call(t,(function(e){return!e.get("line")&&e.get("path"),e}))}},2392:(e,t,n)=>{"use strict";n.r(t),n.d(t,{transform:()=>p});var r=n(2991),o=n.n(r),a=n(81643),i=n.n(a),s=n(3649),u=n.n(s),l=n(32366),c=n.n(l);function p(e){return o()(e).call(e,(function(e){var t,n="is not of a type(s)",r=i()(t=e.get("message")).call(t,n);if(r>-1){var o,a,s=u()(o=e.get("message")).call(o,r+n.length).split(",");return e.set("message",u()(a=e.get("message")).call(a,0,r)+function(e){return c()(e).call(e,(function(e,t,n,r){return n===r.length-1&&r.length>1?e+"or "+t:r[n+1]&&r.length>2?e+t+", ":r[n+1]?e+t+" ":e+t}),"should be a")}(s))}return e}))}},21835:(e,t,n)=>{"use strict";n.r(t),n.d(t,{transform:()=>r});n(2991),n(81643),n(27361),n(43393);function r(e,t){t.jsSpec;return e}},77793:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>i});var r=n(93527),o=n(34966),a=n(87667);function i(e){return{statePlugins:{err:{reducers:(0,r.default)(e),actions:o,selectors:a}}}}},93527:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>b});var r=n(87672),o=n.n(r),a=n(51942),i=n.n(a),s=n(2991),u=n.n(s),l=n(77766),c=n.n(l),p=n(20116),f=n.n(p),h=n(10062),d=n.n(h),m=n(34966),v=n(43393),g=n(56982),y={line:0,level:"error",message:"Unknown error"};function b(){var e;return e={},o()(e,m.NEW_THROWN_ERR,(function(e,t){var n=t.payload,r=i()(y,n,{type:"thrown"});return e.update("errors",(function(e){return(e||(0,v.List)()).push((0,v.fromJS)(r))})).update("errors",(function(e){return(0,g.default)(e)}))})),o()(e,m.NEW_THROWN_ERR_BATCH,(function(e,t){var n=t.payload;return n=u()(n).call(n,(function(e){return(0,v.fromJS)(i()(y,e,{type:"thrown"}))})),e.update("errors",(function(e){var t;return c()(t=e||(0,v.List)()).call(t,(0,v.fromJS)(n))})).update("errors",(function(e){return(0,g.default)(e)}))})),o()(e,m.NEW_SPEC_ERR,(function(e,t){var n=t.payload,r=(0,v.fromJS)(n);return r=r.set("type","spec"),e.update("errors",(function(e){return(e||(0,v.List)()).push((0,v.fromJS)(r)).sortBy((function(e){return e.get("line")}))})).update("errors",(function(e){return(0,g.default)(e)}))})),o()(e,m.NEW_SPEC_ERR_BATCH,(function(e,t){var n=t.payload;return n=u()(n).call(n,(function(e){return(0,v.fromJS)(i()(y,e,{type:"spec"}))})),e.update("errors",(function(e){var t;return c()(t=e||(0,v.List)()).call(t,(0,v.fromJS)(n))})).update("errors",(function(e){return(0,g.default)(e)}))})),o()(e,m.NEW_AUTH_ERR,(function(e,t){var n=t.payload,r=(0,v.fromJS)(i()({},n));return r=r.set("type","auth"),e.update("errors",(function(e){return(e||(0,v.List)()).push((0,v.fromJS)(r))})).update("errors",(function(e){return(0,g.default)(e)}))})),o()(e,m.CLEAR,(function(e,t){var n,r=t.payload;if(!r||!e.get("errors"))return e;var o=f()(n=e.get("errors")).call(n,(function(e){var t;return d()(t=e.keySeq()).call(t,(function(t){var n=e.get(t),o=r[t];return!o||n!==o}))}));return e.merge({errors:o})})),o()(e,m.CLEAR_BY,(function(e,t){var n,r=t.payload;if(!r||"function"!=typeof r)return e;var o=f()(n=e.get("errors")).call(n,(function(e){return r(e)}));return e.merge({errors:o})})),e}},87667:(e,t,n)=>{"use strict";n.r(t),n.d(t,{allErrors:()=>a,lastError:()=>i});var r=n(43393),o=n(20573),a=(0,o.P1)((function(e){return e}),(function(e){return e.get("errors",(0,r.List)())})),i=(0,o.P1)(a,(function(e){return e.last()}))},49978:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(4309);function o(){return{fn:{opsFilter:r.default}}}},4309:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>s});var r=n(20116),o=n.n(r),a=n(81643),i=n.n(a);function s(e,t){return o()(e).call(e,(function(e,n){return-1!==i()(n).call(n,t)}))}},25474:(e,t,n)=>{"use strict";n.r(t),n.d(t,{UPDATE_LAYOUT:()=>o,UPDATE_FILTER:()=>a,UPDATE_MODE:()=>i,SHOW:()=>s,updateLayout:()=>u,updateFilter:()=>l,show:()=>c,changeMode:()=>p});var r=n(90242),o="layout_update_layout",a="layout_update_filter",i="layout_update_mode",s="layout_show";function u(e){return{type:o,payload:e}}function l(e){return{type:a,payload:e}}function c(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return e=(0,r.AF)(e),{type:s,payload:{thing:e,shown:t}}}function p(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return e=(0,r.AF)(e),{type:i,payload:{thing:e,mode:t}}}},26821:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>s});var r=n(5672),o=n(25474),a=n(4400),i=n(28989);function s(){return{statePlugins:{layout:{reducers:r.default,actions:o,selectors:a},spec:{wrapSelectors:i}}}}},5672:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>c});var r,o=n(87672),a=n.n(o),i=n(77766),s=n.n(i),u=n(43393),l=n(25474);const c=(r={},a()(r,l.UPDATE_LAYOUT,(function(e,t){return e.set("layout",t.payload)})),a()(r,l.UPDATE_FILTER,(function(e,t){return e.set("filter",t.payload)})),a()(r,l.SHOW,(function(e,t){var n=t.payload.shown,r=(0,u.fromJS)(t.payload.thing);return e.update("shown",(0,u.fromJS)({}),(function(e){return e.set(r,n)}))})),a()(r,l.UPDATE_MODE,(function(e,t){var n,r=t.payload.thing,o=t.payload.mode;return e.setIn(s()(n=["modes"]).call(n,r),(o||"")+"")})),r)},4400:(e,t,n)=>{"use strict";n.r(t),n.d(t,{current:()=>c,currentFilter:()=>p,isShown:()=>f,whatMode:()=>h,showSummary:()=>d});var r=n(59036),o=n.n(r),a=n(77766),i=n.n(a),s=n(20573),u=n(90242),l=n(43393),c=function(e){return e.get("layout")},p=function(e){return e.get("filter")},f=function(e,t,n){return t=(0,u.AF)(t),e.get("shown",(0,l.fromJS)({})).get((0,l.fromJS)(t),n)},h=function(e,t){var n,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return t=(0,u.AF)(t),e.getIn(i()(n=["modes"]).call(n,o()(t)),r)},d=(0,s.P1)((function(e){return e}),(function(e){return!f(e,"editor")}))},28989:(e,t,n)=>{"use strict";n.r(t),n.d(t,{taggedOperations:()=>s});var r=n(77766),o=n.n(r),a=n(3649),i=n.n(a),s=function(e,t){return function(n){for(var r,a=arguments.length,s=new Array(a>1?a-1:0),u=1;u=0&&(l=i()(l).call(l,0,m)),l}}},9150:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});var r=n(54103),o=n.n(r);function a(e){var t=e.configs,n={debug:0,info:1,log:2,warn:3,error:4},r=function(e){return n[e]||-1},a=t.logLevel,i=r(a);function s(e){for(var t,n=arguments.length,o=new Array(n>1?n-1:0),a=1;a=i&&(t=console)[e].apply(t,o)}return s.warn=o()(s).call(s,null,"warn"),s.error=o()(s).call(s,null,"error"),s.info=o()(s).call(s,null,"info"),s.debug=o()(s).call(s,null,"debug"),{rootInjects:{log:s}}}},67002:(e,t,n)=>{"use strict";n.r(t),n.d(t,{UPDATE_SELECTED_SERVER:()=>r,UPDATE_REQUEST_BODY_VALUE:()=>o,UPDATE_REQUEST_BODY_VALUE_RETAIN_FLAG:()=>a,UPDATE_REQUEST_BODY_INCLUSION:()=>i,UPDATE_ACTIVE_EXAMPLES_MEMBER:()=>s,UPDATE_REQUEST_CONTENT_TYPE:()=>u,UPDATE_RESPONSE_CONTENT_TYPE:()=>l,UPDATE_SERVER_VARIABLE_VALUE:()=>c,SET_REQUEST_BODY_VALIDATE_ERROR:()=>p,CLEAR_REQUEST_BODY_VALIDATE_ERROR:()=>f,CLEAR_REQUEST_BODY_VALUE:()=>h,setSelectedServer:()=>d,setRequestBodyValue:()=>m,setRetainRequestBodyValueFlag:()=>v,setRequestBodyInclusion:()=>g,setActiveExamplesMember:()=>y,setRequestContentType:()=>b,setResponseContentType:()=>w,setServerVariableValue:()=>E,setRequestBodyValidateError:()=>x,clearRequestBodyValidateError:()=>_,initRequestBodyValidateError:()=>S,clearRequestBodyValue:()=>k});var r="oas3_set_servers",o="oas3_set_request_body_value",a="oas3_set_request_body_retain_flag",i="oas3_set_request_body_inclusion",s="oas3_set_active_examples_member",u="oas3_set_request_content_type",l="oas3_set_response_content_type",c="oas3_set_server_variable_value",p="oas3_set_request_body_validate_error",f="oas3_clear_request_body_validate_error",h="oas3_clear_request_body_value";function d(e,t){return{type:r,payload:{selectedServerUrl:e,namespace:t}}}function m(e){var t=e.value,n=e.pathMethod;return{type:o,payload:{value:t,pathMethod:n}}}var v=function(e){var t=e.value,n=e.pathMethod;return{type:a,payload:{value:t,pathMethod:n}}};function g(e){var t=e.value,n=e.pathMethod,r=e.name;return{type:i,payload:{value:t,pathMethod:n,name:r}}}function y(e){var t=e.name,n=e.pathMethod,r=e.contextType,o=e.contextName;return{type:s,payload:{name:t,pathMethod:n,contextType:r,contextName:o}}}function b(e){var t=e.value,n=e.pathMethod;return{type:u,payload:{value:t,pathMethod:n}}}function w(e){var t=e.value,n=e.path,r=e.method;return{type:l,payload:{value:t,path:n,method:r}}}function E(e){var t=e.server,n=e.namespace,r=e.key,o=e.val;return{type:c,payload:{server:t,namespace:n,key:r,val:o}}}var x=function(e){var t=e.path,n=e.method,r=e.validationErrors;return{type:p,payload:{path:t,method:n,validationErrors:r}}},_=function(e){var t=e.path,n=e.method;return{type:f,payload:{path:t,method:n}}},S=function(e){var t=e.pathMethod;return{type:f,payload:{path:t[0],method:t[1]}}},k=function(e){var t=e.pathMethod;return{type:h,payload:{pathMethod:t}}}},73723:(e,t,n)=>{"use strict";n.r(t),n.d(t,{definitionsToAuthorize:()=>b});var r=n(87672),o=n.n(r),a=n(18777),i=n.n(a),s=n(77766),u=n.n(s),l=n(78914),c=n.n(l),p=n(20116),f=n.n(p),h=n(32366),d=n.n(h),m=n(20573),v=n(43393),g=n(7779);var y,b=(y=(0,m.P1)((function(e){return e}),(function(e){return e.specSelectors.securityDefinitions()}),(function(e,t){var n,r=(0,v.List)();return t?(c()(n=t.entrySeq()).call(n,(function(e){var t,n=i()(e,2),a=n[0],s=n[1],u=s.get("type");if("oauth2"===u&&c()(t=s.get("flows").entrySeq()).call(t,(function(e){var t=i()(e,2),n=t[0],u=t[1],l=(0,v.fromJS)({flow:n,authorizationUrl:u.get("authorizationUrl"),tokenUrl:u.get("tokenUrl"),scopes:u.get("scopes"),type:s.get("type"),description:s.get("description")});r=r.push(new v.Map(o()({},a,f()(l).call(l,(function(e){return void 0!==e})))))})),"http"!==u&&"apiKey"!==u||(r=r.push(new v.Map(o()({},a,s)))),"openIdConnect"===u&&s.get("openIdConnectData")){var l=s.get("openIdConnectData"),p=l.get("grant_types_supported")||["authorization_code","implicit"];c()(p).call(p,(function(e){var t,n=l.get("scopes_supported")&&d()(t=l.get("scopes_supported")).call(t,(function(e,t){return e.set(t,"")}),new v.Map),i=(0,v.fromJS)({flow:e,authorizationUrl:l.get("authorization_endpoint"),tokenUrl:l.get("token_endpoint"),scopes:n,type:"oauth2",openIdConnectUrl:s.get("openIdConnectUrl")});r=r.push(new v.Map(o()({},a,f()(i).call(i,(function(e){return void 0!==e})))))}))}})),r):r})),function(e,t){return function(){for(var n=t.getSystem().specSelectors.specJson(),r=arguments.length,o=new Array(r),a=0;a{"use strict";n.r(t),n.d(t,{default:()=>p});var r=n(5872),o=n.n(r),a=n(18777),i=n.n(a),s=n(2991),u=n.n(s),l=n(67294),c=(n(23930),n(43393));const p=function(e){var t,n=e.callbacks,r=e.getComponent,a=e.specPath,s=r("OperationContainer",!0);if(!n)return l.createElement("span",null,"No callbacks");var p=u()(t=n.entrySeq()).call(t,(function(t){var n,r=i()(t,2),p=r[0],f=r[1];return l.createElement("div",{key:p},l.createElement("h2",null,p),u()(n=f.entrySeq()).call(n,(function(t){var n,r=i()(t,2),f=r[0],h=r[1];return"$$ref"===f?null:l.createElement("div",{key:f},u()(n=h.entrySeq()).call(n,(function(t){var n=i()(t,2),r=n[0],u=n[1];if("$$ref"===r)return null;var h=(0,c.fromJS)({operation:u});return l.createElement(s,o()({},e,{op:h,key:r,tag:"",method:r,path:f,specPath:a.push(p,f,r),allowTryItOut:!1}))})))})))}));return l.createElement("div",null,p)}},86775:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>x});var r=n(26394),o=n.n(r),a=n(69198),i=n.n(a),s=n(5824),u=n.n(s),l=n(51379),c=n.n(l),p=n(10098),f=n.n(p),h=n(87672),d=n.n(h),m=n(51942),v=n.n(m),g=n(20116),y=n.n(g),b=n(2991),w=n.n(b),E=n(67294),x=function(e){c()(n,e);var t=f()(n);function n(e,r){var a;o()(this,n),a=t.call(this,e,r),d()(u()(a),"onChange",(function(e){var t=a.props.onChange,n=e.target,r=n.value,o=n.name,i=v()({},a.state.value);o?i[o]=r:i=r,a.setState({value:i},(function(){return t(a.state)}))}));var i=a.props,s=i.name,l=i.schema,c=a.getValue();return a.state={name:s,schema:l,value:c},a}return i()(n,[{key:"getValue",value:function(){var e=this.props,t=e.name,n=e.authorized;return n&&n.getIn([t,"value"])}},{key:"render",value:function(){var e,t,n=this.props,r=n.schema,o=n.getComponent,a=n.errSelectors,i=n.name,s=o("Input"),u=o("Row"),l=o("Col"),c=o("authError"),p=o("Markdown",!0),f=o("JumpToPath",!0),h=(r.get("scheme")||"").toLowerCase(),d=this.getValue(),m=y()(e=a.allErrors()).call(e,(function(e){return e.get("authId")===i}));if("basic"===h){var v,g=d?d.get("username"):null;return E.createElement("div",null,E.createElement("h4",null,E.createElement("code",null,i||r.get("name")),"  (http, Basic)",E.createElement(f,{path:["securityDefinitions",i]})),g&&E.createElement("h6",null,"Authorized"),E.createElement(u,null,E.createElement(p,{source:r.get("description")})),E.createElement(u,null,E.createElement("label",null,"Username:"),g?E.createElement("code",null," ",g," "):E.createElement(l,null,E.createElement(s,{type:"text",required:"required",name:"username","aria-label":"auth-basic-username",onChange:this.onChange,autoFocus:!0}))),E.createElement(u,null,E.createElement("label",null,"Password:"),g?E.createElement("code",null," ****** "):E.createElement(l,null,E.createElement(s,{autoComplete:"new-password",name:"password",type:"password","aria-label":"auth-basic-password",onChange:this.onChange}))),w()(v=m.valueSeq()).call(v,(function(e,t){return E.createElement(c,{error:e,key:t})})))}return"bearer"===h?E.createElement("div",null,E.createElement("h4",null,E.createElement("code",null,i||r.get("name")),"  (http, Bearer)",E.createElement(f,{path:["securityDefinitions",i]})),d&&E.createElement("h6",null,"Authorized"),E.createElement(u,null,E.createElement(p,{source:r.get("description")})),E.createElement(u,null,E.createElement("label",null,"Value:"),d?E.createElement("code",null," ****** "):E.createElement(l,null,E.createElement(s,{type:"text","aria-label":"auth-bearer-value",onChange:this.onChange,autoFocus:!0}))),w()(t=m.valueSeq()).call(t,(function(e,t){return E.createElement(c,{error:e,key:t})}))):E.createElement("div",null,E.createElement("em",null,E.createElement("b",null,i)," HTTP authentication: unsupported scheme ","'".concat(h,"'")))}}]),n}(E.Component)},76467:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>p});var r=n(33427),o=n(42458),a=n(15757),i=n(56617),s=n(9928),u=n(45327),l=n(86775),c=n(96796);const p={Callbacks:r.default,HttpAuth:l.default,RequestBody:o.default,Servers:i.default,ServersContainer:s.default,RequestBodyEditor:u.default,OperationServers:c.default,operationLink:a.default}},15757:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>g});var r=n(26394),o=n.n(r),a=n(69198),i=n.n(a),s=n(51379),u=n.n(s),l=n(10098),c=n.n(l),p=n(59340),f=n.n(p),h=n(2991),d=n.n(h),m=n(67294),v=(n(23930),function(e){u()(n,e);var t=c()(n);function n(){return o()(this,n),t.apply(this,arguments)}return i()(n,[{key:"render",value:function(){var e=this.props,t=e.link,n=e.name,r=(0,e.getComponent)("Markdown",!0),o=t.get("operationId")||t.get("operationRef"),a=t.get("parameters")&&t.get("parameters").toJS(),i=t.get("description");return m.createElement("div",{className:"operation-link"},m.createElement("div",{className:"description"},m.createElement("b",null,m.createElement("code",null,n)),i?m.createElement(r,{source:i}):null),m.createElement("pre",null,"Operation `",o,"`",m.createElement("br",null),m.createElement("br",null),"Parameters ",function(e,t){var n;if("string"!=typeof t)return"";return d()(n=t.split("\n")).call(n,(function(t,n){return n>0?Array(e+1).join(" ")+t:t})).join("\n")}(0,f()(a,null,2))||"{}",m.createElement("br",null)))}}]),n}(m.Component));const g=v},96796:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>w});var r=n(95945),o=n.n(r),a=n(26394),i=n.n(a),s=n(69198),u=n.n(s),l=n(5824),c=n.n(l),p=n(51379),f=n.n(p),h=n(10098),d=n.n(h),m=n(87672),v=n.n(m),g=n(77766),y=n.n(g),b=n(67294),w=(n(23930),function(e){f()(n,e);var t=d()(n);function n(){var e,r;i()(this,n);for(var a=arguments.length,s=new Array(a),u=0;u{"use strict";n.r(t),n.d(t,{default:()=>w});var r=n(26394),o=n.n(r),a=n(69198),i=n.n(a),s=n(5824),u=n.n(s),l=n(51379),c=n.n(l),p=n(10098),f=n.n(p),h=n(87672),d=n.n(h),m=n(67294),v=n(94184),g=n.n(v),y=n(90242),b=Function.prototype,w=function(e){c()(n,e);var t=f()(n);function n(e,r){var a;return o()(this,n),a=t.call(this,e,r),d()(u()(a),"applyDefaultValue",(function(e){var t=e||a.props,n=t.onChange,r=t.defaultValue;return a.setState({value:r}),n(r)})),d()(u()(a),"onChange",(function(e){a.props.onChange((0,y.Pz)(e))})),d()(u()(a),"onDomChange",(function(e){var t=e.target.value;a.setState({value:t},(function(){return a.onChange(t)}))})),a.state={value:(0,y.Pz)(e.value)||e.defaultValue},e.onChange(e.value),a}return i()(n,[{key:"UNSAFE_componentWillReceiveProps",value:function(e){this.props.value!==e.value&&e.value!==this.state.value&&this.setState({value:(0,y.Pz)(e.value)}),!e.value&&e.defaultValue&&this.state.value&&this.applyDefaultValue(e)}},{key:"render",value:function(){var e=this.props,t=e.getComponent,n=e.errors,r=this.state.value,o=n.size>0,a=t("TextArea");return m.createElement("div",{className:"body-param"},m.createElement(a,{className:g()("body-param__text",{invalid:o}),title:n.size?n.join(", "):"",value:r,onChange:this.onDomChange}))}}]),n}(m.PureComponent);d()(w,"defaultProps",{onChange:b,userHasEditedBody:!1})},42458:(e,t,n)=>{"use strict";n.r(t),n.d(t,{getDefaultRequestBodyValue:()=>b,default:()=>w});var r=n(18777),o=n.n(r),a=n(2991),i=n.n(a),s=n(81643),u=n.n(s),l=n(78580),c=n.n(l),p=n(77766),f=n.n(p),h=n(41511),d=n.n(h),m=n(67294),v=(n(23930),n(43393)),g=n(90242),y=n(2518),b=function(e,t,n){var r=e.getIn(["content",t]),o=r.get("schema").toJS(),a=void 0!==r.get("examples"),i=r.get("example"),s=a?r.getIn(["examples",n,"value"]):i,u=(0,g.xi)(o,t,{includeWriteOnly:!0},s);return(0,g.Pz)(u)};const w=function(e){var t=e.userHasEditedBody,n=e.requestBody,r=e.requestBodyValue,a=e.requestBodyInclusionSetting,s=e.requestBodyErrors,l=e.getComponent,p=e.getConfigs,h=e.specSelectors,w=e.fn,E=e.contentType,x=e.isExecute,_=e.specPath,S=e.onChange,k=e.onChangeIncludeEmpty,A=e.activeExamplesKey,C=e.updateActiveExamplesKey,O=e.setRetainRequestBodyValueFlag,j=function(e){var t={key:e,shouldDispatchInit:!1,defaultValue:!0};return"no value"===a.get(e,"no value")&&(t.shouldDispatchInit=!0),t},I=l("Markdown",!0),T=l("modelExample"),N=l("RequestBodyEditor"),P=l("highlightCode"),R=l("ExamplesSelectValueRetainer"),M=l("Example"),D=l("ParameterIncludeEmpty"),L=p().showCommonExtensions,B=n&&n.get("description")||null,F=n&&n.get("content")||new v.OrderedMap;E=E||F.keySeq().first()||"";var z=F.get(E,(0,v.OrderedMap)()),U=z.get("schema",(0,v.OrderedMap)()),q=z.get("examples",null),V=null==q?void 0:i()(q).call(q,(function(e,t){var r,o=null===(r=e)||void 0===r?void 0:r.get("value",null);return o&&(e=e.set("value",b(n,E,t),o)),e}));if(s=v.List.isList(s)?s:(0,v.List)(),!z.size)return null;var W="object"===z.getIn(["schema","type"]),H="binary"===z.getIn(["schema","format"]),$="base64"===z.getIn(["schema","format"]);if("application/octet-stream"===E||0===u()(E).call(E,"image/")||0===u()(E).call(E,"audio/")||0===u()(E).call(E,"video/")||H||$){var J=l("Input");return x?m.createElement(J,{type:"file",onChange:function(e){S(e.target.files[0])}}):m.createElement("i",null,"Example values are not available for ",m.createElement("code",null,E)," media types.")}if(W&&("application/x-www-form-urlencoded"===E||0===u()(E).call(E,"multipart/"))&&U.get("properties",(0,v.OrderedMap)()).size>0){var K,G=l("JsonSchemaForm"),Z=l("ParameterExt"),Y=U.get("properties",(0,v.OrderedMap)());return r=v.Map.isMap(r)?r:(0,v.OrderedMap)(),m.createElement("div",{className:"table-container"},B&&m.createElement(I,{source:B}),m.createElement("table",null,m.createElement("tbody",null,v.Map.isMap(Y)&&i()(K=Y.entrySeq()).call(K,(function(e){var t,n,u=o()(e,2),p=u[0],h=u[1];if(!h.get("readOnly")){var y=L?(0,g.po)(h):null,b=c()(t=U.get("required",(0,v.List)())).call(t,p),E=h.get("type"),_=h.get("format"),A=h.get("description"),C=r.getIn([p,"value"]),O=r.getIn([p,"errors"])||s,T=a.get(p)||!1,N=h.has("default")||h.has("example")||h.hasIn(["items","example"])||h.hasIn(["items","default"]),P=h.has("enum")&&(1===h.get("enum").size||b),R=N||P,M="";"array"!==E||R||(M=[]),("object"===E||R)&&(M=(0,g.xi)(h,!1,{includeWriteOnly:!0})),"string"!=typeof M&&"object"===E&&(M=(0,g.Pz)(M)),"string"==typeof M&&"array"===E&&(M=JSON.parse(M));var B="string"===E&&("binary"===_||"base64"===_);return m.createElement("tr",{key:p,className:"parameters","data-property-name":p},m.createElement("td",{className:"parameters-col_name"},m.createElement("div",{className:b?"parameter__name required":"parameter__name"},p,b?m.createElement("span",null," *"):null),m.createElement("div",{className:"parameter__type"},E,_&&m.createElement("span",{className:"prop-format"},"($",_,")"),L&&y.size?i()(n=y.entrySeq()).call(n,(function(e){var t,n=o()(e,2),r=n[0],a=n[1];return m.createElement(Z,{key:f()(t="".concat(r,"-")).call(t,a),xKey:r,xVal:a})})):null),m.createElement("div",{className:"parameter__deprecated"},h.get("deprecated")?"deprecated":null)),m.createElement("td",{className:"parameters-col_description"},m.createElement(I,{source:A}),x?m.createElement("div",null,m.createElement(G,{fn:w,dispatchInitialValue:!B,schema:h,description:p,getComponent:l,value:void 0===C?M:C,required:b,errors:O,onChange:function(e){S(e,[p])}}),b?null:m.createElement(D,{onChange:function(e){return k(p,e)},isIncluded:T,isIncludedOptions:j(p),isDisabled:d()(C)?0!==C.length:!(0,g.O2)(C)})):null))}})))))}var Q=b(n,E,A),X=null;return(0,y.O)(Q)&&(X="json"),m.createElement("div",null,B&&m.createElement(I,{source:B}),V?m.createElement(R,{userHasEditedBody:t,examples:V,currentKey:A,currentUserInputValue:r,onSelect:function(e){C(e)},updateValue:S,defaultToFirstExample:!0,getComponent:l,setRetainRequestBodyValueFlag:O}):null,x?m.createElement("div",null,m.createElement(N,{value:r,errors:s,defaultValue:Q,onChange:S,getComponent:l})):m.createElement(T,{getComponent:l,getConfigs:p,specSelectors:h,expandDepth:1,isExecute:x,schema:z.get("schema"),specPath:_.push("content",E),example:m.createElement(P,{className:"body-param__example",getConfigs:p,language:X,value:(0,g.Pz)(r)||Q}),includeWriteOnly:!0}),V?m.createElement(M,{example:V.get(A),getComponent:l,getConfigs:p}):null)}},9928:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>f});var r=n(26394),o=n.n(r),a=n(69198),i=n.n(a),s=n(51379),u=n.n(s),l=n(10098),c=n.n(l),p=n(67294),f=function(e){u()(n,e);var t=c()(n);function n(){return o()(this,n),t.apply(this,arguments)}return i()(n,[{key:"render",value:function(){var e=this.props,t=e.specSelectors,n=e.oas3Selectors,r=e.oas3Actions,o=e.getComponent,a=t.servers(),i=o("Servers");return a&&a.size?p.createElement("div",null,p.createElement("span",{className:"servers-title"},"Servers"),p.createElement(i,{servers:a,currentServer:n.selectedServer(),setSelectedServer:r.setSelectedServer,setServerVariableValue:r.setServerVariableValue,getServerVariable:n.serverVariableValue,getEffectiveServerValue:n.serverEffectiveValue})):null}}]),n}(p.Component)},56617:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>k});var r=n(18777),o=n.n(r),a=n(26394),i=n.n(a),s=n(69198),u=n.n(s),l=n(5824),c=n.n(l),p=n(51379),f=n.n(p),h=n(10098),d=n.n(h),m=n(87672),v=n.n(m),g=n(77766),y=n.n(g),b=n(94473),w=n.n(b),E=n(2991),x=n.n(E),_=n(67294),S=n(43393),k=(n(23930),function(e){f()(n,e);var t=d()(n);function n(){var e,r;i()(this,n);for(var o=arguments.length,a=new Array(o),s=0;s{"use strict";n.r(t),n.d(t,{isOAS3:()=>u,isSwagger2:()=>l,OAS3ComponentWrapFactory:()=>c});var r=n(5872),o=n.n(r),a=n(29828),i=n.n(a),s=n(67294);function u(e){var t=e.get("openapi");return"string"==typeof t&&(i()(t).call(t,"3.0.")&&t.length>4)}function l(e){var t=e.get("swagger");return"string"==typeof t&&i()(t).call(t,"2.0")}function c(e){return function(t,n){return function(r){return n&&n.specSelectors&&n.specSelectors.specJson?u(n.specSelectors.specJson())?s.createElement(e,o()({},r,n,{Ori:t})):s.createElement(t,r):(console.warn("OAS3 wrapper: couldn't get spec"),null)}}}},97451:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>p});var r=n(92044),o=n(73723),a=n(91741),i=n(76467),s=n(37761),u=n(67002),l=n(5065),c=n(62109);function p(){return{components:i.default,wrapComponents:s.default,statePlugins:{spec:{wrapSelectors:r,selectors:a},auth:{wrapSelectors:o},oas3:{actions:u,reducers:c.default,selectors:l}}}}},62109:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>w});var r,o=n(87672),a=n.n(o),i=n(71064),s=n.n(i),u=n(18777),l=n.n(u),c=n(69301),p=n.n(c),f=n(3649),h=n.n(f),d=n(78914),m=n.n(d),v=n(32366),g=n.n(v),y=n(43393),b=n(67002);const w=(r={},a()(r,b.UPDATE_SELECTED_SERVER,(function(e,t){var n=t.payload,r=n.selectedServerUrl,o=n.namespace,a=o?[o,"selectedServer"]:["selectedServer"];return e.setIn(a,r)})),a()(r,b.UPDATE_REQUEST_BODY_VALUE,(function(e,t){var n=t.payload,r=n.value,o=n.pathMethod,a=l()(o,2),i=a[0],u=a[1];if(!y.Map.isMap(r))return e.setIn(["requestData",i,u,"bodyValue"],r);var c,f=e.getIn(["requestData",i,u,"bodyValue"])||(0,y.Map)();y.Map.isMap(f)||(f=(0,y.Map)());var d=p()(r).call(r),v=s()(d),g=h()(v).call(v,0);return m()(g).call(g,(function(e){var t=r.getIn([e]);f.has(e)&&y.Map.isMap(t)||(c=f.setIn([e,"value"],t))})),e.setIn(["requestData",i,u,"bodyValue"],c)})),a()(r,b.UPDATE_REQUEST_BODY_VALUE_RETAIN_FLAG,(function(e,t){var n=t.payload,r=n.value,o=n.pathMethod,a=l()(o,2),i=a[0],s=a[1];return e.setIn(["requestData",i,s,"retainBodyValue"],r)})),a()(r,b.UPDATE_REQUEST_BODY_INCLUSION,(function(e,t){var n=t.payload,r=n.value,o=n.pathMethod,a=n.name,i=l()(o,2),s=i[0],u=i[1];return e.setIn(["requestData",s,u,"bodyInclusion",a],r)})),a()(r,b.UPDATE_ACTIVE_EXAMPLES_MEMBER,(function(e,t){var n=t.payload,r=n.name,o=n.pathMethod,a=n.contextType,i=n.contextName,s=l()(o,2),u=s[0],c=s[1];return e.setIn(["examples",u,c,a,i,"activeExample"],r)})),a()(r,b.UPDATE_REQUEST_CONTENT_TYPE,(function(e,t){var n=t.payload,r=n.value,o=n.pathMethod,a=l()(o,2),i=a[0],s=a[1];return e.setIn(["requestData",i,s,"requestContentType"],r)})),a()(r,b.UPDATE_RESPONSE_CONTENT_TYPE,(function(e,t){var n=t.payload,r=n.value,o=n.path,a=n.method;return e.setIn(["requestData",o,a,"responseContentType"],r)})),a()(r,b.UPDATE_SERVER_VARIABLE_VALUE,(function(e,t){var n=t.payload,r=n.server,o=n.namespace,a=n.key,i=n.val,s=o?[o,"serverVariableValues",r,a]:["serverVariableValues",r,a];return e.setIn(s,i)})),a()(r,b.SET_REQUEST_BODY_VALIDATE_ERROR,(function(e,t){var n=t.payload,r=n.path,o=n.method,a=n.validationErrors,i=[];if(i.push("Required field is not provided"),a.missingBodyValue)return e.setIn(["requestData",r,o,"errors"],(0,y.fromJS)(i));if(a.missingRequiredKeys&&a.missingRequiredKeys.length>0){var s=a.missingRequiredKeys;return e.updateIn(["requestData",r,o,"bodyValue"],(0,y.fromJS)({}),(function(e){return g()(s).call(s,(function(e,t){return e.setIn([t,"errors"],(0,y.fromJS)(i))}),e)}))}return console.warn("unexpected result: SET_REQUEST_BODY_VALIDATE_ERROR"),e})),a()(r,b.CLEAR_REQUEST_BODY_VALIDATE_ERROR,(function(e,t){var n=t.payload,r=n.path,o=n.method,a=e.getIn(["requestData",r,o,"bodyValue"]);if(!y.Map.isMap(a))return e.setIn(["requestData",r,o,"errors"],(0,y.fromJS)([]));var i=p()(a).call(a),u=s()(i),l=h()(u).call(u,0);return l?e.updateIn(["requestData",r,o,"bodyValue"],(0,y.fromJS)({}),(function(e){return g()(l).call(l,(function(e,t){return e.setIn([t,"errors"],(0,y.fromJS)([]))}),e)})):e})),a()(r,b.CLEAR_REQUEST_BODY_VALUE,(function(e,t){var n=t.payload.pathMethod,r=l()(n,2),o=r[0],a=r[1],i=e.getIn(["requestData",o,a,"bodyValue"]);return i?y.Map.isMap(i)?e.setIn(["requestData",o,a,"bodyValue"],(0,y.Map)()):e.setIn(["requestData",o,a,"bodyValue"],""):e})),r)},5065:(e,t,n)=>{"use strict";n.r(t),n.d(t,{selectedServer:()=>E,requestBodyValue:()=>x,shouldRetainRequestBodyValue:()=>_,hasUserEditedBody:()=>S,requestBodyInclusionSetting:()=>k,requestBodyErrors:()=>A,activeExamplesMember:()=>C,requestContentType:()=>O,responseContentType:()=>j,serverVariableValue:()=>I,serverVariables:()=>T,serverEffectiveValue:()=>N,validateBeforeExecute:()=>P,validateShallowRequired:()=>R});var r=n(59036),o=n.n(r),a=n(77766),i=n.n(a),s=n(2991),u=n.n(s),l=n(78914),c=n.n(l),p=n(86902),f=n.n(p),h=n(81643),d=n.n(h),m=n(43393),v=n(7779),g=n(42458),y=n(90242);function b(e){return function(){for(var t=arguments.length,n=new Array(t),r=0;r{"use strict";n.r(t),n.d(t,{servers:()=>c,isSwagger2:()=>p});var r=n(20573),o=n(43393),a=n(7779);var i,s=function(e){return e||(0,o.Map)()},u=(0,r.P1)(s,(function(e){return e.get("json",(0,o.Map)())})),l=(0,r.P1)(s,(function(e){return e.get("resolved",(0,o.Map)())})),c=(i=(0,r.P1)((function(e){var t=l(e);return t.count()<1&&(t=u(e)),t}),(function(e){return e.getIn(["servers"])||(0,o.Map)()})),function(){return function(e){var t=e.getSystem().specSelectors.specJson();if((0,a.isOAS3)(t)){for(var n=arguments.length,r=new Array(n>1?n-1:0),o=1;o{"use strict";n.r(t),n.d(t,{definitions:()=>h,hasHost:()=>d,securityDefinitions:()=>m,host:()=>v,basePath:()=>g,consumes:()=>y,produces:()=>b,schemes:()=>w,servers:()=>E,isOAS3:()=>x,isSwagger2:()=>_});var r=n(20573),o=n(33881),a=n(43393),i=n(7779);function s(e){return function(t,n){return function(){var r=n.getSystem().specSelectors.specJson();return(0,i.isOAS3)(r)?e.apply(void 0,arguments):t.apply(void 0,arguments)}}}var u=function(e){return e||(0,a.Map)()},l=s((0,r.P1)((function(){return null}))),c=(0,r.P1)(u,(function(e){return e.get("json",(0,a.Map)())})),p=(0,r.P1)(u,(function(e){return e.get("resolved",(0,a.Map)())})),f=function(e){var t=p(e);return t.count()<1&&(t=c(e)),t},h=s((0,r.P1)(f,(function(e){var t=e.getIn(["components","schemas"]);return a.Map.isMap(t)?t:(0,a.Map)()}))),d=s((function(e){return f(e).hasIn(["servers",0])})),m=s((0,r.P1)(o.specJsonWithResolvedSubtrees,(function(e){return e.getIn(["components","securitySchemes"])||null}))),v=l,g=l,y=l,b=l,w=l,E=s((0,r.P1)(f,(function(e){return e.getIn(["servers"])||(0,a.Map)()}))),x=function(e,t){return function(){var e=t.getSystem().specSelectors.specJson();return(0,i.isOAS3)(a.Map.isMap(e)?e:(0,a.Map)())}},_=function(e,t){return function(){var e=t.getSystem().specSelectors.specJson();return(0,i.isSwagger2)(a.Map.isMap(e)?e:(0,a.Map)())}}},70356:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>u});var r=n(80122),o=n.n(r),a=n(67294),i=n(7779),s=["Ori"];const u=(0,i.OAS3ComponentWrapFactory)((function(e){var t=e.Ori,n=o()(e,s),r=n.schema,i=n.getComponent,u=n.errSelectors,l=n.authorized,c=n.onAuthChange,p=n.name,f=i("HttpAuth");return"http"===r.get("type")?a.createElement(f,{key:p,schema:r,name:p,errSelectors:u,authorized:l,getComponent:i,onChange:c}):a.createElement(t,n)}))},37761:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>l});var r=n(22460),o=n(70356),a=n(69487),i=n(50058),s=n(53499),u=n(90287);const l={Markdown:r.default,AuthItem:o.default,JsonSchema_string:u.default,VersionStamp:a.default,model:s.default,onlineValidatorBadge:i.default}},90287:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>u});var r=n(80122),o=n.n(r),a=n(67294),i=n(7779),s=["Ori"];const u=(0,i.OAS3ComponentWrapFactory)((function(e){var t=e.Ori,n=o()(e,s),r=n.schema,i=n.getComponent,u=n.errors,l=n.onChange,c=r&&r.get?r.get("format"):null,p=r&&r.get?r.get("type"):null,f=i("Input");return p&&"string"===p&&c&&("binary"===c||"base64"===c)?a.createElement(f,{type:"file",className:u.length?"invalid":"",title:u.length?u:"",onChange:function(e){l(e.target.files[0])},disabled:t.isDisabled}):a.createElement(t,n)}))},22460:(e,t,n)=>{"use strict";n.r(t),n.d(t,{Markdown:()=>f,default:()=>h});var r=n(25843),o=n.n(r),a=n(67294),i=n(94184),s=n.n(i),u=n(89927),l=n(7779),c=n(86019),p=new u._("commonmark");p.block.ruler.enable(["table"]),p.set({linkTarget:"_blank"});var f=function(e){var t=e.source,n=e.className,r=void 0===n?"":n,i=e.getConfigs;if("string"!=typeof t)return null;if(t){var u,l=i().useUnsafeMarkdown,f=p.render(t),h=(0,c.s)(f,{useUnsafeMarkdown:l});return"string"==typeof h&&(u=o()(h).call(h)),a.createElement("div",{dangerouslySetInnerHTML:{__html:u},className:s()(r,"renderedMarkdown")})}return null};f.defaultProps={getConfigs:function(){return{useUnsafeMarkdown:!1}}};const h=(0,l.OAS3ComponentWrapFactory)(f)},53499:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>g});var r=n(5872),o=n.n(r),a=n(26394),i=n.n(a),s=n(69198),u=n.n(s),l=n(51379),c=n.n(l),p=n(10098),f=n.n(p),h=n(67294),d=n(7779),m=n(53795),v=function(e){c()(n,e);var t=f()(n);function n(){return i()(this,n),t.apply(this,arguments)}return u()(n,[{key:"render",value:function(){var e=this.props,t=e.getConfigs,n=["model-box"],r=null;return!0===e.schema.get("deprecated")&&(n.push("deprecated"),r=h.createElement("span",{className:"model-deprecated-warning"},"Deprecated:")),h.createElement("div",{className:n.join(" ")},r,h.createElement(m.Z,o()({},this.props,{getConfigs:t,depth:1,expandDepth:this.props.expandDepth||0})))}}]),n}(h.Component);const g=(0,d.OAS3ComponentWrapFactory)(v)},50058:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});var r=n(7779),o=n(5623);const a=(0,r.OAS3ComponentWrapFactory)(o.Z)},69487:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(67294);const o=(0,n(7779).OAS3ComponentWrapFactory)((function(e){var t=e.Ori;return r.createElement("span",null,r.createElement(t,e),r.createElement("small",{className:"version-stamp"},r.createElement("pre",{className:"version"},"OAS3")))}))},28560:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>i});var r=n(33032),o=n.n(r),a=!1;function i(){return{statePlugins:{spec:{wrapActions:{updateSpec:function(e){return function(){return a=!0,e.apply(void 0,arguments)}},updateJsonSpec:function(e,t){return function(){var n=t.getConfigs().onComplete;return a&&"function"==typeof n&&(o()(n,0),a=!1),e.apply(void 0,arguments)}}}}}}}},92135:(e,t,n)=>{"use strict";n.r(t),n.d(t,{requestSnippetGenerator_curl_powershell:()=>P,requestSnippetGenerator_curl_bash:()=>R,requestSnippetGenerator_curl_cmd:()=>M});var r=n(59036),o=n.n(r),a=n(18777),i=n.n(a),s=n(86418),u=n.n(s),l=n(81643),c=n.n(l),p=n(25843),f=n.n(p),h=n(77766),d=n.n(h),m=n(59340),v=n.n(m),g=n(2991),y=n.n(g),b=n(39291),w=n.n(b),E=n(72119),x=n.n(E),_=n(78580),S=n.n(_),k=n(27504),A=n(43393),C=function(e){var t,n="_**[]";return c()(e).call(e,n)<0?e:f()(t=e.split(n)[0]).call(t)},O=function(e){return"-d "===e||/^[_\/-]/g.test(e)?e:"'"+e.replace(/'/g,"'\\''")+"'"},j=function(e){return"-d "===(e=e.replace(/\^/g,"^^").replace(/\\"/g,'\\\\"').replace(/"/g,'""').replace(/\n/g,"^\n"))?e.replace(/-d /g,"-d ^\n"):/^[_\/-]/g.test(e)?e:'"'+e+'"'},I=function(e){return"-d "===e?e:/\n/.test(e)?'@"\n'+e.replace(/"/g,'\\"').replace(/`/g,"``").replace(/\$/,"`$")+'\n"@':/^[_\/-]/g.test(e)?e:"'"+e.replace(/"/g,'""').replace(/'/g,"''")+"'"};function T(e){var t,n=[],r=u()(e.get("body").entrySeq());try{for(r.s();!(t=r.n()).done;){var o,a,s,l=i()(t.value,2),c=l[0],p=l[1],f=C(c);if(p instanceof k.Z.File)n.push(d()(o=d()(a=' "'.concat(f,'": {\n "name": "')).call(a,p.name,'"')).call(o,p.type?',\n "type": "'.concat(p.type,'"'):"","\n }"));else n.push(d()(s=' "'.concat(f,'": ')).call(s,v()(p,null,2).replace(/(\r\n|\r|\n)/g,"\n ")))}}catch(e){r.e(e)}finally{r.f()}return"{\n".concat(n.join(",\n"),"\n}")}var N=function(e,t,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"",a=!1,s="",l=function(){for(var e=arguments.length,n=new Array(e),r=0;r0&&void 0!==arguments[0]?arguments[0]:1;return s+=w()(e=" ").call(e,t)},h=e.get("headers");if(s+="curl"+r,e.has("curlOptions")&&l.apply(void 0,o()(e.get("curlOptions"))),l("-X",e.get("method")),p(),f(),c("".concat(e.get("url"))),h&&h.size){var m,g,b=u()(x()(m=e.get("headers")).call(m));try{for(b.s();!(g=b.n()).done;){var E,_=g.value;p(),f();var O=i()(_,2),j=O[0],I=O[1];c("-H",d()(E="".concat(j,": ")).call(E,I)),a=a||/^content-type$/i.test(j)&&/^multipart\/form-data$/i.test(I)}}catch(e){b.e(e)}finally{b.f()}}var N,P=e.get("body");if(P)if(a&&S()(N=["POST","PUT","PATCH"]).call(N,e.get("method"))){var R,M=u()(P.entrySeq());try{for(M.s();!(R=M.n()).done;){var D,L,B,F=i()(R.value,2),z=F[0],U=F[1],q=C(z);if(p(),f(),c("-F"),U instanceof k.Z.File)l(d()(D=d()(L="".concat(q,"=@")).call(L,U.name)).call(D,U.type?";type=".concat(U.type):""));else l(d()(B="".concat(q,"=")).call(B,U))}}catch(e){M.e(e)}finally{M.f()}}else if(P instanceof k.Z.File)p(),f(),c("--data-binary '@".concat(P.name,"'"));else{p(),f(),c("-d ");var V=P;A.Map.isMap(V)?c(T(e)):("string"!=typeof V&&(V=v()(V)),c(V))}else P||"POST"!==e.get("method")||(p(),f(),c("-d ''"));return s},P=function(e){return N(e,I,"`\n",".exe")},R=function(e){return N(e,O,"\\\n")},M=function(e){return N(e,j,"^\n")}},86575:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>i});var r=n(92135),o=n(4669),a=n(84206);const i=function(){return{components:{RequestSnippets:a.default},fn:r,statePlugins:{requestSnippets:{selectors:o}}}}},84206:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>x});var r=n(18777),o=n.n(r),a=n(20116),i=n.n(a),s=n(66419),u=n.n(s),l=n(78914),c=n.n(l),p=n(2991),f=n.n(p),h=n(67294),d=n(27361),m=n.n(d),v=n(23560),g=n.n(v),y=n(74855),b=n(36581),w={cursor:"pointer",lineHeight:1,display:"inline-flex",backgroundColor:"rgb(250, 250, 250)",paddingBottom:"0",paddingTop:"0",border:"1px solid rgb(51, 51, 51)",borderRadius:"4px 4px 0 0",boxShadow:"none",borderBottom:"none"},E={cursor:"pointer",lineHeight:1,display:"inline-flex",backgroundColor:"rgb(51, 51, 51)",boxShadow:"none",border:"1px solid rgb(51, 51, 51)",paddingBottom:"0",paddingTop:"0",borderRadius:"4px 4px 0 0",marginTop:"-5px",marginRight:"-5px",marginLeft:"-5px",zIndex:"9999",borderBottom:"none"};const x=function(e){var t,n,r=e.request,a=e.requestSnippetsSelectors,s=e.getConfigs,l=g()(s)?s():null,p=!1!==m()(l,"syntaxHighlight")&&m()(l,"syntaxHighlight.activated",!0),d=(0,h.useRef)(null),v=(0,h.useState)(null===(t=a.getSnippetGenerators())||void 0===t?void 0:t.keySeq().first()),x=o()(v,2),_=x[0],S=x[1],k=(0,h.useState)(null==a?void 0:a.getDefaultExpanded()),A=o()(k,2),C=A[0],O=A[1];(0,h.useEffect)((function(){}),[]),(0,h.useEffect)((function(){var e,t=i()(e=u()(d.current.childNodes)).call(e,(function(e){var t;return!!e.nodeType&&(null===(t=e.classList)||void 0===t?void 0:t.contains("curl-command"))}));return c()(t).call(t,(function(e){return e.addEventListener("mousewheel",R,{passive:!1})})),function(){c()(t).call(t,(function(e){return e.removeEventListener("mousewheel",R)}))}}),[r]);var j=a.getSnippetGenerators(),I=j.get(_),T=I.get("fn")(r),N=function(){O(!C)},P=function(e){return e===_?E:w},R=function(e){var t=e.target,n=e.deltaY,r=t.scrollHeight,o=t.offsetHeight,a=t.scrollTop;r>o&&(0===a&&n<0||o+a>=r&&n>0)&&e.preventDefault()},M=p?h.createElement(b.d3,{language:I.get("syntax"),className:"curl microlight",style:(0,b.C2)(m()(l,"syntaxHighlight.theme"))},T):h.createElement("textarea",{readOnly:!0,className:"curl",value:T});return h.createElement("div",{className:"request-snippets",ref:d},h.createElement("div",{style:{width:"100%",display:"flex",justifyContent:"flex-start",alignItems:"center",marginBottom:"15px"}},h.createElement("h4",{onClick:function(){return N()},style:{cursor:"pointer"}},"Snippets"),h.createElement("button",{onClick:function(){return N()},style:{border:"none",background:"none"},title:C?"Collapse operation":"Expand operation"},h.createElement("svg",{className:"arrow",width:"10",height:"10"},h.createElement("use",{href:C?"#large-arrow-down":"#large-arrow",xlinkHref:C?"#large-arrow-down":"#large-arrow"})))),C&&h.createElement("div",{className:"curl-command"},h.createElement("div",{style:{paddingLeft:"15px",paddingRight:"10px",width:"100%",display:"flex"}},f()(n=j.entrySeq()).call(n,(function(e){var t=o()(e,2),n=t[0],r=t[1];return h.createElement("div",{style:P(n),className:"btn",key:n,onClick:function(){return function(e){_!==e&&S(e)}(n)}},h.createElement("h4",{style:n===_?{color:"white"}:{}},r.get("title")))}))),h.createElement("div",{className:"copy-to-clipboard"},h.createElement(y.CopyToClipboard,{text:T},h.createElement("button",null))),h.createElement("div",null,M)))}},4669:(e,t,n)=>{"use strict";n.r(t),n.d(t,{getGenerators:()=>f,getSnippetGenerators:()=>h,getActiveLanguage:()=>d,getDefaultExpanded:()=>m});var r=n(20116),o=n.n(r),a=n(78580),i=n.n(a),s=n(2991),u=n.n(s),l=n(20573),c=n(43393),p=function(e){return e||(0,c.Map)()},f=(0,l.P1)(p,(function(e){var t=e.get("languages"),n=e.get("generators",(0,c.Map)());return!t||t.isEmpty()?n:o()(n).call(n,(function(e,n){return i()(t).call(t,n)}))})),h=function(e){return function(t){var n,r,a=t.fn;return o()(n=u()(r=f(e)).call(r,(function(e,t){var n=function(e){return a["requestSnippetGenerator_".concat(e)]}(t);return"function"!=typeof n?null:e.set("fn",n)}))).call(n,(function(e){return e}))}},d=(0,l.P1)(p,(function(e){return e.get("activeLanguage")})),m=(0,l.P1)(p,(function(e){return e.get("defaultExpanded")}))},36195:(e,t,n)=>{"use strict";n.r(t),n.d(t,{ErrorBoundary:()=>v,default:()=>g});var r=n(26394),o=n.n(r),a=n(69198),i=n.n(a),s=n(51379),u=n.n(s),l=n(10098),c=n.n(l),p=n(77766),f=n.n(p),h=n(67294),d=n(56189),m=n(29403),v=function(e){u()(n,e);var t=c()(n);function n(){var e,r;o()(this,n);for(var a=arguments.length,i=new Array(a),s=0;s{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(67294);const o=function(e){var t=e.name;return r.createElement("div",{className:"fallback"},"😱 ",r.createElement("i",null,"Could not render ","t"===t?"this component":t,", see the console."))}},56189:(e,t,n)=>{"use strict";n.r(t),n.d(t,{componentDidCatch:()=>d,withErrorBoundary:()=>m});var r=n(5872),o=n.n(r),a=n(26394),i=n.n(a),s=n(69198),u=n.n(s),l=n(51379),c=n.n(l),p=n(10098),f=n.n(p),h=n(67294),d=console.error,m=function(e){return function(t){var n,r=e(),a=r.getComponent,s=r.fn,l=a("ErrorBoundary"),p=s.getDisplayName(t),d=function(e){c()(r,e);var n=f()(r);function r(){return i()(this,r),n.apply(this,arguments)}return u()(r,[{key:"render",value:function(){return h.createElement(l,{targetName:p,getComponent:a,fn:s},h.createElement(t,o()({},this.props,this.context)))}}]),r}(h.Component);return d.displayName="WithErrorBoundary(".concat(p,")"),(n=t).prototype&&n.prototype.isReactComponent&&(d.prototype.mapStateToProps=t.prototype.mapStateToProps),d}}},27621:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>d});var r=n(59036),o=n.n(r),a=n(77766),i=n.n(a),s=n(44494),u=n.n(s),l=n(7287),c=n.n(l),p=n(36195),f=n(29403),h=n(56189);const d=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.componentList,n=void 0===t?[]:t,r=e.fullOverride,a=void 0!==r&&r;return function(e){var t,r,s=e.getSystem,l=a?n:i()(t=[]).call(t,["App","BaseLayout","VersionPragmaFilter","InfoContainer","ServersContainer","SchemesContainer","AuthorizeBtnContainer","FilterContainer","Operations","OperationContainer","parameters","responses","OperationServers","Models","ModelWrapper"],o()(n)),d=c()(l,u()(r=Array(l.length)).call(r,(function(e,t){return t.fn.withErrorBoundary(e)})));return{fn:{componentDidCatch:h.componentDidCatch,withErrorBoundary:(0,h.withErrorBoundary)(s)},components:{ErrorBoundary:p.default,Fallback:f.default},wrapComponents:d}}}},57050:(e,t,n)=>{"use strict";n.r(t),n.d(t,{sampleFromSchemaGeneric:()=>U,inferSchema:()=>q,createXMLExample:()=>V,sampleFromSchema:()=>W,memoizedCreateXMLExample:()=>$,memoizedSampleFromSchema:()=>J});var r=n(23765),o=n.n(r),a=n(77766),i=n.n(a),s=n(81643),u=n.n(s),l=n(78914),c=n.n(l),p=n(41511),f=n.n(p),h=n(78580),d=n.n(h),m=n(77149),v=n.n(m),g=n(3649),y=n.n(g),b=n(94473),w=n.n(b),E=n(2991),x=n.n(E),_=n(59340),S=n.n(_),k=n(53479),A=n.n(k),C=n(14419),O=n.n(C),j=n(41609),I=n.n(j),T=n(90242),N=n(60314),P={string:function(e){return e.pattern?function(e){try{return new(O())(e).gen()}catch(e){return"string"}}(e.pattern):"string"},string_email:function(){return"user@example.com"},"string_date-time":function(){return(new Date).toISOString()},string_date:function(){return(new Date).toISOString().substring(0,10)},string_uuid:function(){return"3fa85f64-5717-4562-b3fc-2c963f66afa6"},string_hostname:function(){return"example.com"},string_ipv4:function(){return"198.51.100.42"},string_ipv6:function(){return"2001:0db8:5b96:0000:0000:426f:8e17:642a"},number:function(){return 0},number_float:function(){return 0},integer:function(){return 0},boolean:function(e){return"boolean"!=typeof e.default||e.default}},R=function(e){var t,n=e=(0,T.mz)(e),r=n.type,o=n.format,a=P[i()(t="".concat(r,"_")).call(t,o)]||P[r];return(0,T.Wl)(a)?a(e):"Unknown Type: "+e.type},M=function(e){return(0,T.XV)(e,"$$ref",(function(e){return"string"==typeof e&&u()(e).call(e,"#")>-1}))},D=["maxProperties","minProperties"],L=["minItems","maxItems"],B=["minimum","maximum","exclusiveMinimum","exclusiveMaximum"],F=["minLength","maxLength"],z=function e(t,n){var r,o,a,s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},l=function(e){void 0===n[e]&&void 0!==t[e]&&(n[e]=t[e])};(c()(r=i()(o=["example","default","enum","xml","type"]).call(o,D,L,B,F)).call(r,(function(e){return l(e)})),void 0!==t.required&&f()(t.required))&&(void 0!==n.required&&n.required.length||(n.required=[]),c()(a=t.required).call(a,(function(e){var t;d()(t=n.required).call(t,e)||n.required.push(e)})));if(t.properties){n.properties||(n.properties={});var p=(0,T.mz)(t.properties);for(var h in p){var m;if(Object.prototype.hasOwnProperty.call(p,h))if(!p[h]||!p[h].deprecated)if(!p[h]||!p[h].readOnly||s.includeReadOnly)if(!p[h]||!p[h].writeOnly||s.includeWriteOnly)if(!n.properties[h])n.properties[h]=p[h],!t.required&&f()(t.required)&&-1!==u()(m=t.required).call(m,h)&&(n.required?n.required.push(h):n.required=[h])}}return t.items&&(n.items||(n.items={}),n.items=e(t.items,n.items,s)),n},U=function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=arguments.length>3&&void 0!==arguments[3]&&arguments[3];t&&(0,T.Wl)(t.toJS)&&(t=t.toJS());var s=void 0!==r||t&&void 0!==t.example||t&&void 0!==t.default,l=!s&&t&&t.oneOf&&t.oneOf.length>0,p=!s&&t&&t.anyOf&&t.anyOf.length>0;if(!s&&(l||p)){var h=(0,T.mz)(l?t.oneOf[0]:t.anyOf[0]);if(z(h,t,n),!t.xml&&h.xml&&(t.xml=h.xml),void 0!==t.example&&void 0!==h.example)s=!0;else if(h.properties){t.properties||(t.properties={});var m=(0,T.mz)(h.properties);for(var g in m){var b;if(Object.prototype.hasOwnProperty.call(m,g))if(!m[g]||!m[g].deprecated)if(!m[g]||!m[g].readOnly||n.includeReadOnly)if(!m[g]||!m[g].writeOnly||n.includeWriteOnly)if(!t.properties[g])t.properties[g]=m[g],!h.required&&f()(h.required)&&-1!==u()(b=h.required).call(b,g)&&(t.required?t.required.push(g):t.required=[g])}}}var E,_={},S=t||{},k=S.xml,A=S.type,C=S.example,O=S.properties,j=S.additionalProperties,N=S.items,P=n.includeReadOnly,F=n.includeWriteOnly,U=k=k||{},q=U.name,V=U.prefix,W=U.namespace,H={};if(a&&(E=(V?V+":":"")+(q=q||"notagname"),W)){var $=V?"xmlns:"+V:"xmlns";_[$]=W}a&&(H[E]=[]);var J=function(e){return v()(e).call(e,(function(e){return Object.prototype.hasOwnProperty.call(t,e)}))};t&&!A&&(O||j||J(D)?A="object":N||J(L)?A="array":J(B)?(A="number",t.type="number"):s||t.enum||(A="string",t.type="string"));var K,G,Z=function(e){var n,r,o,a,i;null!==(null===(n=t)||void 0===n?void 0:n.maxItems)&&void 0!==(null===(r=t)||void 0===r?void 0:r.maxItems)&&(e=y()(e).call(e,0,null===(i=t)||void 0===i?void 0:i.maxItems));if(null!==(null===(o=t)||void 0===o?void 0:o.minItems)&&void 0!==(null===(a=t)||void 0===a?void 0:a.minItems))for(var s=0;e.length<(null===(u=t)||void 0===u?void 0:u.minItems);){var u;e.push(e[s++%e.length])}return e},Y=(0,T.mz)(O),Q=0,X=function(){return t&&null!==t.maxProperties&&void 0!==t.maxProperties&&Q>=t.maxProperties},ee=function(){if(!t||!t.required)return 0;var e,n,r=0;a?c()(e=t.required).call(e,(function(e){return r+=void 0===H[e]?0:1})):c()(n=t.required).call(n,(function(e){var t;return r+=void 0===(null===(t=H[E])||void 0===t?void 0:w()(t).call(t,(function(t){return void 0!==t[e]})))?0:1}));return t.required.length-r},te=function(e){var n;return!(t&&t.required&&t.required.length)||!d()(n=t.required).call(n,e)},ne=function(e){return!t||null===t.maxProperties||void 0===t.maxProperties||!X()&&(!te(e)||t.maxProperties-Q-ee()>0)};if(K=a?function(r){var o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;if(t&&Y[r]){if(Y[r].xml=Y[r].xml||{},Y[r].xml.attribute){var s=f()(Y[r].enum)?Y[r].enum[0]:void 0,u=Y[r].example,l=Y[r].default;return void(_[Y[r].xml.name||r]=void 0!==u?u:void 0!==l?l:void 0!==s?s:R(Y[r]))}Y[r].xml.name=Y[r].xml.name||r}else Y[r]||!1===j||(Y[r]={xml:{name:r}});var c,p=e(t&&Y[r]||void 0,n,o,a);ne(r)&&(Q++,f()(p)?H[E]=i()(c=H[E]).call(c,p):H[E].push(p))}:function(t,r){ne(t)&&(H[t]=e(Y[t],n,r,a),Q++)},s){var re;if(re=M(void 0!==r?r:void 0!==C?C:t.default),!a){if("number"==typeof re&&"string"===A)return"".concat(re);if("string"!=typeof re||"string"===A)return re;try{return JSON.parse(re)}catch(e){return re}}if(t||(A=f()(re)?"array":o()(re)),"array"===A){if(!f()(re)){if("string"==typeof re)return re;re=[re]}var oe=t?t.items:void 0;oe&&(oe.xml=oe.xml||k||{},oe.xml.name=oe.xml.name||k.name);var ae=x()(re).call(re,(function(t){return e(oe,n,t,a)}));return ae=Z(ae),k.wrapped?(H[E]=ae,I()(_)||H[E].push({_attr:_})):H=ae,H}if("object"===A){if("string"==typeof re)return re;for(var ie in re)Object.prototype.hasOwnProperty.call(re,ie)&&(t&&Y[ie]&&Y[ie].readOnly&&!P||t&&Y[ie]&&Y[ie].writeOnly&&!F||(t&&Y[ie]&&Y[ie].xml&&Y[ie].xml.attribute?_[Y[ie].xml.name||ie]=re[ie]:K(ie,re[ie])));return I()(_)||H[E].push({_attr:_}),H}return H[E]=I()(_)?re:[{_attr:_},re],H}if("object"===A){for(var se in Y)Object.prototype.hasOwnProperty.call(Y,se)&&(Y[se]&&Y[se].deprecated||Y[se]&&Y[se].readOnly&&!P||Y[se]&&Y[se].writeOnly&&!F||K(se));if(a&&_&&H[E].push({_attr:_}),X())return H;if(!0===j)a?H[E].push({additionalProp:"Anything can be here"}):H.additionalProp1={},Q++;else if(j){var ue=(0,T.mz)(j),le=e(ue,n,void 0,a);if(a&&ue.xml&&ue.xml.name&&"notagname"!==ue.xml.name)H[E].push(le);else for(var ce=null!==t.minProperties&&void 0!==t.minProperties&&Q{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(57050);function o(){return{fn:r}}},51228:(e,t,n)=>{"use strict";n.r(t),n.d(t,{UPDATE_SPEC:()=>ee,UPDATE_URL:()=>te,UPDATE_JSON:()=>ne,UPDATE_PARAM:()=>re,UPDATE_EMPTY_PARAM_INCLUSION:()=>oe,VALIDATE_PARAMS:()=>ae,SET_RESPONSE:()=>ie,SET_REQUEST:()=>se,SET_MUTATED_REQUEST:()=>ue,LOG_REQUEST:()=>le,CLEAR_RESPONSE:()=>ce,CLEAR_REQUEST:()=>pe,CLEAR_VALIDATE_PARAMS:()=>fe,UPDATE_OPERATION_META_VALUE:()=>he,UPDATE_RESOLVED:()=>de,UPDATE_RESOLVED_SUBTREE:()=>me,SET_SCHEME:()=>ve,updateSpec:()=>ge,updateResolved:()=>ye,updateUrl:()=>be,updateJsonSpec:()=>we,parseToJson:()=>Ee,resolveSpec:()=>_e,requestResolvedSubtree:()=>Ae,changeParam:()=>Ce,changeParamByIdentity:()=>Oe,updateResolvedSubtree:()=>je,invalidateResolvedSubtreeCache:()=>Ie,validateParams:()=>Te,updateEmptyParamInclusion:()=>Ne,clearValidateParams:()=>Pe,changeConsumesValue:()=>Re,changeProducesValue:()=>Me,setResponse:()=>De,setRequest:()=>Le,setMutatedRequest:()=>Be,logRequest:()=>Fe,executeRequest:()=>ze,execute:()=>Ue,clearResponse:()=>qe,clearRequest:()=>Ve,setScheme:()=>We});var r=n(95945),o=n.n(r),a=n(80122),i=n.n(a),s=n(51161),u=n.n(s),l=n(23765),c=n.n(l),p=n(63109),f=n.n(p),h=n(41511),d=n.n(h),m=n(2991),v=n.n(m),g=n(63978),y=n.n(g),b=n(32366),w=n.n(b),E=n(10062),x=n.n(E),_=n(93476),S=n.n(_),k=n(20116),A=n.n(k),C=n(20455),O=n.n(C),j=n(81643),I=n.n(j),T=n(78914),N=n.n(T),P=n(77766),R=n.n(P),M=n(86902),D=n.n(M),L=n(51942),B=n.n(L),F=n(11128),z=n.n(F),U=n(1272),q=n(43393),V=n(84564),W=n.n(V),H=n(7710),$=n(47037),J=n.n($),K=n(23279),G=n.n(K),Z=n(36968),Y=n.n(Z),Q=n(90242),X=["path","method"],ee="spec_update_spec",te="spec_update_url",ne="spec_update_json",re="spec_update_param",oe="spec_update_empty_param_inclusion",ae="spec_validate_param",ie="spec_set_response",se="spec_set_request",ue="spec_set_mutated_request",le="spec_log_request",ce="spec_clear_response",pe="spec_clear_request",fe="spec_clear_validate_param",he="spec_update_operation_meta_value",de="spec_update_resolved",me="spec_update_resolved_subtree",ve="set_scheme";function ge(e){var t,n=(t=e,J()(t)?t:"").replace(/\t/g," ");if("string"==typeof e)return{type:ee,payload:n}}function ye(e){return{type:de,payload:e}}function be(e){return{type:te,payload:e}}function we(e){return{type:ne,payload:e}}var Ee=function(e){return function(t){var n=t.specActions,r=t.specSelectors,o=t.errActions,a=r.specStr,i=null;try{e=e||a(),o.clear({source:"parser"}),i=U.ZP.load(e,{schema:U.A8})}catch(e){return console.error(e),o.newSpecErr({source:"parser",level:"error",message:e.reason,line:e.mark&&e.mark.line?e.mark.line+1:void 0})}return i&&"object"===c()(i)?n.updateJsonSpec(i):{}}},xe=!1,_e=function(e,t){return function(n){var r=n.specActions,o=n.specSelectors,a=n.errActions,i=n.fn,s=i.fetch,u=i.resolve,l=i.AST,c=void 0===l?{}:l,p=n.getConfigs;xe||(console.warn("specActions.resolveSpec is deprecated since v3.10.0 and will be removed in v4.0.0; use requestResolvedSubtree instead!"),xe=!0);var f=p(),h=f.modelPropertyMacro,m=f.parameterMacro,g=f.requestInterceptor,b=f.responseInterceptor;void 0===e&&(e=o.specJson()),void 0===t&&(t=o.url());var w=c.getLineNumberForPath?c.getLineNumberForPath:function(){},E=o.specStr();return u({fetch:s,spec:e,baseDoc:t,modelPropertyMacro:h,parameterMacro:m,requestInterceptor:g,responseInterceptor:b}).then((function(e){var t=e.spec,n=e.errors;if(a.clear({type:"thrown"}),d()(n)&&n.length>0){var o=v()(n).call(n,(function(e){return console.error(e),e.line=e.fullPath?w(E,e.fullPath):null,e.path=e.fullPath?e.fullPath.join("."):null,e.level="error",e.type="thrown",e.source="resolver",y()(e,"message",{enumerable:!0,value:e.message}),e}));a.newThrownErrBatch(o)}return r.updateResolved(t)}))}},Se=[],ke=G()(u()(f().mark((function e(){var t,n,r,o,a,i,s,l,c,p,h,m,g,b,E,_,k,C;return f().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(t=Se.system){e.next=4;break}return console.error("debResolveSubtrees: don't have a system to operate on, aborting."),e.abrupt("return");case 4:if(n=t.errActions,r=t.errSelectors,o=t.fn,a=o.resolveSubtree,i=o.fetch,s=o.AST,l=void 0===s?{}:s,c=t.specSelectors,p=t.specActions,a){e.next=8;break}return console.error("Error: Swagger-Client did not provide a `resolveSubtree` method, doing nothing."),e.abrupt("return");case 8:return h=l.getLineNumberForPath?l.getLineNumberForPath:function(){},m=c.specStr(),g=t.getConfigs(),b=g.modelPropertyMacro,E=g.parameterMacro,_=g.requestInterceptor,k=g.responseInterceptor,e.prev=11,e.next=14,w()(Se).call(Se,function(){var e=u()(f().mark((function e(t,o){var s,l,p,g,w,C,j,I,T;return f().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,t;case 2:return s=e.sent,l=s.resultMap,p=s.specWithCurrentSubtrees,e.next=7,a(p,o,{baseDoc:c.url(),modelPropertyMacro:b,parameterMacro:E,requestInterceptor:_,responseInterceptor:k});case 7:if(g=e.sent,w=g.errors,C=g.spec,r.allErrors().size&&n.clearBy((function(e){var t;return"thrown"!==e.get("type")||"resolver"!==e.get("source")||!x()(t=e.get("fullPath")).call(t,(function(e,t){return e===o[t]||void 0===o[t]}))})),d()(w)&&w.length>0&&(j=v()(w).call(w,(function(e){return e.line=e.fullPath?h(m,e.fullPath):null,e.path=e.fullPath?e.fullPath.join("."):null,e.level="error",e.type="thrown",e.source="resolver",y()(e,"message",{enumerable:!0,value:e.message}),e})),n.newThrownErrBatch(j)),!C||!c.isOAS3()||"components"!==o[0]||"securitySchemes"!==o[1]){e.next=15;break}return e.next=15,S().all(v()(I=A()(T=O()(C)).call(T,(function(e){return"openIdConnect"===e.type}))).call(I,function(){var e=u()(f().mark((function e(t){var n,r;return f().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n={url:t.openIdConnectUrl,requestInterceptor:_,responseInterceptor:k},e.prev=1,e.next=4,i(n);case 4:(r=e.sent)instanceof Error||r.status>=400?console.error(r.statusText+" "+n.url):t.openIdConnectData=JSON.parse(r.text),e.next=11;break;case 8:e.prev=8,e.t0=e.catch(1),console.error(e.t0);case 11:case"end":return e.stop()}}),e,null,[[1,8]])})));return function(t){return e.apply(this,arguments)}}()));case 15:return Y()(l,o,C),Y()(p,o,C),e.abrupt("return",{resultMap:l,specWithCurrentSubtrees:p});case 18:case"end":return e.stop()}}),e)})));return function(t,n){return e.apply(this,arguments)}}(),S().resolve({resultMap:(c.specResolvedSubtree([])||(0,q.Map)()).toJS(),specWithCurrentSubtrees:c.specJson().toJS()}));case 14:C=e.sent,delete Se.system,Se=[],e.next=22;break;case 19:e.prev=19,e.t0=e.catch(11),console.error(e.t0);case 22:p.updateResolvedSubtree([],C.resultMap);case 23:case"end":return e.stop()}}),e,null,[[11,19]])}))),35),Ae=function(e){return function(t){var n;I()(n=v()(Se).call(Se,(function(e){return e.join("@@")}))).call(n,e.join("@@"))>-1||(Se.push(e),Se.system=t,ke())}};function Ce(e,t,n,r,o){return{type:re,payload:{path:e,value:r,paramName:t,paramIn:n,isXml:o}}}function Oe(e,t,n,r){return{type:re,payload:{path:e,param:t,value:n,isXml:r}}}var je=function(e,t){return{type:me,payload:{path:e,value:t}}},Ie=function(){return{type:me,payload:{path:[],value:(0,q.Map)()}}},Te=function(e,t){return{type:ae,payload:{pathMethod:e,isOAS3:t}}},Ne=function(e,t,n,r){return{type:oe,payload:{pathMethod:e,paramName:t,paramIn:n,includeEmptyValue:r}}};function Pe(e){return{type:fe,payload:{pathMethod:e}}}function Re(e,t){return{type:he,payload:{path:e,value:t,key:"consumes_value"}}}function Me(e,t){return{type:he,payload:{path:e,value:t,key:"produces_value"}}}var De=function(e,t,n){return{payload:{path:e,method:t,res:n},type:ie}},Le=function(e,t,n){return{payload:{path:e,method:t,req:n},type:se}},Be=function(e,t,n){return{payload:{path:e,method:t,req:n},type:ue}},Fe=function(e){return{payload:e,type:le}},ze=function(e){return function(t){var n,r,o=t.fn,a=t.specActions,i=t.specSelectors,s=t.getConfigs,l=t.oas3Selectors,c=e.pathName,p=e.method,h=e.operation,m=s(),g=m.requestInterceptor,y=m.responseInterceptor,b=h.toJS();h&&h.get("parameters")&&N()(n=A()(r=h.get("parameters")).call(r,(function(e){return e&&!0===e.get("allowEmptyValue")}))).call(n,(function(t){if(i.parameterInclusionSettingFor([c,p],t.get("name"),t.get("in"))){e.parameters=e.parameters||{};var n=(0,Q.cz)(t,e.parameters);(!n||n&&0===n.size)&&(e.parameters[t.get("name")]="")}}));if(e.contextUrl=W()(i.url()).toString(),b&&b.operationId?e.operationId=b.operationId:b&&c&&p&&(e.operationId=o.opId(b,c,p)),i.isOAS3()){var w,E=R()(w="".concat(c,":")).call(w,p);e.server=l.selectedServer(E)||l.selectedServer();var x=l.serverVariables({server:e.server,namespace:E}).toJS(),_=l.serverVariables({server:e.server}).toJS();e.serverVariables=D()(x).length?x:_,e.requestContentType=l.requestContentType(c,p),e.responseContentType=l.responseContentType(c,p)||"*/*";var S,k=l.requestBodyValue(c,p),C=l.requestBodyInclusionSetting(c,p);if(k&&k.toJS)e.requestBody=A()(S=v()(k).call(k,(function(e){return q.Map.isMap(e)?e.get("value"):e}))).call(S,(function(e,t){return(d()(e)?0!==e.length:!(0,Q.O2)(e))||C.get(t)})).toJS();else e.requestBody=k}var O=B()({},e);O=o.buildRequest(O),a.setRequest(e.pathName,e.method,O);var j=function(){var t=u()(f().mark((function t(n){var r,o;return f().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,g.apply(undefined,[n]);case 2:return r=t.sent,o=B()({},r),a.setMutatedRequest(e.pathName,e.method,o),t.abrupt("return",r);case 6:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}();e.requestInterceptor=j,e.responseInterceptor=y;var I=z()();return o.execute(e).then((function(t){t.duration=z()()-I,a.setResponse(e.pathName,e.method,t)})).catch((function(t){"Failed to fetch"===t.message&&(t.name="",t.message='**Failed to fetch.** \n**Possible Reasons:** \n - CORS \n - Network Failure \n - URL scheme must be "http" or "https" for CORS request.'),a.setResponse(e.pathName,e.method,{error:!0,err:(0,H.serializeError)(t)})}))}},Ue=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.path,n=e.method,r=i()(e,X);return function(e){var a=e.fn.fetch,i=e.specSelectors,s=e.specActions,u=i.specJsonWithResolvedSubtrees().toJS(),l=i.operationScheme(t,n),c=i.contentTypeValues([t,n]).toJS(),p=c.requestContentType,f=c.responseContentType,h=/xml/i.test(p),d=i.parameterValues([t,n],h).toJS();return s.executeRequest(o()(o()({},r),{},{fetch:a,spec:u,pathName:t,method:n,parameters:d,requestContentType:p,scheme:l,responseContentType:f}))}};function qe(e,t){return{type:ce,payload:{path:e,method:t}}}function Ve(e,t){return{type:pe,payload:{path:e,method:t}}}function We(e,t,n){return{type:ve,payload:{scheme:e,path:t,method:n}}}},37038:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>s});var r=n(20032),o=n(51228),a=n(33881),i=n(77508);function s(){return{statePlugins:{spec:{wrapActions:i,reducers:r.default,actions:o,selectors:a}}}}},20032:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>E});var r,o=n(87672),a=n.n(o),i=n(59036),s=n.n(i),u=n(77766),l=n.n(u),c=n(32366),p=n.n(c),f=n(2991),h=n.n(f),d=n(51942),m=n.n(d),v=n(43393),g=n(90242),y=n(27504),b=n(33881),w=n(51228);const E=(r={},a()(r,w.UPDATE_SPEC,(function(e,t){return"string"==typeof t.payload?e.set("spec",t.payload):e})),a()(r,w.UPDATE_URL,(function(e,t){return e.set("url",t.payload+"")})),a()(r,w.UPDATE_JSON,(function(e,t){return e.set("json",(0,g.oG)(t.payload))})),a()(r,w.UPDATE_RESOLVED,(function(e,t){return e.setIn(["resolved"],(0,g.oG)(t.payload))})),a()(r,w.UPDATE_RESOLVED_SUBTREE,(function(e,t){var n,r=t.payload,o=r.value,a=r.path;return e.setIn(l()(n=["resolvedSubtrees"]).call(n,s()(a)),(0,g.oG)(o))})),a()(r,w.UPDATE_PARAM,(function(e,t){var n,r,o=t.payload,a=o.path,i=o.paramName,u=o.paramIn,c=o.param,p=o.value,f=o.isXml,h=c?(0,g.V9)(c):l()(n="".concat(u,".")).call(n,i),d=f?"value_xml":"value";return e.setIn(l()(r=["meta","paths"]).call(r,s()(a),["parameters",h,d]),p)})),a()(r,w.UPDATE_EMPTY_PARAM_INCLUSION,(function(e,t){var n,r,o=t.payload,a=o.pathMethod,i=o.paramName,u=o.paramIn,c=o.includeEmptyValue;if(!i||!u)return console.warn("Warning: UPDATE_EMPTY_PARAM_INCLUSION could not generate a paramKey."),e;var p=l()(n="".concat(u,".")).call(n,i);return e.setIn(l()(r=["meta","paths"]).call(r,s()(a),["parameter_inclusions",p]),c)})),a()(r,w.VALIDATE_PARAMS,(function(e,t){var n,r,o=t.payload,a=o.pathMethod,i=o.isOAS3,u=(0,b.specJsonWithResolvedSubtrees)(e).getIn(l()(n=["paths"]).call(n,s()(a))),c=(0,b.parameterValues)(e,a).toJS();return e.updateIn(l()(r=["meta","paths"]).call(r,s()(a),["parameters"]),(0,v.fromJS)({}),(function(t){var n;return p()(n=u.get("parameters",(0,v.List)())).call(n,(function(t,n){var r=(0,g.cz)(n,c),o=(0,b.parameterInclusionSettingFor)(e,a,n.get("name"),n.get("in")),s=(0,g.Ik)(n,r,{bypassRequiredCheck:o,isOAS3:i});return t.setIn([(0,g.V9)(n),"errors"],(0,v.fromJS)(s))}),t)}))})),a()(r,w.CLEAR_VALIDATE_PARAMS,(function(e,t){var n,r=t.payload.pathMethod;return e.updateIn(l()(n=["meta","paths"]).call(n,s()(r),["parameters"]),(0,v.fromJS)([]),(function(e){return h()(e).call(e,(function(e){return e.set("errors",(0,v.fromJS)([]))}))}))})),a()(r,w.SET_RESPONSE,(function(e,t){var n,r=t.payload,o=r.res,a=r.path,i=r.method;(n=o.error?m()({error:!0,name:o.err.name,message:o.err.message,statusCode:o.err.statusCode},o.err.response):o).headers=n.headers||{};var s=e.setIn(["responses",a,i],(0,g.oG)(n));return y.Z.Blob&&o.data instanceof y.Z.Blob&&(s=s.setIn(["responses",a,i,"text"],o.data)),s})),a()(r,w.SET_REQUEST,(function(e,t){var n=t.payload,r=n.req,o=n.path,a=n.method;return e.setIn(["requests",o,a],(0,g.oG)(r))})),a()(r,w.SET_MUTATED_REQUEST,(function(e,t){var n=t.payload,r=n.req,o=n.path,a=n.method;return e.setIn(["mutatedRequests",o,a],(0,g.oG)(r))})),a()(r,w.UPDATE_OPERATION_META_VALUE,(function(e,t){var n,r,o,a,i,u,c=t.payload,p=c.path,f=c.value,h=c.key,d=l()(n=["paths"]).call(n,s()(p)),m=l()(r=["meta","paths"]).call(r,s()(p));return e.getIn(l()(o=["json"]).call(o,s()(d)))||e.getIn(l()(a=["resolved"]).call(a,s()(d)))||e.getIn(l()(i=["resolvedSubtrees"]).call(i,s()(d)))?e.setIn(l()(u=[]).call(u,s()(m),[h]),(0,v.fromJS)(f)):e})),a()(r,w.CLEAR_RESPONSE,(function(e,t){var n=t.payload,r=n.path,o=n.method;return e.deleteIn(["responses",r,o])})),a()(r,w.CLEAR_REQUEST,(function(e,t){var n=t.payload,r=n.path,o=n.method;return e.deleteIn(["requests",r,o])})),a()(r,w.SET_SCHEME,(function(e,t){var n=t.payload,r=n.scheme,o=n.path,a=n.method;return o&&a?e.setIn(["scheme",o,a],r):o||a?void 0:e.setIn(["scheme","_defaultScheme"],r)})),r)},33881:(e,t,n)=>{"use strict";n.r(t),n.d(t,{lastError:()=>R,url:()=>M,specStr:()=>D,specSource:()=>L,specJson:()=>B,specResolved:()=>F,specResolvedSubtree:()=>z,specJsonWithResolvedSubtrees:()=>q,spec:()=>V,isOAS3:()=>W,info:()=>H,externalDocs:()=>$,version:()=>J,semver:()=>K,paths:()=>G,operations:()=>Z,consumes:()=>Y,produces:()=>Q,security:()=>X,securityDefinitions:()=>ee,findDefinition:()=>te,definitions:()=>ne,basePath:()=>re,host:()=>oe,schemes:()=>ae,operationsWithRootInherited:()=>ie,tags:()=>se,tagDetails:()=>ue,operationsWithTags:()=>le,taggedOperations:()=>ce,responses:()=>pe,requests:()=>fe,mutatedRequests:()=>he,responseFor:()=>de,requestFor:()=>me,mutatedRequestFor:()=>ve,allowTryItOutFor:()=>ge,parameterWithMetaByIdentity:()=>ye,parameterInclusionSettingFor:()=>be,parameterWithMeta:()=>we,operationWithMeta:()=>Ee,getParameter:()=>xe,hasHost:()=>_e,parameterValues:()=>Se,parametersIncludeIn:()=>ke,parametersIncludeType:()=>Ae,contentTypeValues:()=>Ce,currentProducesFor:()=>Oe,producesOptionsFor:()=>je,consumesOptionsFor:()=>Ie,operationScheme:()=>Te,canExecuteScheme:()=>Ne,validateBeforeExecute:()=>Pe,getOAS3RequiredRequestBodyContentType:()=>Re,isMediaTypeSchemaPropertiesEqual:()=>Me});var r=n(18777),o=n.n(r),a=n(59036),i=n.n(a),s=n(77766),u=n.n(s),l=n(3649),c=n.n(l),p=n(78914),f=n.n(p),h=n(81643),d=n.n(h),m=n(2991),v=n.n(m),g=n(20116),y=n.n(g),b=n(94473),w=n.n(b),E=n(32366),x=n.n(E),_=n(47302),S=n.n(_),k=n(77149),A=n.n(k),C=n(41511),O=n.n(C),j=n(20573),I=n(90242),T=n(43393),N=["get","put","post","delete","options","head","patch","trace"],P=function(e){return e||(0,T.Map)()},R=(0,j.P1)(P,(function(e){return e.get("lastError")})),M=(0,j.P1)(P,(function(e){return e.get("url")})),D=(0,j.P1)(P,(function(e){return e.get("spec")||""})),L=(0,j.P1)(P,(function(e){return e.get("specSource")||"not-editor"})),B=(0,j.P1)(P,(function(e){return e.get("json",(0,T.Map)())})),F=(0,j.P1)(P,(function(e){return e.get("resolved",(0,T.Map)())})),z=function(e,t){var n;return e.getIn(u()(n=["resolvedSubtrees"]).call(n,i()(t)),void 0)},U=function e(t,n){return T.Map.isMap(t)&&T.Map.isMap(n)?n.get("$$ref")?n:(0,T.OrderedMap)().mergeWith(e,t,n):n},q=(0,j.P1)(P,(function(e){return(0,T.OrderedMap)().mergeWith(U,e.get("json"),e.get("resolvedSubtrees"))})),V=function(e){return B(e)},W=(0,j.P1)(V,(function(){return!1})),H=(0,j.P1)(V,(function(e){return De(e&&e.get("info"))})),$=(0,j.P1)(V,(function(e){return De(e&&e.get("externalDocs"))})),J=(0,j.P1)(H,(function(e){return e&&e.get("version")})),K=(0,j.P1)(J,(function(e){var t;return c()(t=/v?([0-9]*)\.([0-9]*)\.([0-9]*)/i.exec(e)).call(t,1)})),G=(0,j.P1)(q,(function(e){return e.get("paths")})),Z=(0,j.P1)(G,(function(e){if(!e||e.size<1)return(0,T.List)();var t=(0,T.List)();return e&&f()(e)?(f()(e).call(e,(function(e,n){if(!e||!f()(e))return{};f()(e).call(e,(function(e,r){var o;d()(N).call(N,r)<0||(t=t.push((0,T.fromJS)({path:n,method:r,operation:e,id:u()(o="".concat(r,"-")).call(o,n)})))}))})),t):(0,T.List)()})),Y=(0,j.P1)(V,(function(e){return(0,T.Set)(e.get("consumes"))})),Q=(0,j.P1)(V,(function(e){return(0,T.Set)(e.get("produces"))})),X=(0,j.P1)(V,(function(e){return e.get("security",(0,T.List)())})),ee=(0,j.P1)(V,(function(e){return e.get("securityDefinitions")})),te=function(e,t){var n=e.getIn(["resolvedSubtrees","definitions",t],null),r=e.getIn(["json","definitions",t],null);return n||r||null},ne=(0,j.P1)(V,(function(e){var t=e.get("definitions");return T.Map.isMap(t)?t:(0,T.Map)()})),re=(0,j.P1)(V,(function(e){return e.get("basePath")})),oe=(0,j.P1)(V,(function(e){return e.get("host")})),ae=(0,j.P1)(V,(function(e){return e.get("schemes",(0,T.Map)())})),ie=(0,j.P1)(Z,Y,Q,(function(e,t,n){return v()(e).call(e,(function(e){return e.update("operation",(function(e){if(e){if(!T.Map.isMap(e))return;return e.withMutations((function(e){return e.get("consumes")||e.update("consumes",(function(e){return(0,T.Set)(e).merge(t)})),e.get("produces")||e.update("produces",(function(e){return(0,T.Set)(e).merge(n)})),e}))}return(0,T.Map)()}))}))})),se=(0,j.P1)(V,(function(e){var t=e.get("tags",(0,T.List)());return T.List.isList(t)?y()(t).call(t,(function(e){return T.Map.isMap(e)})):(0,T.List)()})),ue=function(e,t){var n,r=se(e)||(0,T.List)();return w()(n=y()(r).call(r,T.Map.isMap)).call(n,(function(e){return e.get("name")===t}),(0,T.Map)())},le=(0,j.P1)(ie,se,(function(e,t){return x()(e).call(e,(function(e,t){var n=(0,T.Set)(t.getIn(["operation","tags"]));return n.count()<1?e.update("default",(0,T.List)(),(function(e){return e.push(t)})):x()(n).call(n,(function(e,n){return e.update(n,(0,T.List)(),(function(e){return e.push(t)}))}),e)}),x()(t).call(t,(function(e,t){return e.set(t.get("name"),(0,T.List)())}),(0,T.OrderedMap)()))})),ce=function(e){return function(t){var n,r=(0,t.getConfigs)(),o=r.tagsSorter,a=r.operationsSorter;return v()(n=le(e).sortBy((function(e,t){return t}),(function(e,t){var n="function"==typeof o?o:I.wh.tagsSorter[o];return n?n(e,t):null}))).call(n,(function(t,n){var r="function"==typeof a?a:I.wh.operationsSorter[a],o=r?S()(t).call(t,r):t;return(0,T.Map)({tagDetails:ue(e,n),operations:o})}))}},pe=(0,j.P1)(P,(function(e){return e.get("responses",(0,T.Map)())})),fe=(0,j.P1)(P,(function(e){return e.get("requests",(0,T.Map)())})),he=(0,j.P1)(P,(function(e){return e.get("mutatedRequests",(0,T.Map)())})),de=function(e,t,n){return pe(e).getIn([t,n],null)},me=function(e,t,n){return fe(e).getIn([t,n],null)},ve=function(e,t,n){return he(e).getIn([t,n],null)},ge=function(){return!0},ye=function(e,t,n){var r,o,a=q(e).getIn(u()(r=["paths"]).call(r,i()(t),["parameters"]),(0,T.OrderedMap)()),s=e.getIn(u()(o=["meta","paths"]).call(o,i()(t),["parameters"]),(0,T.OrderedMap)()),l=v()(a).call(a,(function(e){var t,r,o,a=s.get(u()(t="".concat(n.get("in"),".")).call(t,n.get("name"))),i=s.get(u()(r=u()(o="".concat(n.get("in"),".")).call(o,n.get("name"),".hash-")).call(r,n.hashCode()));return(0,T.OrderedMap)().merge(e,a,i)}));return w()(l).call(l,(function(e){return e.get("in")===n.get("in")&&e.get("name")===n.get("name")}),(0,T.OrderedMap)())},be=function(e,t,n,r){var o,a,s=u()(o="".concat(r,".")).call(o,n);return e.getIn(u()(a=["meta","paths"]).call(a,i()(t),["parameter_inclusions",s]),!1)},we=function(e,t,n,r){var o,a=q(e).getIn(u()(o=["paths"]).call(o,i()(t),["parameters"]),(0,T.OrderedMap)()),s=w()(a).call(a,(function(e){return e.get("in")===r&&e.get("name")===n}),(0,T.OrderedMap)());return ye(e,t,s)},Ee=function(e,t,n){var r,o=q(e).getIn(["paths",t,n],(0,T.OrderedMap)()),a=e.getIn(["meta","paths",t,n],(0,T.OrderedMap)()),i=v()(r=o.get("parameters",(0,T.List)())).call(r,(function(r){return ye(e,[t,n],r)}));return(0,T.OrderedMap)().merge(o,a).set("parameters",i)};function xe(e,t,n,r){var o;t=t||[];var a=e.getIn(u()(o=["meta","paths"]).call(o,i()(t),["parameters"]),(0,T.fromJS)([]));return w()(a).call(a,(function(e){return T.Map.isMap(e)&&e.get("name")===n&&e.get("in")===r}))||(0,T.Map)()}var _e=(0,j.P1)(V,(function(e){var t=e.get("host");return"string"==typeof t&&t.length>0&&"/"!==t[0]}));function Se(e,t,n){var r;t=t||[];var o=Ee.apply(void 0,u()(r=[e]).call(r,i()(t))).get("parameters",(0,T.List)());return x()(o).call(o,(function(e,t){var r=n&&"body"===t.get("in")?t.get("value_xml"):t.get("value");return e.set((0,I.V9)(t,{allowHashes:!1}),r)}),(0,T.fromJS)({}))}function ke(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(T.List.isList(e))return A()(e).call(e,(function(e){return T.Map.isMap(e)&&e.get("in")===t}))}function Ae(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(T.List.isList(e))return A()(e).call(e,(function(e){return T.Map.isMap(e)&&e.get("type")===t}))}function Ce(e,t){var n,r;t=t||[];var o=q(e).getIn(u()(n=["paths"]).call(n,i()(t)),(0,T.fromJS)({})),a=e.getIn(u()(r=["meta","paths"]).call(r,i()(t)),(0,T.fromJS)({})),s=Oe(e,t),l=o.get("parameters")||new T.List,c=a.get("consumes_value")?a.get("consumes_value"):Ae(l,"file")?"multipart/form-data":Ae(l,"formData")?"application/x-www-form-urlencoded":void 0;return(0,T.fromJS)({requestContentType:c,responseContentType:s})}function Oe(e,t){var n,r;t=t||[];var o=q(e).getIn(u()(n=["paths"]).call(n,i()(t)),null);if(null!==o){var a=e.getIn(u()(r=["meta","paths"]).call(r,i()(t),["produces_value"]),null),s=o.getIn(["produces",0],null);return a||s||"application/json"}}function je(e,t){var n;t=t||[];var r=q(e),a=r.getIn(u()(n=["paths"]).call(n,i()(t)),null);if(null!==a){var s=t,l=o()(s,1)[0],c=a.get("produces",null),p=r.getIn(["paths",l,"produces"],null),f=r.getIn(["produces"],null);return c||p||f}}function Ie(e,t){var n;t=t||[];var r=q(e),a=r.getIn(u()(n=["paths"]).call(n,i()(t)),null);if(null!==a){var s=t,l=o()(s,1)[0],c=a.get("consumes",null),p=r.getIn(["paths",l,"consumes"],null),f=r.getIn(["consumes"],null);return c||p||f}}var Te=function(e,t,n){var r=e.get("url").match(/^([a-z][a-z0-9+\-.]*):/),o=O()(r)?r[1]:null;return e.getIn(["scheme",t,n])||e.getIn(["scheme","_defaultScheme"])||o||""},Ne=function(e,t,n){var r;return d()(r=["http","https"]).call(r,Te(e,t,n))>-1},Pe=function(e,t){var n;t=t||[];var r=e.getIn(u()(n=["meta","paths"]).call(n,i()(t),["parameters"]),(0,T.fromJS)([])),o=!0;return f()(r).call(r,(function(e){var t=e.get("errors");t&&t.count()&&(o=!1)})),o},Re=function(e,t){var n,r,o={requestBody:!1,requestContentType:{}},a=e.getIn(u()(n=["resolvedSubtrees","paths"]).call(n,i()(t),["requestBody"]),(0,T.fromJS)([]));return a.size<1||(a.getIn(["required"])&&(o.requestBody=a.getIn(["required"])),f()(r=a.getIn(["content"]).entrySeq()).call(r,(function(e){var t=e[0];if(e[1].getIn(["schema","required"])){var n=e[1].getIn(["schema","required"]).toJS();o.requestContentType[t]=n}}))),o},Me=function(e,t,n,r){var o;if((n||r)&&n===r)return!0;var a=e.getIn(u()(o=["resolvedSubtrees","paths"]).call(o,i()(t),["requestBody","content"]),(0,T.fromJS)([]));if(a.size<2||!n||!r)return!1;var s=a.getIn([n,"schema","properties"],(0,T.fromJS)([])),l=a.getIn([r,"schema","properties"],(0,T.fromJS)([]));return!!s.equals(l)};function De(e){return T.Map.isMap(e)?e:new T.Map}},77508:(e,t,n)=>{"use strict";n.r(t),n.d(t,{updateSpec:()=>l,updateJsonSpec:()=>c,executeRequest:()=>p,validateParams:()=>f});var r=n(86902),o=n.n(r),a=n(78914),i=n.n(a),s=n(27361),u=n.n(s),l=function(e,t){var n=t.specActions;return function(){e.apply(void 0,arguments),n.parseToJson.apply(n,arguments)}},c=function(e,t){var n=t.specActions;return function(){for(var t=arguments.length,r=new Array(t),a=0;a{"use strict";n.r(t),n.d(t,{loaded:()=>r});var r=function(e,t){return function(){e.apply(void 0,arguments);var n=t.getConfigs().withCredentials;void 0!==n&&(t.fn.fetch.withCredentials="string"==typeof n?"true"===n:!!n)}}},48792:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>Vn});var r={};n.r(r),n.d(r,{JsonPatchError:()=>Fe,_areEquals:()=>Ge,applyOperation:()=>We,applyPatch:()=>He,applyReducer:()=>$e,deepClone:()=>ze,getValueByPointer:()=>Ve,validate:()=>Ke,validator:()=>Je});var o={};n.r(o),n.d(o,{compare:()=>rt,generate:()=>tt,observe:()=>et,unobserve:()=>Xe});var a={};n.r(a),n.d(a,{cookie:()=>Cn,header:()=>An,path:()=>_n,query:()=>Sn});var i=n(77766),s=n.n(i),u=n(51161),l=n.n(u),c=n(63109),p=n.n(c),f=n(86418),h=n.n(f),d=n(23765),m=n.n(d),v=n(18777),g=n.n(v),y=n(78580),b=n.n(y),w=n(72119),E=n.n(w),x=n(66419),_=n.n(x),S=n(59340),k=n.n(S),A=n(2991),C=n.n(A),O=n(86902),j=n.n(O),I=n(26295),T=n.n(I),N=n(20116),P=n.n(N),R=(n(31905),n(92495)),M=n.n(R),D=n(1272);const L="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:window,{FormData:B,Blob:F,File:z}=L;var U=n(59036),q=n.n(U),V=n(3649),W=n.n(V),H=function(e){return":/?#[]@!$&'()*+,;=".indexOf(e)>-1},$=function(e){return/^[a-z0-9\-._~]+$/i.test(e)};function J(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=n.escape,o=arguments.length>2?arguments[2]:void 0;return"number"==typeof e&&(e=e.toString()),"string"==typeof e&&e.length&&r?o?JSON.parse(e):C()(t=q()(e)).call(t,(function(e){var t,n;if($(e))return e;if(H(e)&&"unsafe"===r)return e;var o=new TextEncoder;return C()(t=C()(n=_()(o.encode(e))).call(n,(function(e){var t;return W()(t="0".concat(e.toString(16).toUpperCase())).call(t,-2)}))).call(t,(function(e){return"%".concat(e)})).join("")})).join(""):e}function K(e){var t=e.value;return Array.isArray(t)?function(e){var t=e.key,n=e.value,r=e.style,o=e.explode,a=e.escape,i=function(e){return J(e,{escape:a})};if("simple"===r)return C()(n).call(n,(function(e){return i(e)})).join(",");if("label"===r)return".".concat(C()(n).call(n,(function(e){return i(e)})).join("."));if("matrix"===r)return C()(n).call(n,(function(e){return i(e)})).reduce((function(e,n){var r,a,i;return!e||o?s()(a=s()(i="".concat(e||"",";")).call(i,t,"=")).call(a,n):s()(r="".concat(e,",")).call(r,n)}),"");if("form"===r){var u=o?"&".concat(t,"="):",";return C()(n).call(n,(function(e){return i(e)})).join(u)}if("spaceDelimited"===r){var l=o?"".concat(t,"="):"";return C()(n).call(n,(function(e){return i(e)})).join(" ".concat(l))}if("pipeDelimited"===r){var c=o?"".concat(t,"="):"";return C()(n).call(n,(function(e){return i(e)})).join("|".concat(c))}return}(e):"object"===m()(t)?function(e){var t=e.key,n=e.value,r=e.style,o=e.explode,a=e.escape,i=function(e){return J(e,{escape:a})},u=j()(n);if("simple"===r)return u.reduce((function(e,t){var r,a,u,l=i(n[t]),c=o?"=":",",p=e?"".concat(e,","):"";return s()(r=s()(a=s()(u="".concat(p)).call(u,t)).call(a,c)).call(r,l)}),"");if("label"===r)return u.reduce((function(e,t){var r,a,u,l=i(n[t]),c=o?"=":".",p=e?"".concat(e,"."):".";return s()(r=s()(a=s()(u="".concat(p)).call(u,t)).call(a,c)).call(r,l)}),"");if("matrix"===r&&o)return u.reduce((function(e,t){var r,o,a=i(n[t]),u=e?"".concat(e,";"):";";return s()(r=s()(o="".concat(u)).call(o,t,"=")).call(r,a)}),"");if("matrix"===r)return u.reduce((function(e,r){var o,a,u=i(n[r]),l=e?"".concat(e,","):";".concat(t,"=");return s()(o=s()(a="".concat(l)).call(a,r,",")).call(o,u)}),"");if("form"===r)return u.reduce((function(e,t){var r,a,u,l,c=i(n[t]),p=e?s()(r="".concat(e)).call(r,o?"&":","):"",f=o?"=":",";return s()(a=s()(u=s()(l="".concat(p)).call(l,t)).call(u,f)).call(a,c)}),"");return}(e):function(e){var t,n=e.key,r=e.value,o=e.style,a=e.escape,i=function(e){return J(e,{escape:a})};if("simple"===o)return i(r);if("label"===o)return".".concat(i(r));if("matrix"===o)return s()(t=";".concat(n,"=")).call(t,i(r));if("form"===o)return i(r);if("deepObject"===o)return i(r,{},!0);return}(e)}const G=function(e,t){t.body=e};var Z={serializeRes:te,mergeInQueryOrForm:fe};function Y(e){return Q.apply(this,arguments)}function Q(){return Q=l()(p().mark((function e(t){var n,r,o,a,i,s=arguments;return p().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(n=s.length>1&&void 0!==s[1]?s[1]:{},"object"===m()(t)&&(t=(n=t).url),n.headers=n.headers||{},Z.mergeInQueryOrForm(n),n.headers&&j()(n.headers).forEach((function(e){var t=n.headers[e];"string"==typeof t&&(n.headers[e]=t.replace(/\n+/g," "))})),!n.requestInterceptor){e.next=12;break}return e.next=8,n.requestInterceptor(n);case 8:if(e.t0=e.sent,e.t0){e.next=11;break}e.t0=n;case 11:n=e.t0;case 12:return r=n.headers["content-type"]||n.headers["Content-Type"],/multipart\/form-data/i.test(r)&&n.body instanceof B&&(delete n.headers["content-type"],delete n.headers["Content-Type"]),e.prev=14,e.next=17,(n.userFetch||fetch)(n.url,n);case 17:return o=e.sent,e.next=20,Z.serializeRes(o,t,n);case 20:if(o=e.sent,!n.responseInterceptor){e.next=28;break}return e.next=24,n.responseInterceptor(o);case 24:if(e.t1=e.sent,e.t1){e.next=27;break}e.t1=o;case 27:o=e.t1;case 28:e.next=39;break;case 30:if(e.prev=30,e.t2=e.catch(14),o){e.next=34;break}throw e.t2;case 34:throw(a=new Error(o.statusText||"response status is ".concat(o.status))).status=o.status,a.statusCode=o.status,a.responseError=e.t2,a;case 39:if(o.ok){e.next=45;break}throw(i=new Error(o.statusText||"response status is ".concat(o.status))).status=o.status,i.statusCode=o.status,i.response=o,i;case 45:return e.abrupt("return",o);case 46:case"end":return e.stop()}}),e,null,[[14,30]])}))),Q.apply(this,arguments)}var X=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return/(json|xml|yaml|text)\b/.test(e)};function ee(e,t){return t&&(0===t.indexOf("application/json")||t.indexOf("+json")>0)?JSON.parse(e):D.ZP.load(e)}function te(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=n.loadSpec,o=void 0!==r&&r,a={ok:e.ok,url:e.url||t,status:e.status,statusText:e.statusText,headers:re(e.headers)},i=a.headers["content-type"],s=o||X(i),u=s?e.text:e.blob||e.buffer;return u.call(e).then((function(e){if(a.text=e,a.data=e,s)try{var t=ee(e,i);a.body=t,a.obj=t}catch(e){a.parseError=e}return a}))}function ne(e){return b()(e).call(e,", ")?e.split(", "):e}function re(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return"function"!=typeof E()(e)?{}:_()(E()(e).call(e)).reduce((function(e,t){var n=g()(t,2),r=n[0],o=n[1];return e[r]=ne(o),e}),{})}function oe(e,t){return t||"undefined"==typeof navigator||(t=navigator),t&&"ReactNative"===t.product?!(!e||"object"!==m()(e)||"string"!=typeof e.uri):void 0!==z&&e instanceof z||(void 0!==F&&e instanceof F||(!!ArrayBuffer.isView(e)||null!==e&&"object"===m()(e)&&"function"==typeof e.pipe))}function ae(e,t){return Array.isArray(e)&&e.some((function(e){return oe(e,t)}))}var ie={form:",",spaceDelimited:"%20",pipeDelimited:"|"},se={csv:",",ssv:"%20",tsv:"%09",pipes:"|"};function ue(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=t.collectionFormat,o=t.allowEmptyValue,a=t.serializationOption,i=t.encoding,s="object"!==m()(t)||Array.isArray(t)?t:t.value,u=n?function(e){return e.toString()}:function(e){return encodeURIComponent(e)},l=u(e);if(void 0===s&&o)return[[l,""]];if(oe(s)||ae(s))return[[l,s]];if(a)return le(e,s,n,a);if(i){if([m()(i.style),m()(i.explode),m()(i.allowReserved)].some((function(e){return"undefined"!==e}))){var c=i.style,p=i.explode,f=i.allowReserved;return le(e,s,n,{style:c,explode:p,allowReserved:f})}if(i.contentType){if("application/json"===i.contentType){var h="string"==typeof s?s:k()(s);return[[l,u(h)]]}return[[l,u(s.toString())]]}return"object"!==m()(s)?[[l,u(s)]]:Array.isArray(s)&&s.every((function(e){return"object"!==m()(e)}))?[[l,C()(s).call(s,u).join(",")]]:[[l,u(k()(s))]]}return"object"!==m()(s)?[[l,u(s)]]:Array.isArray(s)?"multi"===r?[[l,C()(s).call(s,u)]]:[[l,C()(s).call(s,u).join(se[r||"csv"])]]:[[l,""]]}function le(e,t,n,r){var o,a,i,u=r.style||"form",l=void 0===r.explode?"form"===u:r.explode,c=!n&&(r&&r.allowReserved?"unsafe":"reserved"),p=function(e){return J(e,{escape:c})},f=n?function(e){return e}:function(e){return J(e,{escape:c})};return"object"!==m()(t)?[[f(e),p(t)]]:Array.isArray(t)?l?[[f(e),C()(t).call(t,p)]]:[[f(e),C()(t).call(t,p).join(ie[u])]]:"deepObject"===u?C()(a=j()(t)).call(a,(function(n){var r;return[f(s()(r="".concat(e,"[")).call(r,n,"]")),p(t[n])]})):l?C()(i=j()(t)).call(i,(function(e){return[f(e),p(t[e])]})):[[f(e),C()(o=j()(t)).call(o,(function(e){var n;return[s()(n="".concat(f(e),",")).call(n,p(t[e]))]})).join(",")]]}function ce(e){return T()(e).reduce((function(e,t){var n,r=g()(t,2),o=r[0],a=r[1],i=h()(ue(o,a,!0));try{for(i.s();!(n=i.n()).done;){var s=g()(n.value,2),u=s[0],l=s[1];if(Array.isArray(l)){var c,p=h()(l);try{for(p.s();!(c=p.n()).done;){var f=c.value;if(ArrayBuffer.isView(f)){var d=new F([f]);e.append(u,d)}else e.append(u,f)}}catch(e){p.e(e)}finally{p.f()}}else if(ArrayBuffer.isView(l)){var m=new F([l]);e.append(u,m)}else e.append(u,l)}}catch(e){i.e(e)}finally{i.f()}return e}),new B)}function pe(e){var t=j()(e).reduce((function(t,n){var r,o=h()(ue(n,e[n]));try{for(o.s();!(r=o.n()).done;){var a=g()(r.value,2),i=a[0],s=a[1];t[i]=s}}catch(e){o.e(e)}finally{o.f()}return t}),{});return M().stringify(t,{encode:!1,indices:!1})||""}function fe(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.url,n=void 0===t?"":t,r=e.query,o=e.form,a=function(){for(var e=arguments.length,t=new Array(e),n=0;n=48&&t<=57))return!1;n++}return!0}function Re(e){return-1===e.indexOf("/")&&-1===e.indexOf("~")?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function Me(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function De(e){if(void 0===e)return!0;if(e)if(Array.isArray(e)){for(var t=0,n=e.length;t0&&"constructor"==s[l-1]))throw new TypeError("JSON-Patch: modifying `__proto__` or `constructor/prototype` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(n&&void 0===p&&(void 0===u[f]?p=s.slice(0,l).join("/"):l==c-1&&(p=t.path),void 0!==p&&h(t,0,e,p)),l++,Array.isArray(u)){if("-"===f)f=u.length;else{if(n&&!Pe(f))throw new Fe("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",a,t,e);Pe(f)&&(f=~~f)}if(l>=c){if(n&&"add"===t.op&&f>u.length)throw new Fe("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",a,t,e);if(!1===(i=qe[t.op].call(t,u,f,e)).test)throw new Fe("Test operation failed","TEST_OPERATION_FAILED",a,t,e);return i}}else if(l>=c){if(!1===(i=Ue[t.op].call(t,u,f,e)).test)throw new Fe("Test operation failed","TEST_OPERATION_FAILED",a,t,e);return i}if(u=u[f],n&&l0)throw new Fe('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,n);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new Fe("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new Fe("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&De(e.value))throw new Fe("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",t,e,n);if(n)if("add"==e.op){var o=e.path.split("/").length,a=r.split("/").length;if(o!==a+1&&o!==a)throw new Fe("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",t,e,n)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==r)throw new Fe("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",t,e,n)}else if("move"===e.op||"copy"===e.op){var i=Ke([{op:"_get",path:e.from,value:void 0}],n);if(i&&"OPERATION_PATH_UNRESOLVABLE"===i.name)throw new Fe("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",t,e,n)}}function Ke(e,t,n){try{if(!Array.isArray(e))throw new Fe("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(t)He(Ne(t),Ne(e),n||!0);else{n=n||Je;for(var r=0;r0&&(e.patches=[],e.callback&&e.callback(r)),r}function nt(e,t,n,r,o){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var a=Te(t),i=Te(e),s=!1,u=i.length-1;u>=0;u--){var l=e[p=i[u]];if(!Ie(t,p)||void 0===t[p]&&void 0!==l&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(o&&n.push({op:"test",path:r+"/"+Re(p),value:Ne(l)}),n.push({op:"remove",path:r+"/"+Re(p)}),s=!0):(o&&n.push({op:"test",path:r,value:e}),n.push({op:"replace",path:r,value:t}),!0);else{var c=t[p];"object"==typeof l&&null!=l&&"object"==typeof c&&null!=c&&Array.isArray(l)===Array.isArray(c)?nt(l,c,n,r+"/"+Re(p),o):l!==c&&(!0,o&&n.push({op:"test",path:r+"/"+Re(p),value:Ne(l)}),n.push({op:"replace",path:r+"/"+Re(p),value:Ne(c)}))}}if(s||a.length!=i.length)for(u=0;u0){var o=t(e,n[n.length-1],n);o&&(r=s()(r).call(r,o))}if(Array.isArray(e)){var a=C()(e).call(e,(function(e,r){return pt(e,t,s()(n).call(n,r))}));a&&(r=s()(r).call(r,a))}else if(mt(e)){var i,u=C()(i=j()(e)).call(i,(function(r){return pt(e[r],t,s()(n).call(n,r))}));u&&(r=s()(r).call(r,u))}return r=ht(r)}function ft(e){return Array.isArray(e)?e:[e]}function ht(e){var t;return s()(t=[]).apply(t,q()(C()(e).call(e,(function(e){return Array.isArray(e)?ht(e):e}))))}function dt(e){return P()(e).call(e,(function(e){return void 0!==e}))}function mt(e){return e&&"object"===m()(e)}function vt(e){return e&&"function"==typeof e}function gt(e){if(wt(e)){var t=e.op;return"add"===t||"remove"===t||"replace"===t}return!1}function yt(e){return gt(e)||wt(e)&&"mutation"===e.type}function bt(e){return yt(e)&&("add"===e.op||"replace"===e.op||"merge"===e.op||"mergeDeep"===e.op)}function wt(e){return e&&"object"===m()(e)}function Et(e,t){try{return Ve(e,t)}catch(e){return console.error(e),{}}}var xt=n(52424),_t=n.n(xt),St=n(94435),kt=n.n(St),At=n(8575);function Ct(e,t){function n(){Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack;for(var e=arguments.length,n=new Array(e),r=0;r-1&&-1===Tt.indexOf(n)||Nt.indexOf(r)>-1||Pt.some((function(e){return r.indexOf(e)>-1}))}function Mt(e,t){var n,r=e.split("#"),o=g()(r,2),a=o[0],i=o[1],u=At.resolve(a||"",t||"");return i?s()(n="".concat(u,"#")).call(n,i):u}var Dt="application/json, application/yaml",Lt=/^([a-z]+:\/\/|\/\/)/i,Bt=Ct("JSONRefError",(function(e,t,n){this.originalError=n,Ee()(this,t||{})})),Ft={},zt=new(_t()),Ut=[function(e){return"paths"===e[0]&&"responses"===e[3]&&"examples"===e[5]},function(e){return"paths"===e[0]&&"responses"===e[3]&&"content"===e[5]&&"example"===e[7]},function(e){return"paths"===e[0]&&"responses"===e[3]&&"content"===e[5]&&"examples"===e[7]&&"value"===e[9]},function(e){return"paths"===e[0]&&"requestBody"===e[3]&&"content"===e[4]&&"example"===e[6]},function(e){return"paths"===e[0]&&"requestBody"===e[3]&&"content"===e[4]&&"examples"===e[6]&&"value"===e[8]},function(e){return"paths"===e[0]&&"parameters"===e[2]&&"example"===e[4]},function(e){return"paths"===e[0]&&"parameters"===e[3]&&"example"===e[5]},function(e){return"paths"===e[0]&&"parameters"===e[2]&&"examples"===e[4]&&"value"===e[6]},function(e){return"paths"===e[0]&&"parameters"===e[3]&&"examples"===e[5]&&"value"===e[7]},function(e){return"paths"===e[0]&&"parameters"===e[2]&&"content"===e[4]&&"example"===e[6]},function(e){return"paths"===e[0]&&"parameters"===e[2]&&"content"===e[4]&&"examples"===e[6]&&"value"===e[8]},function(e){return"paths"===e[0]&&"parameters"===e[3]&&"content"===e[4]&&"example"===e[7]},function(e){return"paths"===e[0]&&"parameters"===e[3]&&"content"===e[5]&&"examples"===e[7]&&"value"===e[9]}],qt={key:"$ref",plugin:function(e,t,n,r){var o=r.getInstance(),a=W()(n).call(n,0,-1);if(!Rt(a)&&!function(e){return Ut.some((function(t){return t(e)}))}(a)){var i=r.getContext(n).baseDoc;if("string"!=typeof e)return new Bt("$ref: must be a string (JSON-Ref)",{$ref:e,baseDoc:i,fullPath:n});var u,l,c,p=Jt(e),f=p[0],h=p[1]||"";try{u=i||f?Ht(f,i):null}catch(t){return $t(t,{pointer:h,$ref:e,basePath:u,fullPath:n})}if(function(e,t,n,r){var o,a,i=zt.get(r);i||(i={},zt.set(r,i));var u=function(e){if(0===e.length)return"";return"/".concat(C()(e).call(e,Xt).join("/"))}(n),l=s()(o="".concat(t||"","#")).call(o,e),c=u.replace(/allOf\/\d+\/?/g,""),p=r.contextTree.get([]).baseDoc;if(t===p&&en(c,e))return!0;var f="",h=n.some((function(e){var t;return f=s()(t="".concat(f,"/")).call(t,Xt(e)),i[f]&&i[f].some((function(e){return en(e,l)||en(l,e)}))}));if(h)return!0;return void(i[c]=s()(a=i[c]||[]).call(a,l))}(h,u,a,r)&&!o.useCircularStructures){var d=Mt(e,u);return e===d?null:it.replace(n,d)}if(null==u?(c=Yt(h),void 0===(l=r.get(c))&&(l=new Bt("Could not resolve reference: ".concat(e),{pointer:h,$ref:e,baseDoc:i,fullPath:n}))):l=null!=(l=Kt(u,h)).__value?l.__value:l.catch((function(t){throw $t(t,{pointer:h,$ref:e,baseDoc:i,fullPath:n})})),l instanceof Error)return[it.remove(n),l];var m=Mt(e,u),v=it.replace(a,l,{$$ref:m});if(u&&u!==i)return[v,it.context(a,{baseDoc:u})];try{if(!function(e,t){var n=[e];return t.path.reduce((function(e,t){return n.push(e[t]),e[t]}),e),r(t.value);function r(e){return it.isObject(e)&&(n.indexOf(e)>=0||j()(e).some((function(t){return r(e[t])})))}}(r.state,v)||o.useCircularStructures)return v}catch(e){return null}}}},Vt=Ee()(qt,{docCache:Ft,absoluteify:Ht,clearCache:function(e){void 0!==e?delete Ft[e]:j()(Ft).forEach((function(e){delete Ft[e]}))},JSONRefError:Bt,wrapError:$t,getDoc:Gt,split:Jt,extractFromDoc:Kt,fetchJSON:function(e){return fetch(e,{headers:{Accept:Dt},loadSpec:!0}).then((function(e){return e.text()})).then((function(e){return D.ZP.load(e)}))},extract:Zt,jsonPointerToArray:Yt,unescapeJsonPointerToken:Qt});const Wt=Vt;function Ht(e,t){if(!Lt.test(e)){var n;if(!t)throw new Bt(s()(n="Tried to resolve a relative URL, without having a basePath. path: '".concat(e,"' basePath: '")).call(n,t,"'"));return At.resolve(t,e)}return e}function $t(e,t){var n,r;e&&e.response&&e.response.body?n=s()(r="".concat(e.response.body.code," ")).call(r,e.response.body.message):n=e.message;return new Bt("Could not resolve reference: ".concat(n),t,e)}function Jt(e){return(e+"").split("#")}function Kt(e,t){var n=Ft[e];if(n&&!it.isPromise(n))try{var r=Zt(t,n);return Ee()(ke().resolve(r),{__value:r})}catch(e){return ke().reject(e)}return Gt(e).then((function(e){return Zt(t,e)}))}function Gt(e){var t=Ft[e];return t?it.isPromise(t)?t:ke().resolve(t):(Ft[e]=Vt.fetchJSON(e).then((function(t){return Ft[e]=t,t})),Ft[e])}function Zt(e,t){var n=Yt(e);if(n.length<1)return t;var r=it.getIn(t,n);if(void 0===r)throw new Bt("Could not resolve pointer: ".concat(e," does not exist in document"),{pointer:e});return r}function Yt(e){var t;if("string"!=typeof e)throw new TypeError("Expected a string, got a ".concat(m()(e)));return"/"===e[0]&&(e=e.substr(1)),""===e?[]:C()(t=e.split("/")).call(t,Qt)}function Qt(e){return"string"!=typeof e?e:new(kt())("=".concat(e.replace(/~1/g,"/").replace(/~0/g,"~"))).get("")}function Xt(e){var t,n=new(kt())([["",e.replace(/~/g,"~0").replace(/\//g,"~1")]]);return W()(t=n.toString()).call(t,1)}function en(e,t){if(!(n=t)||"/"===n||"#"===n)return!0;var n,r=e.charAt(t.length),o=W()(t).call(t,-1);return 0===e.indexOf(t)&&(!r||"/"===r||"#"===r)&&"#"!==o}const tn={key:"allOf",plugin:function(e,t,n,r,o){if(!o.meta||!o.meta.$$ref){var a=W()(n).call(n,0,-1);if(!Rt(a)){if(!Array.isArray(e)){var i=new TypeError("allOf must be an array");return i.fullPath=n,i}var u=!1,l=o.value;if(a.forEach((function(e){l&&(l=l[e])})),l=me()({},l),0!==j()(l).length){delete l.allOf;var c,p,f=[];if(f.push(r.replace(a,{})),e.forEach((function(e,t){if(!r.isObject(e)){if(u)return null;u=!0;var o=new TypeError("Elements in allOf must be objects");return o.fullPath=n,f.push(o)}f.push(r.mergeDeep(a,e));var i=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=n.specmap,o=n.getBaseUrlForNodePath,a=void 0===o?function(e){var n;return r.getContext(s()(n=[]).call(n,q()(t),q()(e))).baseDoc}:o,i=n.targetKeys,u=void 0===i?["$ref","$$ref"]:i,l=[];return jt()(e).forEach((function(){if(b()(u).call(u,this.key)&&"string"==typeof this.node){var e=this.path,n=s()(t).call(t,this.path),o=Mt(this.node,a(e));l.push(r.replace(n,o))}})),l}(e,W()(n).call(n,0,-1),{getBaseUrlForNodePath:function(e){var o;return r.getContext(s()(o=[]).call(o,q()(n),[t],q()(e))).baseDoc},specmap:r});f.push.apply(f,q()(i))})),l.example)f.push(r.remove(s()(c=[]).call(c,a,"example")));if(f.push(r.mergeDeep(a,l)),!l.$$ref)f.push(r.remove(s()(p=[]).call(p,a,"$$ref")));return f}}}}},nn={key:"parameters",plugin:function(e,t,n,r){if(Array.isArray(e)&&e.length){var o=Ee()([],e),a=W()(n).call(n,0,-1),i=me()({},it.getIn(r.spec,a));return e.forEach((function(e,t){try{o[t].default=r.parameterMacro(i,e)}catch(e){var a=new Error(e);return a.fullPath=n,a}})),it.replace(n,o)}return it.replace(n,e)}},rn={key:"properties",plugin:function(e,t,n,r){var o=me()({},e);for(var a in e)try{o[a].default=r.modelPropertyMacro(o[a])}catch(e){var i=new Error(e);return i.fullPath=n,i}return it.replace(n,o)}};var on=function(){function e(t){ge()(this,e),this.root=an(t||{})}return be()(e,[{key:"set",value:function(e,t){var n=this.getParent(e,!0);if(n){var r=e[e.length-1],o=n.children;o[r]?sn(o[r],t,n):o[r]=an(t,n)}else sn(this.root,t,null)}},{key:"get",value:function(e){if((e=e||[]).length<1)return this.root.value;for(var t,n,r=this.root,o=0;o1?n-1:0),o=1;o1?r-1:0),a=1;a0}))}},{key:"nextPromisedPatch",value:function(){var e;if(this.promisedPatches.length>0)return ke().race(C()(e=this.promisedPatches).call(e,(function(e){return e.value})))}},{key:"getPluginHistory",value:function(e){var t=this.constructor.getPluginName(e);return this.pluginHistory[t]||[]}},{key:"getPluginRunCount",value:function(e){return this.getPluginHistory(e).length}},{key:"getPluginHistoryTip",value:function(e){var t=this.getPluginHistory(e);return t&&t[t.length-1]||{}}},{key:"getPluginMutationIndex",value:function(e){var t=this.getPluginHistoryTip(e).mutationIndex;return"number"!=typeof t?-1:t}},{key:"updatePluginHistory",value:function(e,t){var n=this.constructor.getPluginName(e);this.pluginHistory[n]=this.pluginHistory[n]||[],this.pluginHistory[n].push(t)}},{key:"updatePatches",value:function(e){var t=this;it.normalizeArray(e).forEach((function(e){if(e instanceof Error)t.errors.push(e);else try{if(!it.isObject(e))return void t.debug("updatePatches","Got a non-object patch",e);if(t.showDebug&&t.allPatches.push(e),it.isPromise(e.value))return t.promisedPatches.push(e),void t.promisedPatchThen(e);if(it.isContextPatch(e))return void t.setContext(e.path,e.value);if(it.isMutation(e))return void t.updateMutations(e)}catch(e){console.error(e),t.errors.push(e)}}))}},{key:"updateMutations",value:function(e){"object"===m()(e.value)&&!Array.isArray(e.value)&&this.allowMetaPatches&&(e.value=me()({},e.value));var t=it.applyPatch(this.state,e,{allowMetaPatches:this.allowMetaPatches});t&&(this.mutations.push(e),this.state=t)}},{key:"removePromisedPatch",value:function(e){var t,n=this.promisedPatches.indexOf(e);n<0?this.debug("Tried to remove a promisedPatch that isn't there!"):Ce()(t=this.promisedPatches).call(t,n,1)}},{key:"promisedPatchThen",value:function(e){var t=this;return e.value=e.value.then((function(n){var r=me()(me()({},e),{},{value:n});t.removePromisedPatch(e),t.updatePatches(r)})).catch((function(n){t.removePromisedPatch(e),t.updatePatches(n)})),e.value}},{key:"getMutations",value:function(e,t){var n;return e=e||0,"number"!=typeof t&&(t=this.mutations.length),W()(n=this.mutations).call(n,e,t)}},{key:"getCurrentMutations",value:function(){return this.getMutationsForPlugin(this.getCurrentPlugin())}},{key:"getMutationsForPlugin",value:function(e){var t=this.getPluginMutationIndex(e);return this.getMutations(t+1)}},{key:"getCurrentPlugin",value:function(){return this.currentPlugin}},{key:"getLib",value:function(){return this.libMethods}},{key:"_get",value:function(e){return it.getIn(this.state,e)}},{key:"_getContext",value:function(e){return this.contextTree.get(e)}},{key:"setContext",value:function(e,t){return this.contextTree.set(e,t)}},{key:"_hasRun",value:function(e){return this.getPluginRunCount(this.getCurrentPlugin())>(e||0)}},{key:"dispatch",value:function(){var e,t=this,n=this,r=this.nextPlugin();if(!r){var o=this.nextPromisedPatch();if(o)return o.then((function(){return t.dispatch()})).catch((function(){return t.dispatch()}));var a={spec:this.state,errors:this.errors};return this.showDebug&&(a.patches=this.allPatches),ke().resolve(a)}if(n.pluginCount=n.pluginCount||{},n.pluginCount[r]=(n.pluginCount[r]||0)+1,n.pluginCount[r]>100)return ke().resolve({spec:n.state,errors:s()(e=n.errors).call(e,new Error("We've reached a hard limit of ".concat(100," plugin runs")))});if(r!==this.currentPlugin&&this.promisedPatches.length){var i,u=C()(i=this.promisedPatches).call(i,(function(e){return e.value}));return ke().all(C()(u).call(u,(function(e){return e.then(un,un)}))).then((function(){return t.dispatch()}))}return function(){n.currentPlugin=r;var e=n.getCurrentMutations(),t=n.mutations.length-1;try{if(r.isGenerator){var o,a=h()(r(e,n.getLib()));try{for(a.s();!(o=a.n()).done;){l(o.value)}}catch(e){a.e(e)}finally{a.f()}}else{l(r(e,n.getLib()))}}catch(e){console.error(e),l([Ee()(Object.create(e),{plugin:r})])}finally{n.updatePluginHistory(r,{mutationIndex:t})}return n.dispatch()}();function l(e){e&&(e=it.fullyNormalizeArray(e),n.updatePatches(e,r))}}}],[{key:"getPluginName",value:function(e){return e.pluginName}},{key:"getPatchesOfType",value:function(e,t){return P()(e).call(e,t)}}]),e}();var cn={refs:Wt,allOf:tn,parameters:nn,properties:rn},pn=n(23159);function fn(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.requestInterceptor,r=t.responseInterceptor,o=e.withCredentials?"include":"same-origin";return function(t){return e({url:t,loadSpec:!0,requestInterceptor:n,responseInterceptor:r,headers:{Accept:Dt},credentials:o}).then((function(e){return e.body}))}}function hn(e){var t=e.fetch,n=e.spec,r=e.url,o=e.mode,a=e.allowMetaPatches,i=void 0===a||a,s=e.pathDiscriminator,u=e.modelPropertyMacro,c=e.parameterMacro,f=e.requestInterceptor,h=e.responseInterceptor,d=e.skipNormalization,m=e.useCircularStructures,v=e.http,g=e.baseDoc;return g=g||r,v=t||v||Y,n?y(n):fn(v,{requestInterceptor:f,responseInterceptor:h})(g).then(y);function y(e){g&&(cn.refs.docCache[g]=e),cn.refs.fetchJSON=fn(v,{requestInterceptor:f,responseInterceptor:h});var t,n=[cn.refs];return"function"==typeof c&&n.push(cn.parameters),"function"==typeof u&&n.push(cn.properties),"strict"!==o&&n.push(cn.allOf),(t={spec:e,context:{baseDoc:g},plugins:n,allowMetaPatches:i,pathDiscriminator:s,parameterMacro:c,modelPropertyMacro:u,useCircularStructures:m},new ln(t).dispatch()).then(d?function(){var e=l()(p().mark((function e(t){return p().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",t);case 1:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}():pn.K1)}}var dn=n(80122),mn=n.n(dn),vn=n(27361),gn=n.n(vn),yn=n(30006);function bn(e){return"[object Object]"===Object.prototype.toString.call(e)}function wn(e){var t,n;return!1!==bn(e)&&(void 0===(t=e.constructor)||!1!==bn(n=t.prototype)&&!1!==n.hasOwnProperty("isPrototypeOf"))}const En={body:function(e){var t=e.req,n=e.value;t.body=n},header:function(e){var t=e.req,n=e.parameter,r=e.value;t.headers=t.headers||{},void 0!==r&&(t.headers[n.name]=r)},query:function(e){var t=e.req,n=e.value,r=e.parameter;t.query=t.query||{},!1===n&&"boolean"===r.type&&(n="false");0===n&&["number","integer"].indexOf(r.type)>-1&&(n="0");if(n)t.query[r.name]={collectionFormat:r.collectionFormat,value:n};else if(r.allowEmptyValue&&void 0!==n){var o=r.name;t.query[o]=t.query[o]||{},t.query[o].allowEmptyValue=!0}},path:function(e){var t=e.req,n=e.value,r=e.parameter;t.url=t.url.split("{".concat(r.name,"}")).join(encodeURIComponent(n))},formData:function(e){var t=e.req,n=e.value,r=e.parameter;(n||r.allowEmptyValue)&&(t.form=t.form||{},t.form[r.name]={value:n,allowEmptyValue:r.allowEmptyValue,collectionFormat:r.collectionFormat})}};function xn(e,t){return b()(t).call(t,"application/json")?"string"==typeof e?e:k()(e):e.toString()}function _n(e){var t=e.req,n=e.value,r=e.parameter,o=r.name,a=r.style,i=r.explode,s=r.content;if(s){var u=j()(s)[0];t.url=t.url.split("{".concat(o,"}")).join(J(xn(n,u),{escape:!0}))}else{var l=K({key:r.name,value:n,style:a||"simple",explode:i||!1,escape:!0});t.url=t.url.split("{".concat(o,"}")).join(l)}}function Sn(e){var t=e.req,n=e.value,r=e.parameter;if(t.query=t.query||{},r.content){var o=j()(r.content)[0];t.query[r.name]=xn(n,o)}else if(!1===n&&(n="false"),0===n&&(n="0"),n){var a=r.style,i=r.explode,s=r.allowReserved;t.query[r.name]={value:n,serializationOption:{style:a,explode:i,allowReserved:s}}}else if(r.allowEmptyValue&&void 0!==n){var u=r.name;t.query[u]=t.query[u]||{},t.query[u].allowEmptyValue=!0}}var kn=["accept","authorization","content-type"];function An(e){var t=e.req,n=e.parameter,r=e.value;if(t.headers=t.headers||{},!(kn.indexOf(n.name.toLowerCase())>-1))if(n.content){var o=j()(n.content)[0];t.headers[n.name]=xn(r,o)}else void 0!==r&&(t.headers[n.name]=K({key:n.name,value:r,style:n.style||"simple",explode:void 0!==n.explode&&n.explode,escape:!1}))}function Cn(e){var t=e.req,n=e.parameter,r=e.value;t.headers=t.headers||{};var o=m()(r);if(n.content){var a,i=j()(n.content)[0];t.headers.Cookie=s()(a="".concat(n.name,"=")).call(a,xn(r,i))}else if("undefined"!==o){var u="object"===o&&!Array.isArray(r)&&n.explode?"":"".concat(n.name,"=");t.headers.Cookie=u+K({key:n.name,value:r,escape:!1,style:n.style||"form",explode:void 0!==n.explode&&n.explode})}}var On=n(90149),jn=n.n(On);const In=(void 0!==jn()?jn():"undefined"!=typeof self?self:window).btoa;function Tn(e,t){var n=e.operation,r=e.requestBody,o=e.securities,a=e.spec,i=e.attachContentTypeForEmptyPayload,u=e.requestContentType;t=function(e){var t=e.request,n=e.securities,r=void 0===n?{}:n,o=e.operation,a=void 0===o?{}:o,i=e.spec,u=me()({},t),l=r.authorized,c=void 0===l?{}:l,p=a.security||i.security||[],f=c&&!!j()(c).length,h=gn()(i,["components","securitySchemes"])||{};if(u.headers=u.headers||{},u.query=u.query||{},!j()(r).length||!f||!p||Array.isArray(a.security)&&!a.security.length)return t;return p.forEach((function(e){j()(e).forEach((function(e){var t=c[e],n=h[e];if(t){var r=t.value||t,o=n.type;if(t)if("apiKey"===o)"query"===n.in&&(u.query[n.name]=r),"header"===n.in&&(u.headers[n.name]=r),"cookie"===n.in&&(u.cookies[n.name]=r);else if("http"===o){if(/^basic$/i.test(n.scheme)){var a,i=r.username||"",l=r.password||"",p=In(s()(a="".concat(i,":")).call(a,l));u.headers.Authorization="Basic ".concat(p)}/^bearer$/i.test(n.scheme)&&(u.headers.Authorization="Bearer ".concat(r))}else if("oauth2"===o||"openIdConnect"===o){var f,d=t.token||{},m=d[n["x-tokenName"]||"access_token"],v=d.token_type;v&&"bearer"!==v.toLowerCase()||(v="Bearer"),u.headers.Authorization=s()(f="".concat(v," ")).call(f,m)}}}))})),u}({request:t,securities:o,operation:n,spec:a});var l=n.requestBody||{},c=j()(l.content||{}),p=u&&c.indexOf(u)>-1;if(r||i){if(u&&p)t.headers["Content-Type"]=u;else if(!u){var f=c[0];f&&(t.headers["Content-Type"]=f,u=f)}}else u&&p&&(t.headers["Content-Type"]=u);if(!e.responseContentType&&n.responses){var h,d=P()(h=T()(n.responses)).call(h,(function(e){var t=g()(e,2),n=t[0],r=t[1],o=parseInt(n,10);return o>=200&&o<300&&wn(r.content)})).reduce((function(e,t){var n=g()(t,2)[1];return s()(e).call(e,j()(n.content))}),[]);d.length>0&&(t.headers.accept=d.join(", "))}if(r)if(u){if(c.indexOf(u)>-1)if("application/x-www-form-urlencoded"===u||"multipart/form-data"===u)if("object"===m()(r)){var v=(l.content[u]||{}).encoding||{};t.form={},j()(r).forEach((function(e){t.form[e]={value:r[e],encoding:v[e]||{}}}))}else t.form=r;else t.body=r}else t.body=r;return t}function Nn(e,t){var n,r,o=e.spec,a=e.operation,i=e.securities,u=e.requestContentType,l=e.responseContentType,c=e.attachContentTypeForEmptyPayload;if(t=function(e){var t=e.request,n=e.securities,r=void 0===n?{}:n,o=e.operation,a=void 0===o?{}:o,i=e.spec,u=me()({},t),l=r.authorized,c=void 0===l?{}:l,p=r.specSecurity,f=void 0===p?[]:p,h=a.security||f,d=c&&!!j()(c).length,m=i.securityDefinitions;if(u.headers=u.headers||{},u.query=u.query||{},!j()(r).length||!d||!h||Array.isArray(a.security)&&!a.security.length)return t;return h.forEach((function(e){j()(e).forEach((function(e){var t=c[e];if(t){var n=t.token,r=t.value||t,o=m[e],a=o.type,i=o["x-tokenName"]||"access_token",l=n&&n[i],p=n&&n.token_type;if(t)if("apiKey"===a){var f="query"===o.in?"query":"headers";u[f]=u[f]||{},u[f][o.name]=r}else if("basic"===a)if(r.header)u.headers.authorization=r.header;else{var h,d=r.username||"",v=r.password||"";r.base64=In(s()(h="".concat(d,":")).call(h,v)),u.headers.authorization="Basic ".concat(r.base64)}else if("oauth2"===a&&l){var g;p=p&&"bearer"!==p.toLowerCase()?p:"Bearer",u.headers.authorization=s()(g="".concat(p," ")).call(g,l)}}}))})),u}({request:t,securities:i,operation:a,spec:o}),t.body||t.form||c)if(u)t.headers["Content-Type"]=u;else if(Array.isArray(a.consumes)){var p=g()(a.consumes,1);t.headers["Content-Type"]=p[0]}else if(Array.isArray(o.consumes)){var f=g()(o.consumes,1);t.headers["Content-Type"]=f[0]}else a.parameters&&P()(n=a.parameters).call(n,(function(e){return"file"===e.type})).length?t.headers["Content-Type"]="multipart/form-data":a.parameters&&P()(r=a.parameters).call(r,(function(e){return"formData"===e.in})).length&&(t.headers["Content-Type"]="application/x-www-form-urlencoded");else if(u){var h,d,m=a.parameters&&P()(h=a.parameters).call(h,(function(e){return"body"===e.in})).length>0,v=a.parameters&&P()(d=a.parameters).call(d,(function(e){return"formData"===e.in})).length>0;(m||v)&&(t.headers["Content-Type"]=u)}return!l&&Array.isArray(a.produces)&&a.produces.length>0&&(t.headers.accept=a.produces.join(", ")),t}var Pn=["http","fetch","spec","operationId","pathName","method","parameters","securities"],Rn=function(e){return Array.isArray(e)?e:[]},Mn=Ct("OperationNotFoundError",(function(e,t,n){this.originalError=n,Ee()(this,t||{})})),Dn={buildRequest:Bn};function Ln(e){var t=e.http,n=e.fetch,r=e.spec,o=e.operationId,a=e.pathName,i=e.method,s=e.parameters,u=e.securities,l=mn()(e,Pn),c=t||n||Y;a&&i&&!o&&(o=(0,pn.nc)(a,i));var p=Dn.buildRequest(me()({spec:r,operationId:o,parameters:s,securities:u,http:c},l));return p.body&&(wn(p.body)||Array.isArray(p.body))&&(p.body=k()(p.body)),c(p)}function Bn(e){var t,n,r=e.spec,o=e.operationId,i=e.responseContentType,u=e.scheme,l=e.requestInterceptor,c=e.responseInterceptor,p=e.contextUrl,f=e.userFetch,h=e.server,d=e.serverVariables,m=e.http,v=e.signal,y=e.parameters,b=e.parameterBuilders,w=(0,pn.z6)(r);b||(b=w?a:En);var E={url:"",credentials:m&&m.withCredentials?"include":"same-origin",headers:{},cookies:{}};v&&(E.signal=v),l&&(E.requestInterceptor=l),c&&(E.responseInterceptor=c),f&&(E.userFetch=f);var x=(0,pn.$r)(r,o);if(!x)throw new Mn("Operation ".concat(o," not found"));var _,S=x.operation,k=void 0===S?{}:S,A=x.method,O=x.pathName;if(E.url+=(_={spec:r,scheme:u,contextUrl:p,server:h,serverVariables:d,pathName:O,method:A},(0,pn.z6)(_.spec)?function(e){var t=e.spec,n=e.pathName,r=e.method,o=e.server,a=e.contextUrl,i=e.serverVariables,u=void 0===i?{}:i,l=gn()(t,["paths",n,(r||"").toLowerCase(),"servers"])||gn()(t,["paths",n,"servers"])||gn()(t,["servers"]),c="",p=null;if(o&&l&&l.length){var f=C()(l).call(l,(function(e){return e.url}));f.indexOf(o)>-1&&(c=o,p=l[f.indexOf(o)])}if(!c&&l&&l.length){c=l[0].url;var h=g()(l,1);p=h[0]}return c.indexOf("{")>-1&&function(e){for(var t,n=[],r=/{([^}]+)}/g;t=r.exec(e);)n.push(t[1]);return n}(c).forEach((function(e){if(p.variables&&p.variables[e]){var t=p.variables[e],n=u[e]||t.default,r=new RegExp("{".concat(e,"}"),"g");c=c.replace(r,n)}})),function(){var e,t,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",o=n&&r?At.parse(At.resolve(r,n)):At.parse(n),a=At.parse(r),i=Fn(o.protocol)||Fn(a.protocol)||"",u=o.host||a.host,l=o.pathname||"";return"/"===(e=i&&u?s()(t="".concat(i,"://")).call(t,u+l):l)[e.length-1]?W()(e).call(e,0,-1):e}(c,a)}(_):function(e){var t,n,r=e.spec,o=e.scheme,a=e.contextUrl,i=void 0===a?"":a,u=At.parse(i),l=Array.isArray(r.schemes)?r.schemes[0]:null,c=o||l||Fn(u.protocol)||"http",p=r.host||u.host||"",f=r.basePath||"";return"/"===(t=c&&p?s()(n="".concat(c,"://")).call(n,p+f):f)[t.length-1]?W()(t).call(t,0,-1):t}(_)),!o)return delete E.cookies,E;E.url+=O,E.method="".concat(A).toUpperCase(),y=y||{};var I=r.paths[O]||{};i&&(E.headers.accept=i);var T=function(e){var t={};e.forEach((function(e){t[e.in]||(t[e.in]={}),t[e.in][e.name]=e}));var n=[];return j()(t).forEach((function(e){j()(t[e]).forEach((function(r){n.push(t[e][r])}))})),n}(s()(t=s()(n=[]).call(n,Rn(k.parameters))).call(t,Rn(I.parameters)));T.forEach((function(e){var t,n,o=b[e.in];if("body"===e.in&&e.schema&&e.schema.properties&&(t=y),void 0===(t=e&&e.name&&y[e.name]))t=e&&e.name&&y[s()(n="".concat(e.in,".")).call(n,e.name)];else if(function(e,t){return P()(t).call(t,(function(t){return t.name===e}))}(e.name,T).length>1){var a;console.warn(s()(a="Parameter '".concat(e.name,"' is ambiguous because the defined spec has more than one parameter with the name: '")).call(a,e.name,"' and the passed-in parameter values did not define an 'in' value."))}if(null!==t){if(void 0!==e.default&&void 0===t&&(t=e.default),void 0===t&&e.required&&!e.allowEmptyValue)throw new Error("Required parameter ".concat(e.name," is not provided"));if(w&&e.schema&&"object"===e.schema.type&&"string"==typeof t)try{t=JSON.parse(t)}catch(e){throw new Error("Could not parse object parameter value string as JSON")}o&&o({req:E,parameter:e,value:t,operation:k,spec:r})}}));var N=me()(me()({},e),{},{operation:k});if((E=w?Tn(N,E):Nn(N,E)).cookies&&j()(E.cookies).length){var R=j()(E.cookies).reduce((function(e,t){var n=E.cookies[t];return e+(e?"&":"")+yn.serialize(t,n)}),"");E.headers.Cookie=R}return E.cookies&&delete E.cookies,fe(E),E}var Fn=function(e){return e?e.replace(/\W/g,""):null};function zn(e,t){return Un.apply(this,arguments)}function Un(){return Un=l()(p().mark((function e(t,n){var r,o,a,i,s,u,l,c,f,h,d,m,v=arguments;return p().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=v.length>2&&void 0!==v[2]?v[2]:{},o=r.returnEntireTree,a=r.baseDoc,i=r.requestInterceptor,s=r.responseInterceptor,u=r.parameterMacro,l=r.modelPropertyMacro,c=r.useCircularStructures,f={pathDiscriminator:n,baseDoc:a,requestInterceptor:i,responseInterceptor:s,parameterMacro:u,modelPropertyMacro:l,useCircularStructures:c},h=(0,pn.K1)({spec:t}),d=h.spec,e.next=6,hn(me()(me()({},f),{},{spec:d,allowMetaPatches:!0,skipNormalization:!0}));case 6:return m=e.sent,!o&&Array.isArray(n)&&n.length&&(m.spec=gn()(m.spec,n)||null),e.abrupt("return",m);case 9:case"end":return e.stop()}}),e)}))),Un.apply(this,arguments)}var qn=n(34852);function Vn(e){var t,n,r,o=e.configs,a=e.getConfigs;return{fn:{fetch:(t=Y,n=o.preFetch,r=o.postFetch,r=r||function(e){return e},n=n||function(e){return e},function(e){return"string"==typeof e&&(e={url:e}),Z.mergeInQueryOrForm(e),e=n(e),r(t(e))}),buildRequest:Bn,execute:Ln,resolve:hn,resolveSubtree:function(e,t,n){var r;if(void 0===n){var o=a();n={modelPropertyMacro:o.modelPropertyMacro,parameterMacro:o.parameterMacro,requestInterceptor:o.requestInterceptor,responseInterceptor:o.responseInterceptor}}for(var i=arguments.length,u=new Array(i>3?i-3:0),l=3;l{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(90242);function o(){return{fn:{shallowEqualKeys:r.be}}}},48347:(e,t,n)=>{"use strict";n.r(t),n.d(t,{getDisplayName:()=>r});var r=function(e){return e.displayName||e.name||"Component"}},73420:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>l});var r=n(59340),o=n.n(r),a=n(90242),i=n(55776),s=n(48347),u=n(60314);const l=function(e){var t,n=e.getComponents,r=e.getStore,l=e.getSystem,c=(t=(0,i.getComponent)(l,r,n),(0,a.HP)(t,(function(){for(var e=arguments.length,t=new Array(e),n=0;n{"use strict";n.r(t),n.d(t,{getComponent:()=>he,render:()=>fe,withMappedContainer:()=>pe});var r=n(23765),o=n.n(r),a=n(95945),i=n.n(a),s=n(5872),u=n.n(s),l=n(26394),c=n.n(l),p=n(69198),f=n.n(p),h=n(51379),d=n.n(h),m=n(10098),v=n.n(m),g=n(86902),y=n.n(g),b=n(67294),w=n(73935),E=n(97779),x=b.createContext(null);var _=function(e){e()},S=function(){return _},k={notify:function(){}};var A=function(){function e(e,t){this.store=e,this.parentSub=t,this.unsubscribe=null,this.listeners=k,this.handleChangeWrapper=this.handleChangeWrapper.bind(this)}var t=e.prototype;return t.addNestedSub=function(e){return this.trySubscribe(),this.listeners.subscribe(e)},t.notifyNestedSubs=function(){this.listeners.notify()},t.handleChangeWrapper=function(){this.onStateChange&&this.onStateChange()},t.isSubscribed=function(){return Boolean(this.unsubscribe)},t.trySubscribe=function(){this.unsubscribe||(this.unsubscribe=this.parentSub?this.parentSub.addNestedSub(this.handleChangeWrapper):this.store.subscribe(this.handleChangeWrapper),this.listeners=function(){var e=S(),t=null,n=null;return{clear:function(){t=null,n=null},notify:function(){e((function(){for(var e=t;e;)e.callback(),e=e.next}))},get:function(){for(var e=[],n=t;n;)e.push(n),n=n.next;return e},subscribe:function(e){var r=!0,o=n={callback:e,next:null,prev:n};return o.prev?o.prev.next=o:t=o,function(){r&&null!==t&&(r=!1,o.next?o.next.prev=o.prev:n=o.prev,o.prev?o.prev.next=o.next:t=o.next)}}}}())},t.tryUnsubscribe=function(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null,this.listeners.clear(),this.listeners=k)},e}(),C="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?b.useLayoutEffect:b.useEffect;const O=function(e){var t=e.store,n=e.context,r=e.children,o=(0,b.useMemo)((function(){var e=new A(t);return e.onStateChange=e.notifyNestedSubs,{store:t,subscription:e}}),[t]),a=(0,b.useMemo)((function(){return t.getState()}),[t]);C((function(){var e=o.subscription;return e.trySubscribe(),a!==t.getState()&&e.notifyNestedSubs(),function(){e.tryUnsubscribe(),e.onStateChange=null}}),[o,a]);var i=n||x;return b.createElement(i.Provider,{value:o},r)};var j=n(87462),I=n(63366),T=n(8679),N=n.n(T),P=n(72973),R=[],M=[null,null];function D(e,t){var n=e[1];return[t.payload,n+1]}function L(e,t,n){C((function(){return e.apply(void 0,t)}),n)}function B(e,t,n,r,o,a,i){e.current=r,t.current=o,n.current=!1,a.current&&(a.current=null,i())}function F(e,t,n,r,o,a,i,s,u,l){if(e){var c=!1,p=null,f=function(){if(!c){var e,n,f=t.getState();try{e=r(f,o.current)}catch(e){n=e,p=e}n||(p=null),e===a.current?i.current||u():(a.current=e,s.current=e,i.current=!0,l({type:"STORE_UPDATED",payload:{error:n}}))}};n.onStateChange=f,n.trySubscribe(),f();return function(){if(c=!0,n.tryUnsubscribe(),n.onStateChange=null,p)throw p}}}var z=function(){return[null,0]};function U(e,t){void 0===t&&(t={});var n=t,r=n.getDisplayName,o=void 0===r?function(e){return"ConnectAdvanced("+e+")"}:r,a=n.methodName,i=void 0===a?"connectAdvanced":a,s=n.renderCountProp,u=void 0===s?void 0:s,l=n.shouldHandleStateChanges,c=void 0===l||l,p=n.storeKey,f=void 0===p?"store":p,h=(n.withRef,n.forwardRef),d=void 0!==h&&h,m=n.context,v=void 0===m?x:m,g=(0,I.Z)(n,["getDisplayName","methodName","renderCountProp","shouldHandleStateChanges","storeKey","withRef","forwardRef","context"]),y=v;return function(t){var n=t.displayName||t.name||"Component",r=o(n),a=(0,j.Z)({},g,{getDisplayName:o,methodName:i,renderCountProp:u,shouldHandleStateChanges:c,storeKey:f,displayName:r,wrappedComponentName:n,WrappedComponent:t}),s=g.pure;var l=s?b.useMemo:function(e){return e()};function p(n){var r=(0,b.useMemo)((function(){var e=n.reactReduxForwardedRef,t=(0,I.Z)(n,["reactReduxForwardedRef"]);return[n.context,e,t]}),[n]),o=r[0],i=r[1],s=r[2],u=(0,b.useMemo)((function(){return o&&o.Consumer&&(0,P.isContextConsumer)(b.createElement(o.Consumer,null))?o:y}),[o,y]),p=(0,b.useContext)(u),f=Boolean(n.store)&&Boolean(n.store.getState)&&Boolean(n.store.dispatch);Boolean(p)&&Boolean(p.store);var h=f?n.store:p.store,d=(0,b.useMemo)((function(){return function(t){return e(t.dispatch,a)}(h)}),[h]),m=(0,b.useMemo)((function(){if(!c)return M;var e=new A(h,f?null:p.subscription),t=e.notifyNestedSubs.bind(e);return[e,t]}),[h,f,p]),v=m[0],g=m[1],w=(0,b.useMemo)((function(){return f?p:(0,j.Z)({},p,{subscription:v})}),[f,p,v]),E=(0,b.useReducer)(D,R,z),x=E[0][0],_=E[1];if(x&&x.error)throw x.error;var S=(0,b.useRef)(),k=(0,b.useRef)(s),C=(0,b.useRef)(),O=(0,b.useRef)(!1),T=l((function(){return C.current&&s===k.current?C.current:d(h.getState(),s)}),[h,x,s]);L(B,[k,S,O,s,T,C,g]),L(F,[c,h,v,d,k,S,O,C,g,_],[h,v,d]);var N=(0,b.useMemo)((function(){return b.createElement(t,(0,j.Z)({},T,{ref:i}))}),[i,t,T]);return(0,b.useMemo)((function(){return c?b.createElement(u.Provider,{value:w},N):N}),[u,N,w])}var h=s?b.memo(p):p;if(h.WrappedComponent=t,h.displayName=p.displayName=r,d){var m=b.forwardRef((function(e,t){return b.createElement(h,(0,j.Z)({},e,{reactReduxForwardedRef:t}))}));return m.displayName=r,m.WrappedComponent=t,N()(m,t)}return N()(h,t)}}function q(e,t){return e===t?0!==e||0!==t||1/e==1/t:e!=e&&t!=t}function V(e,t){if(q(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(var o=0;o=0;r--){var o=t[r](e);if(o)return o}return function(t,r){throw new Error("Invalid value of type "+typeof e+" for "+n+" argument when connecting component "+r.wrappedComponentName+".")}}function te(e,t){return e===t}function ne(e){var t=void 0===e?{}:e,n=t.connectHOC,r=void 0===n?U:n,o=t.mapStateToPropsFactories,a=void 0===o?K:o,i=t.mapDispatchToPropsFactories,s=void 0===i?J:i,u=t.mergePropsFactories,l=void 0===u?Z:u,c=t.selectorFactory,p=void 0===c?X:c;return function(e,t,n,o){void 0===o&&(o={});var i=o,u=i.pure,c=void 0===u||u,f=i.areStatesEqual,h=void 0===f?te:f,d=i.areOwnPropsEqual,m=void 0===d?V:d,v=i.areStatePropsEqual,g=void 0===v?V:v,y=i.areMergedPropsEqual,b=void 0===y?V:y,w=(0,I.Z)(i,["pure","areStatesEqual","areOwnPropsEqual","areStatePropsEqual","areMergedPropsEqual"]),E=ee(e,a,"mapStateToProps"),x=ee(t,s,"mapDispatchToProps"),_=ee(n,l,"mergeProps");return r(p,(0,j.Z)({methodName:"connect",getDisplayName:function(e){return"Connect("+e+")"},shouldHandleStateChanges:Boolean(e),initMapStateToProps:E,initMapDispatchToProps:x,initMergeProps:_,pure:c,areStatesEqual:h,areOwnPropsEqual:m,areStatePropsEqual:g,areMergedPropsEqual:b},w))}}const re=ne();var oe;oe=w.unstable_batchedUpdates,_=oe;var ae=n(57557),ie=n.n(ae),se=n(6557),ue=n.n(se),le=function(e,t,n){return(0,E.qC)(n?function(e,t){return function(n){var r=e().fn,o=function(e){d()(o,e);var r=v()(o);function o(){return c()(this,o),r.apply(this,arguments)}return f()(o,[{key:"render",value:function(){return b.createElement(O,{store:t},b.createElement(n,u()({},this.props,this.context)))}}]),o}(b.Component);return o.displayName="WithRoot(".concat(r.getDisplayName(n),")"),o}}(e,n):ue(),re((function(n,r){var o,a=i()(i()({},r),e()),s=(null===(o=t.prototype)||void 0===o?void 0:o.mapStateToProps)||function(e){return{state:e}};return s(n,a)})),function(e){return function(t){var n=e().fn,r=function(n){d()(o,n);var r=v()(o);function o(){return c()(this,o),r.apply(this,arguments)}return f()(o,[{key:"render",value:function(){return b.createElement(t,u()({},e(),this.props,this.context))}}]),o}(b.Component);return r.displayName="WithSystem(".concat(n.getDisplayName(t),")"),r}}(e))(t)},ce=function(e,t,n,r){for(var o in t){var a=t[o];"function"==typeof a&&a(n[o],r[o],e())}},pe=function(e,t,n){return function(t,r){var o=e().fn,a=n(t,"root"),i=function(t){d()(o,t);var n=v()(o);function o(t,a){var i;return c()(this,o),i=n.call(this,t,a),ce(e,r,t,{}),i}return f()(o,[{key:"UNSAFE_componentWillReceiveProps",value:function(t){ce(e,r,t,this.props)}},{key:"render",value:function(){var e=ie()(this.props,r?y()(r):[]);return b.createElement(a,e)}}]),o}(b.Component);return i.displayName="WithMappedContainer(".concat(o.getDisplayName(a),")"),i}},fe=function(e,t,n,r){return function(o){var a=n(e,t,r)("App","root");w.render(b.createElement(a,null),o)}},he=function(e,t,n){return function(r,a){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if("string"!=typeof r)throw new TypeError("Need a string, to fetch a component. Was given a "+o()(r));var s=n(r);return s?a?"root"===a?le(e,s,t()):le(e,s):s:(i.failSilently||e().log.warn("Could not find component:",r),null)}}},36581:(e,t,n)=>{"use strict";n.d(t,{d3:()=>N,C2:()=>Z});var r=n(86902),o=n.n(r),a=n(78580),i=n.n(a),s=n(63366);function u(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n=4?[t[0],t[1],t[2],t[3],"".concat(t[0],".").concat(t[1]),"".concat(t[0],".").concat(t[2]),"".concat(t[0],".").concat(t[3]),"".concat(t[1],".").concat(t[0]),"".concat(t[1],".").concat(t[2]),"".concat(t[1],".").concat(t[3]),"".concat(t[2],".").concat(t[0]),"".concat(t[2],".").concat(t[1]),"".concat(t[2],".").concat(t[3]),"".concat(t[3],".").concat(t[0]),"".concat(t[3],".").concat(t[1]),"".concat(t[3],".").concat(t[2]),"".concat(t[0],".").concat(t[1],".").concat(t[2]),"".concat(t[0],".").concat(t[1],".").concat(t[3]),"".concat(t[0],".").concat(t[2],".").concat(t[1]),"".concat(t[0],".").concat(t[2],".").concat(t[3]),"".concat(t[0],".").concat(t[3],".").concat(t[1]),"".concat(t[0],".").concat(t[3],".").concat(t[2]),"".concat(t[1],".").concat(t[0],".").concat(t[2]),"".concat(t[1],".").concat(t[0],".").concat(t[3]),"".concat(t[1],".").concat(t[2],".").concat(t[0]),"".concat(t[1],".").concat(t[2],".").concat(t[3]),"".concat(t[1],".").concat(t[3],".").concat(t[0]),"".concat(t[1],".").concat(t[3],".").concat(t[2]),"".concat(t[2],".").concat(t[0],".").concat(t[1]),"".concat(t[2],".").concat(t[0],".").concat(t[3]),"".concat(t[2],".").concat(t[1],".").concat(t[0]),"".concat(t[2],".").concat(t[1],".").concat(t[3]),"".concat(t[2],".").concat(t[3],".").concat(t[0]),"".concat(t[2],".").concat(t[3],".").concat(t[1]),"".concat(t[3],".").concat(t[0],".").concat(t[1]),"".concat(t[3],".").concat(t[0],".").concat(t[2]),"".concat(t[3],".").concat(t[1],".").concat(t[0]),"".concat(t[3],".").concat(t[1],".").concat(t[2]),"".concat(t[3],".").concat(t[2],".").concat(t[0]),"".concat(t[3],".").concat(t[2],".").concat(t[1]),"".concat(t[0],".").concat(t[1],".").concat(t[2],".").concat(t[3]),"".concat(t[0],".").concat(t[1],".").concat(t[3],".").concat(t[2]),"".concat(t[0],".").concat(t[2],".").concat(t[1],".").concat(t[3]),"".concat(t[0],".").concat(t[2],".").concat(t[3],".").concat(t[1]),"".concat(t[0],".").concat(t[3],".").concat(t[1],".").concat(t[2]),"".concat(t[0],".").concat(t[3],".").concat(t[2],".").concat(t[1]),"".concat(t[1],".").concat(t[0],".").concat(t[2],".").concat(t[3]),"".concat(t[1],".").concat(t[0],".").concat(t[3],".").concat(t[2]),"".concat(t[1],".").concat(t[2],".").concat(t[0],".").concat(t[3]),"".concat(t[1],".").concat(t[2],".").concat(t[3],".").concat(t[0]),"".concat(t[1],".").concat(t[3],".").concat(t[0],".").concat(t[2]),"".concat(t[1],".").concat(t[3],".").concat(t[2],".").concat(t[0]),"".concat(t[2],".").concat(t[0],".").concat(t[1],".").concat(t[3]),"".concat(t[2],".").concat(t[0],".").concat(t[3],".").concat(t[1]),"".concat(t[2],".").concat(t[1],".").concat(t[0],".").concat(t[3]),"".concat(t[2],".").concat(t[1],".").concat(t[3],".").concat(t[0]),"".concat(t[2],".").concat(t[3],".").concat(t[0],".").concat(t[1]),"".concat(t[2],".").concat(t[3],".").concat(t[1],".").concat(t[0]),"".concat(t[3],".").concat(t[0],".").concat(t[1],".").concat(t[2]),"".concat(t[3],".").concat(t[0],".").concat(t[2],".").concat(t[1]),"".concat(t[3],".").concat(t[1],".").concat(t[0],".").concat(t[2]),"".concat(t[3],".").concat(t[1],".").concat(t[2],".").concat(t[0]),"".concat(t[3],".").concat(t[2],".").concat(t[0],".").concat(t[1]),"".concat(t[3],".").concat(t[2],".").concat(t[1],".").concat(t[0])]:void 0),d[r]}function v(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0,r=e.filter((function(e){return"token"!==e})),o=m(r);return o.reduce((function(e,t){return p({},e,n[t])}),t)}function g(e){return e.join(" ")}function y(e){var t=e.node,n=e.stylesheet,r=e.style,o=void 0===r?{}:r,a=e.useInlineStyles,i=e.key,s=t.properties,u=t.type,l=t.tagName,c=t.value;if("text"===u)return c;if(l){var d,m=function(e,t){var n=0;return function(r){return n+=1,r.map((function(r,o){return y({node:r,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(o)})}))}}(n,a);if(a){var b=Object.keys(n).reduce((function(e,t){return t.split(".").forEach((function(t){e.includes(t)||e.push(t)})),e}),[]),w=s.className&&s.className.includes("token")?["token"]:[],E=s.className&&w.concat(s.className.filter((function(e){return!b.includes(e)})));d=p({},s,{className:g(E)||void 0,style:v(s.className,Object.assign({},s.style,o),n)})}else d=p({},s,{className:g(s.className)});var x=m(t.children);return f.createElement(l,(0,h.Z)({key:i},d),x)}}var b=/\n/g;function w(e){var t=e.codeString,n=e.codeStyle,r=e.containerStyle,o=void 0===r?{float:"left",paddingRight:"10px"}:r,a=e.numberStyle,i=void 0===a?{}:a,s=e.startingLineNumber;return f.createElement("code",{style:Object.assign({},n,o)},function(e){var t=e.lines,n=e.startingLineNumber,r=e.style;return t.map((function(e,t){var o=t+n;return f.createElement("span",{key:"line-".concat(t),className:"react-syntax-highlighter-line-number",style:"function"==typeof r?r(o):r},"".concat(o,"\n"))}))}({lines:t.replace(/\n$/,"").split("\n"),style:i,startingLineNumber:s}))}function E(e,t){return{type:"element",tagName:"span",properties:{key:"line-number--".concat(e),className:["comment","linenumber","react-syntax-highlighter-line-number"],style:t},children:[{type:"text",value:e}]}}function x(e,t,n){var r;return p({},{display:"inline-block",minWidth:(r=n,"".concat(r.toString().length,".25em")),paddingRight:"1em",textAlign:"right",userSelect:"none"},"function"==typeof e?e(t):e)}function _(e){var t=e.children,n=e.lineNumber,r=e.lineNumberStyle,o=e.largestLineNumber,a=e.showInlineLineNumbers,i=e.lineProps,s=void 0===i?{}:i,u=e.className,l=void 0===u?[]:u,c=e.showLineNumbers,f=e.wrapLongLines,h="function"==typeof s?s(n):s;if(h.className=l,n&&a){var d=x(r,n,o);t.unshift(E(n,d))}return f&c&&(h.style=p({},h.style,{display:"flex"})),{type:"element",tagName:"span",properties:h,children:t}}function S(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=0;r2&&void 0!==arguments[2]?arguments[2]:[];return _({children:e,lineNumber:t,lineNumberStyle:s,largestLineNumber:i,showInlineLineNumbers:o,lineProps:n,className:a,showLineNumbers:r,wrapLongLines:u})}function m(e,t){if(r&&t&&o){var n=x(s,t,i);e.unshift(E(t,n))}return e}function v(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return t||r.length>0?d(e,n,r):m(e,n)}for(var g=function(){var e=c[h],t=e.children[0].value;if(t.match(b)){var n=t.split("\n");n.forEach((function(t,o){var i=r&&p.length+a,s={type:"text",value:"".concat(t,"\n")};if(0===o){var u=v(c.slice(f+1,h).concat(_({children:[s],className:e.properties.className})),i);p.push(u)}else if(o===n.length-1){if(c[h+1]&&c[h+1].children&&c[h+1].children[0]){var l=_({children:[{type:"text",value:"".concat(t)}],className:e.properties.className});c.splice(h+1,0,l)}else{var d=v([s],i,e.properties.className);p.push(d)}}else{var m=v([s],i,e.properties.className);p.push(m)}})),f=h}h++};h=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}(e,["language","children","style","customStyle","codeTagProps","useInlineStyles","showLineNumbers","showInlineLineNumbers","startingLineNumber","lineNumberContainerStyle","lineNumberStyle","wrapLines","wrapLongLines","lineProps","renderer","PreTag","CodeTag","code","astGenerator"]);U=U||O;var V=m?f.createElement(w,{containerStyle:E,codeStyle:l.style||{},numberStyle:_,startingLineNumber:b,codeString:z}):null,W=o.hljs||o['pre[class*="language-"]']||{backgroundColor:"#fff"},H=C(U)?"hljs":"prismjs",$=h?Object.assign({},q,{style:Object.assign({},W,i)}):Object.assign({},q,{className:q.className?"".concat(H," ").concat(q.className):H,style:Object.assign({},i)});if(!U)return f.createElement(D,$,V,f.createElement(B,l,z));(void 0===S&&R||T)&&(S=!0),R=R||A;var J=[{type:"text",value:z}],K=function(e){var t=e.astGenerator,n=e.language,r=e.code,o=e.defaultCodeValue;if(C(t)){var a=function(e,t){return-1!==e.listLanguages().indexOf(t)}(t,n);return"text"===n?{value:o,language:"text"}:a?t.highlight(n,r):t.highlightAuto(r)}try{return n&&"text"!==n?{value:t.highlight(r,n)}:{value:o}}catch(e){return{value:o}}}({astGenerator:U,language:t,code:z,defaultCodeValue:J});null===K.language&&(K.value=J);var G=k(K,S,P,m,g,b,K.value.length+b,_,T);return l.style=p({},l.style,T?{whiteSpace:"pre-wrap"}:{whiteSpace:"pre"}),f.createElement(D,$,f.createElement(B,l,!g&&V,R({rows:G,stylesheet:o,useInlineStyles:h})))});T.registerLanguage=I.registerLanguage;const N=T;var P=n(96344);const R=n.n(P)();var M=n(82026);const D=n.n(M)();var L=n(42157);const B=n.n(L)();var F=n(61519);const z=n.n(F)();var U=n(54587);const q=n.n(U)();var V=n(30786);const W=n.n(V)();var H=n(66336);const $=n.n(H)(),J={hljs:{display:"block",overflowX:"auto",padding:"0.5em",background:"#333",color:"white"},"hljs-name":{fontWeight:"bold"},"hljs-strong":{fontWeight:"bold"},"hljs-code":{fontStyle:"italic",color:"#888"},"hljs-emphasis":{fontStyle:"italic"},"hljs-tag":{color:"#62c8f3"},"hljs-variable":{color:"#ade5fc"},"hljs-template-variable":{color:"#ade5fc"},"hljs-selector-id":{color:"#ade5fc"},"hljs-selector-class":{color:"#ade5fc"},"hljs-string":{color:"#a2fca2"},"hljs-bullet":{color:"#d36363"},"hljs-type":{color:"#ffa"},"hljs-title":{color:"#ffa"},"hljs-section":{color:"#ffa"},"hljs-attribute":{color:"#ffa"},"hljs-quote":{color:"#ffa"},"hljs-built_in":{color:"#ffa"},"hljs-builtin-name":{color:"#ffa"},"hljs-number":{color:"#d36363"},"hljs-symbol":{color:"#d36363"},"hljs-keyword":{color:"#fcc28c"},"hljs-selector-tag":{color:"#fcc28c"},"hljs-literal":{color:"#fcc28c"},"hljs-comment":{color:"#888"},"hljs-deletion":{color:"#333",backgroundColor:"#fc9b9b"},"hljs-regexp":{color:"#c6b4f0"},"hljs-link":{color:"#c6b4f0"},"hljs-meta":{color:"#fc9b9b"},"hljs-addition":{backgroundColor:"#a2fca2",color:"#333"}};N.registerLanguage("json",D),N.registerLanguage("js",R),N.registerLanguage("xml",B),N.registerLanguage("yaml",q),N.registerLanguage("http",W),N.registerLanguage("bash",z),N.registerLanguage("powershell",$),N.registerLanguage("javascript",R);var K={agate:J,arta:{hljs:{display:"block",overflowX:"auto",padding:"0.5em",background:"#222",color:"#aaa"},"hljs-subst":{color:"#aaa"},"hljs-section":{color:"#fff",fontWeight:"bold"},"hljs-comment":{color:"#444"},"hljs-quote":{color:"#444"},"hljs-meta":{color:"#444"},"hljs-string":{color:"#ffcc33"},"hljs-symbol":{color:"#ffcc33"},"hljs-bullet":{color:"#ffcc33"},"hljs-regexp":{color:"#ffcc33"},"hljs-number":{color:"#00cc66"},"hljs-addition":{color:"#00cc66"},"hljs-built_in":{color:"#32aaee"},"hljs-builtin-name":{color:"#32aaee"},"hljs-literal":{color:"#32aaee"},"hljs-type":{color:"#32aaee"},"hljs-template-variable":{color:"#32aaee"},"hljs-attribute":{color:"#32aaee"},"hljs-link":{color:"#32aaee"},"hljs-keyword":{color:"#6644aa"},"hljs-selector-tag":{color:"#6644aa"},"hljs-name":{color:"#6644aa"},"hljs-selector-id":{color:"#6644aa"},"hljs-selector-class":{color:"#6644aa"},"hljs-title":{color:"#bb1166"},"hljs-variable":{color:"#bb1166"},"hljs-deletion":{color:"#bb1166"},"hljs-template-tag":{color:"#bb1166"},"hljs-doctag":{fontWeight:"bold"},"hljs-strong":{fontWeight:"bold"},"hljs-emphasis":{fontStyle:"italic"}},monokai:{hljs:{display:"block",overflowX:"auto",padding:"0.5em",background:"#272822",color:"#ddd"},"hljs-tag":{color:"#f92672"},"hljs-keyword":{color:"#f92672",fontWeight:"bold"},"hljs-selector-tag":{color:"#f92672",fontWeight:"bold"},"hljs-literal":{color:"#f92672",fontWeight:"bold"},"hljs-strong":{color:"#f92672"},"hljs-name":{color:"#f92672"},"hljs-code":{color:"#66d9ef"},"hljs-class .hljs-title":{color:"white"},"hljs-attribute":{color:"#bf79db"},"hljs-symbol":{color:"#bf79db"},"hljs-regexp":{color:"#bf79db"},"hljs-link":{color:"#bf79db"},"hljs-string":{color:"#a6e22e"},"hljs-bullet":{color:"#a6e22e"},"hljs-subst":{color:"#a6e22e"},"hljs-title":{color:"#a6e22e",fontWeight:"bold"},"hljs-section":{color:"#a6e22e",fontWeight:"bold"},"hljs-emphasis":{color:"#a6e22e"},"hljs-type":{color:"#a6e22e",fontWeight:"bold"},"hljs-built_in":{color:"#a6e22e"},"hljs-builtin-name":{color:"#a6e22e"},"hljs-selector-attr":{color:"#a6e22e"},"hljs-selector-pseudo":{color:"#a6e22e"},"hljs-addition":{color:"#a6e22e"},"hljs-variable":{color:"#a6e22e"},"hljs-template-tag":{color:"#a6e22e"},"hljs-template-variable":{color:"#a6e22e"},"hljs-comment":{color:"#75715e"},"hljs-quote":{color:"#75715e"},"hljs-deletion":{color:"#75715e"},"hljs-meta":{color:"#75715e"},"hljs-doctag":{fontWeight:"bold"},"hljs-selector-id":{fontWeight:"bold"}},nord:{hljs:{display:"block",overflowX:"auto",padding:"0.5em",background:"#2E3440",color:"#D8DEE9"},"hljs-subst":{color:"#D8DEE9"},"hljs-selector-tag":{color:"#81A1C1"},"hljs-selector-id":{color:"#8FBCBB",fontWeight:"bold"},"hljs-selector-class":{color:"#8FBCBB"},"hljs-selector-attr":{color:"#8FBCBB"},"hljs-selector-pseudo":{color:"#88C0D0"},"hljs-addition":{backgroundColor:"rgba(163, 190, 140, 0.5)"},"hljs-deletion":{backgroundColor:"rgba(191, 97, 106, 0.5)"},"hljs-built_in":{color:"#8FBCBB"},"hljs-type":{color:"#8FBCBB"},"hljs-class":{color:"#8FBCBB"},"hljs-function":{color:"#88C0D0"},"hljs-function > .hljs-title":{color:"#88C0D0"},"hljs-keyword":{color:"#81A1C1"},"hljs-literal":{color:"#81A1C1"},"hljs-symbol":{color:"#81A1C1"},"hljs-number":{color:"#B48EAD"},"hljs-regexp":{color:"#EBCB8B"},"hljs-string":{color:"#A3BE8C"},"hljs-title":{color:"#8FBCBB"},"hljs-params":{color:"#D8DEE9"},"hljs-bullet":{color:"#81A1C1"},"hljs-code":{color:"#8FBCBB"},"hljs-emphasis":{fontStyle:"italic"},"hljs-formula":{color:"#8FBCBB"},"hljs-strong":{fontWeight:"bold"},"hljs-link:hover":{textDecoration:"underline"},"hljs-quote":{color:"#4C566A"},"hljs-comment":{color:"#4C566A"},"hljs-doctag":{color:"#8FBCBB"},"hljs-meta":{color:"#5E81AC"},"hljs-meta-keyword":{color:"#5E81AC"},"hljs-meta-string":{color:"#A3BE8C"},"hljs-attr":{color:"#8FBCBB"},"hljs-attribute":{color:"#D8DEE9"},"hljs-builtin-name":{color:"#81A1C1"},"hljs-name":{color:"#81A1C1"},"hljs-section":{color:"#88C0D0"},"hljs-tag":{color:"#81A1C1"},"hljs-variable":{color:"#D8DEE9"},"hljs-template-variable":{color:"#D8DEE9"},"hljs-template-tag":{color:"#5E81AC"},"abnf .hljs-attribute":{color:"#88C0D0"},"abnf .hljs-symbol":{color:"#EBCB8B"},"apache .hljs-attribute":{color:"#88C0D0"},"apache .hljs-section":{color:"#81A1C1"},"arduino .hljs-built_in":{color:"#88C0D0"},"aspectj .hljs-meta":{color:"#D08770"},"aspectj > .hljs-title":{color:"#88C0D0"},"bnf .hljs-attribute":{color:"#8FBCBB"},"clojure .hljs-name":{color:"#88C0D0"},"clojure .hljs-symbol":{color:"#EBCB8B"},"coq .hljs-built_in":{color:"#88C0D0"},"cpp .hljs-meta-string":{color:"#8FBCBB"},"css .hljs-built_in":{color:"#88C0D0"},"css .hljs-keyword":{color:"#D08770"},"diff .hljs-meta":{color:"#8FBCBB"},"ebnf .hljs-attribute":{color:"#8FBCBB"},"glsl .hljs-built_in":{color:"#88C0D0"},"groovy .hljs-meta:not(:first-child)":{color:"#D08770"},"haxe .hljs-meta":{color:"#D08770"},"java .hljs-meta":{color:"#D08770"},"ldif .hljs-attribute":{color:"#8FBCBB"},"lisp .hljs-name":{color:"#88C0D0"},"lua .hljs-built_in":{color:"#88C0D0"},"moonscript .hljs-built_in":{color:"#88C0D0"},"nginx .hljs-attribute":{color:"#88C0D0"},"nginx .hljs-section":{color:"#5E81AC"},"pf .hljs-built_in":{color:"#88C0D0"},"processing .hljs-built_in":{color:"#88C0D0"},"scss .hljs-keyword":{color:"#81A1C1"},"stylus .hljs-keyword":{color:"#81A1C1"},"swift .hljs-meta":{color:"#D08770"},"vim .hljs-built_in":{color:"#88C0D0",fontStyle:"italic"},"yaml .hljs-meta":{color:"#D08770"}},obsidian:{hljs:{display:"block",overflowX:"auto",padding:"0.5em",background:"#282b2e",color:"#e0e2e4"},"hljs-keyword":{color:"#93c763",fontWeight:"bold"},"hljs-selector-tag":{color:"#93c763",fontWeight:"bold"},"hljs-literal":{color:"#93c763",fontWeight:"bold"},"hljs-selector-id":{color:"#93c763"},"hljs-number":{color:"#ffcd22"},"hljs-attribute":{color:"#668bb0"},"hljs-code":{color:"white"},"hljs-class .hljs-title":{color:"white"},"hljs-section":{color:"white",fontWeight:"bold"},"hljs-regexp":{color:"#d39745"},"hljs-link":{color:"#d39745"},"hljs-meta":{color:"#557182"},"hljs-tag":{color:"#8cbbad"},"hljs-name":{color:"#8cbbad",fontWeight:"bold"},"hljs-bullet":{color:"#8cbbad"},"hljs-subst":{color:"#8cbbad"},"hljs-emphasis":{color:"#8cbbad"},"hljs-type":{color:"#8cbbad",fontWeight:"bold"},"hljs-built_in":{color:"#8cbbad"},"hljs-selector-attr":{color:"#8cbbad"},"hljs-selector-pseudo":{color:"#8cbbad"},"hljs-addition":{color:"#8cbbad"},"hljs-variable":{color:"#8cbbad"},"hljs-template-tag":{color:"#8cbbad"},"hljs-template-variable":{color:"#8cbbad"},"hljs-string":{color:"#ec7600"},"hljs-symbol":{color:"#ec7600"},"hljs-comment":{color:"#818e96"},"hljs-quote":{color:"#818e96"},"hljs-deletion":{color:"#818e96"},"hljs-selector-class":{color:"#A082BD"},"hljs-doctag":{fontWeight:"bold"},"hljs-title":{fontWeight:"bold"},"hljs-strong":{fontWeight:"bold"}},"tomorrow-night":{"hljs-comment":{color:"#969896"},"hljs-quote":{color:"#969896"},"hljs-variable":{color:"#cc6666"},"hljs-template-variable":{color:"#cc6666"},"hljs-tag":{color:"#cc6666"},"hljs-name":{color:"#cc6666"},"hljs-selector-id":{color:"#cc6666"},"hljs-selector-class":{color:"#cc6666"},"hljs-regexp":{color:"#cc6666"},"hljs-deletion":{color:"#cc6666"},"hljs-number":{color:"#de935f"},"hljs-built_in":{color:"#de935f"},"hljs-builtin-name":{color:"#de935f"},"hljs-literal":{color:"#de935f"},"hljs-type":{color:"#de935f"},"hljs-params":{color:"#de935f"},"hljs-meta":{color:"#de935f"},"hljs-link":{color:"#de935f"},"hljs-attribute":{color:"#f0c674"},"hljs-string":{color:"#b5bd68"},"hljs-symbol":{color:"#b5bd68"},"hljs-bullet":{color:"#b5bd68"},"hljs-addition":{color:"#b5bd68"},"hljs-title":{color:"#81a2be"},"hljs-section":{color:"#81a2be"},"hljs-keyword":{color:"#b294bb"},"hljs-selector-tag":{color:"#b294bb"},hljs:{display:"block",overflowX:"auto",background:"#1d1f21",color:"#c5c8c6",padding:"0.5em"},"hljs-emphasis":{fontStyle:"italic"},"hljs-strong":{fontWeight:"bold"}}},G=o()(K),Z=function(e){return i()(G).call(G,e)?K[e]:(console.warn("Request style '".concat(e,"' is not available, returning default instead")),J)}},90242:(e,t,n)=>{"use strict";n.d(t,{mz:()=>be,oG:()=>we,AF:()=>Ee,LQ:()=>xe,Kn:()=>_e,Wl:()=>Se,kJ:()=>ke,HP:()=>Ae,Ay:()=>Ce,Q2:()=>Oe,_5:()=>je,iQ:()=>Ie,gp:()=>Te,DR:()=>Ne,Zl:()=>Pe,Ik:()=>Me,xi:()=>Ue,UG:()=>qe,r3:()=>Ve,wh:()=>We,GZ:()=>He,be:()=>$e,Nm:()=>Je,hW:()=>Ke,QG:()=>Ge,oJ:()=>Ze,J6:()=>Ye,nX:()=>Qe,po:()=>Xe,XV:()=>et,Pz:()=>tt,D$:()=>nt,V9:()=>rt,cz:()=>ot,Uj:()=>at,Xb:()=>it,O2:()=>ut});var r=n(59036),o=n.n(r),a=(n(18777),n(23765)),i=n.n(a),s=n(86418),u=n.n(s),l=n(41511),c=n.n(l),p=n(2991),f=n.n(p),h=n(72119),d=n.n(h),m=n(77766),v=n.n(m),g=n(78914),y=n.n(g),b=n(20116),w=n.n(b),E=n(86902),x=n.n(E),_=(n(54103),n(32366)),S=n.n(_),k=n(51942),A=n.n(k),C=n(47302),O=n.n(C),j=n(3649),I=n.n(j),T=n(77149),N=n.n(T),P=(n(78580),n(59340)),R=n.n(P),M=n(81643),D=n.n(M),L=n(94473),B=n.n(L),F=n(29828),z=n.n(F),U=n(25843),q=n.n(U),V=n(43393),W=n.n(V),H=n(17967),$=n(68929),J=n.n($),K=n(11700),G=n.n(K),Z=n(88306),Y=n.n(Z),Q=n(13311),X=n.n(Q),ee=n(59704),te=n.n(ee),ne=n(77813),re=n.n(ne),oe=n(23560),ae=n.n(oe),ie=n(57050),se=n(27504),ue=n(8269),le=n.n(ue),ce=n(19069),pe=n(92282),fe=n.n(pe),he=n(89072),de=n.n(he),me=n(1272),ve=n(48764).Buffer,ge="default",ye=function(e){return W().Iterable.isIterable(e)};function be(e){return _e(e)?ye(e)?e.toJS():e:{}}function we(e){var t,n;if(ye(e))return e;if(e instanceof se.Z.File)return e;if(!_e(e))return e;if(c()(e))return f()(n=W().Seq(e)).call(n,we).toList();if(ae()(d()(e))){var r,o=function(e){if(!ae()(d()(e)))return e;var t,n={},r="_**[]",o={},a=u()(d()(e).call(e));try{for(a.s();!(t=a.n()).done;){var i=t.value;if(n[i[0]]||o[i[0]]&&o[i[0]].containsMultiple){var s,l,c,p;if(!o[i[0]])o[i[0]]={containsMultiple:!0,length:1},n[v()(c=v()(p="".concat(i[0])).call(p,r)).call(c,o[i[0]].length)]=n[i[0]],delete n[i[0]];o[i[0]].length+=1,n[v()(s=v()(l="".concat(i[0])).call(l,r)).call(s,o[i[0]].length)]=i[1]}else n[i[0]]=i[1]}}catch(e){a.e(e)}finally{a.f()}return n}(e);return f()(r=W().OrderedMap(o)).call(r,we)}return f()(t=W().OrderedMap(e)).call(t,we)}function Ee(e){return c()(e)?e:[e]}function xe(e){return"function"==typeof e}function _e(e){return!!e&&"object"===i()(e)}function Se(e){return"function"==typeof e}function ke(e){return c()(e)}var Ae=Y();function Ce(e,t){var n;return S()(n=x()(e)).call(n,(function(n,r){return n[r]=t(e[r],r),n}),{})}function Oe(e,t){var n;return S()(n=x()(e)).call(n,(function(n,r){var o=t(e[r],r);return o&&"object"===i()(o)&&A()(n,o),n}),{})}function je(e){return function(t){t.dispatch,t.getState;return function(t){return function(n){return"function"==typeof n?n(e()):t(n)}}}}function Ie(e){var t,n=e.keySeq();return n.contains(ge)?ge:O()(t=w()(n).call(n,(function(e){return"2"===(e+"")[0]}))).call(t).first()}function Te(e,t){if(!W().Iterable.isIterable(e))return W().List();var n=e.getIn(c()(t)?t:[t]);return W().List.isList(n)?n:W().List()}function Ne(e){var t,n=[/filename\*=[^']+'\w*'"([^"]+)";?/i,/filename\*=[^']+'\w*'([^;]+);?/i,/filename="([^;]*);?"/i,/filename=([^;]*);?/i];if(N()(n).call(n,(function(n){return null!==(t=n.exec(e))})),null!==t&&t.length>1)try{return decodeURIComponent(t[1])}catch(e){console.error(e)}return null}function Pe(e){return t=e.replace(/\.[^./]*$/,""),G()(J()(t));var t}function Re(e,t,n,r,a){if(!t)return[];var s=[],u=t.get("nullable"),l=t.get("required"),p=t.get("maximum"),h=t.get("minimum"),d=t.get("type"),m=t.get("format"),g=t.get("maxLength"),b=t.get("minLength"),E=t.get("uniqueItems"),x=t.get("maxItems"),_=t.get("minItems"),S=t.get("pattern"),k=n||!0===l,A=null!=e;if(u&&null===e||!d||!(k||A&&"array"===d||!(!k&&!A)))return[];var C="string"===d&&e,O="array"===d&&c()(e)&&e.length,j="array"===d&&W().List.isList(e)&&e.count(),I=[C,O,j,"array"===d&&"string"==typeof e&&e,"file"===d&&e instanceof se.Z.File,"boolean"===d&&(e||!1===e),"number"===d&&(e||0===e),"integer"===d&&(e||0===e),"object"===d&&"object"===i()(e)&&null!==e,"object"===d&&"string"==typeof e&&e],T=N()(I).call(I,(function(e){return!!e}));if(k&&!T&&!r)return s.push("Required field is not provided"),s;if("object"===d&&(null===a||"application/json"===a)){var P,R=e;if("string"==typeof e)try{R=JSON.parse(e)}catch(e){return s.push("Parameter string value must be valid JSON"),s}if(t&&t.has("required")&&Se(l.isList)&&l.isList()&&y()(l).call(l,(function(e){void 0===R[e]&&s.push({propKey:e,error:"Required property not found"})})),t&&t.has("properties"))y()(P=t.get("properties")).call(P,(function(e,t){var n=Re(R[t],e,!1,r,a);s.push.apply(s,o()(f()(n).call(n,(function(e){return{propKey:t,error:e}}))))}))}if(S){var M=function(e,t){if(!new RegExp(t).test(e))return"Value must follow pattern "+t}(e,S);M&&s.push(M)}if(_&&"array"===d){var D=function(e,t){var n;if(!e&&t>=1||e&&e.lengtht)return v()(n="Array must not contain more then ".concat(t," item")).call(n,1===t?"":"s")}(e,x);L&&s.push({needRemove:!0,error:L})}if(E&&"array"===d){var B=function(e,t){if(e&&("true"===t||!0===t)){var n=(0,V.fromJS)(e),r=n.toSet();if(e.length>r.size){var o=(0,V.Set)();if(y()(n).call(n,(function(e,t){w()(n).call(n,(function(t){return Se(t.equals)?t.equals(e):t===e})).size>1&&(o=o.add(t))})),0!==o.size)return f()(o).call(o,(function(e){return{index:e,error:"No duplicates allowed."}})).toArray()}}}(e,E);B&&s.push.apply(s,o()(B))}if(g||0===g){var F=function(e,t){var n;if(e.length>t)return v()(n="Value must be no longer than ".concat(t," character")).call(n,1!==t?"s":"")}(e,g);F&&s.push(F)}if(b){var z=function(e,t){var n;if(e.lengtht)return"Value must be less than ".concat(t)}(e,p);U&&s.push(U)}if(h||0===h){var q=function(e,t){if(e2&&void 0!==arguments[2]?arguments[2]:{},r=n.isOAS3,o=void 0!==r&&r,a=n.bypassRequiredCheck,i=void 0!==a&&a,s=e.get("required"),u=(0,ce.Z)(e,{isOAS3:o}),l=u.schema,c=u.parameterContentMediaType;return Re(t,l,s,i,c)},De=function(e,t,n){if(e&&(!e.xml||!e.xml.name)){if(e.xml=e.xml||{},!e.$$ref)return e.type||e.items||e.properties||e.additionalProperties?'\n\x3c!-- XML example cannot be generated; root element name is undefined --\x3e':null;var r=e.$$ref.match(/\S*\/(\S+)$/);e.xml.name=r[1]}return(0,ie.memoizedCreateXMLExample)(e,t,n)},Le=[{when:/json/,shouldStringifyTypes:["string"]}],Be=["object"],Fe=function(e,t,n,r){var a=(0,ie.memoizedSampleFromSchema)(e,t,r),s=i()(a),u=S()(Le).call(Le,(function(e,t){var r;return t.when.test(n)?v()(r=[]).call(r,o()(e),o()(t.shouldStringifyTypes)):e}),Be);return te()(u,(function(e){return e===s}))?R()(a,null,2):a},ze=function(e,t,n,r){var o,a=Fe(e,t,n,r);try{"\n"===(o=me.ZP.dump(me.ZP.load(a),{lineWidth:-1},{schema:me.A8}))[o.length-1]&&(o=I()(o).call(o,0,o.length-1))}catch(e){return console.error(e),"error: could not generate yaml example"}return o.replace(/\t/g," ")},Ue=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:void 0;return e&&Se(e.toJS)&&(e=e.toJS()),r&&Se(r.toJS)&&(r=r.toJS()),/xml/.test(t)?De(e,n,r):/(yaml|yml)/.test(t)?ze(e,n,t,r):Fe(e,n,t,r)},qe=function(){var e={},t=se.Z.location.search;if(!t)return{};if(""!=t){var n=t.substr(1).split("&");for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(r=n[r].split("="),e[decodeURIComponent(r[0])]=r[1]&&decodeURIComponent(r[1])||"")}return e},Ve=function(e){return(e instanceof ve?e:ve.from(e.toString(),"utf-8")).toString("base64")},We={operationsSorter:{alpha:function(e,t){return e.get("path").localeCompare(t.get("path"))},method:function(e,t){return e.get("method").localeCompare(t.get("method"))}},tagsSorter:{alpha:function(e,t){return e.localeCompare(t)}}},He=function(e){var t=[];for(var n in e){var r=e[n];void 0!==r&&""!==r&&t.push([n,"=",encodeURIComponent(r).replace(/%20/g,"+")].join(""))}return t.join("&")},$e=function(e,t,n){return!!X()(n,(function(n){return re()(e[n],t[n])}))};function Je(e){return"string"!=typeof e||""===e?"":(0,H.N)(e)}function Ke(e){return!(!e||D()(e).call(e,"localhost")>=0||D()(e).call(e,"127.0.0.1")>=0||"none"===e)}function Ge(e){if(!W().OrderedMap.isOrderedMap(e))return null;if(!e.size)return null;var t=B()(e).call(e,(function(e,t){return z()(t).call(t,"2")&&x()(e.get("content")||{}).length>0})),n=e.get("default")||W().OrderedMap(),r=(n.get("content")||W().OrderedMap()).keySeq().toJS().length?n:null;return t||r}var Ze=function(e){return"string"==typeof e||e instanceof String?q()(e).call(e).replace(/\s/g,"%20"):""},Ye=function(e){return le()(Ze(e).replace(/%20/g,"_"))},Qe=function(e){return w()(e).call(e,(function(e,t){return/^x-/.test(t)}))},Xe=function(e){return w()(e).call(e,(function(e,t){return/^pattern|maxLength|minLength|maximum|minimum/.test(t)}))};function et(e,t){var n,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){return!0};if("object"!==i()(e)||c()(e)||null===e||!t)return e;var o=A()({},e);return y()(n=x()(o)).call(n,(function(e){e===t&&r(o[e],e)?delete o[e]:o[e]=et(o[e],t,r)})),o}function tt(e){if("string"==typeof e)return e;if(e&&e.toJS&&(e=e.toJS()),"object"===i()(e)&&null!==e)try{return R()(e,null,2)}catch(t){return String(e)}return null==e?"":e.toString()}function nt(e){return"number"==typeof e?e.toString():e}function rt(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.returnAll,r=void 0!==n&&n,o=t.allowHashes,a=void 0===o||o;if(!W().Map.isMap(e))throw new Error("paramToIdentifier: received a non-Im.Map parameter as input");var i,s,u,l=e.get("name"),c=e.get("in"),p=[];e&&e.hashCode&&c&&l&&a&&p.push(v()(i=v()(s="".concat(c,".")).call(s,l,".hash-")).call(i,e.hashCode()));c&&l&&p.push(v()(u="".concat(c,".")).call(u,l));return p.push(l),r?p:p[0]||""}function ot(e,t){var n,r=rt(e,{returnAll:!0});return w()(n=f()(r).call(r,(function(e){return t[e]}))).call(n,(function(e){return void 0!==e}))[0]}function at(){return st(fe()(32).toString("base64"))}function it(e){return st(de()("sha256").update(e).digest("base64"))}function st(e){return e.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}var ut=function(e){return!e||!(!ye(e)||!e.isEmpty())}},2518:(e,t,n)=>{"use strict";function r(e){return function(e){try{return!!JSON.parse(e)}catch(e){return null}}(e)?"json":null}n.d(t,{O:()=>r})},27504:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});const r=function(){var e={location:{},history:{},open:function(){},close:function(){},File:function(){}};if("undefined"==typeof window)return e;try{e=window;for(var t=0,n=["File","Blob","FormData"];t{"use strict";n.d(t,{Z:()=>c});var r=n(20116),o=n.n(r),a=n(78580),i=n.n(a),s=n(43393),u=n.n(s),l=u().Set.of("type","format","items","default","maximum","exclusiveMaximum","minimum","exclusiveMinimum","maxLength","minLength","pattern","maxItems","minItems","uniqueItems","enum","multipleOf");function c(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.isOAS3;if(!u().Map.isMap(e))return{schema:u().Map(),parameterContentMediaType:null};if(!n)return"body"===e.get("in")?{schema:e.get("schema",u().Map()),parameterContentMediaType:null}:{schema:o()(e).call(e,(function(e,t){return i()(l).call(l,t)})),parameterContentMediaType:null};if(e.get("content")){var r=e.get("content",u().Map({})).keySeq(),a=r.first();return{schema:e.getIn(["content",a,"schema"],u().Map()),parameterContentMediaType:a}}return{schema:e.get("schema",u().Map()),parameterContentMediaType:null}}},60314:(e,t,n)=>{"use strict";n.d(t,{Z:()=>D});var r=n(26394),o=n.n(r),a=n(69198),i=n.n(a),s=n(31474),u=n.n(s),l=n(66380),c=n.n(l),p=n(51379),f=n.n(p),h=n(10098),d=n.n(h),m=n(74803),v=n.n(m),g=n(41511),y=n.n(g),b=n(10062),w=n.n(b),E=n(66419),x=n.n(E),_=n(69301),S=n.n(_),k=n(94473),A=n.n(k),C=n(62462),O=n.n(C),j=n(39392),I=n.n(j),T=n(88306),N=n.n(T),P=function(e){return function(t){return y()(e)&&y()(t)&&e.length===t.length&&w()(e).call(e,(function(e,n){return e===t[n]}))}},R=function(){for(var e=arguments.length,t=new Array(e),n=0;n1&&void 0!==arguments[1]?arguments[1]:R,n=N().Cache;N().Cache=M;var r=N()(e,t);return N().Cache=n,r}},79742:(e,t)=>{"use strict";t.byteLength=function(e){var t=u(e),n=t[0],r=t[1];return 3*(n+r)/4-r},t.toByteArray=function(e){var t,n,a=u(e),i=a[0],s=a[1],l=new o(function(e,t,n){return 3*(t+n)/4-n}(0,i,s)),c=0,p=s>0?i-4:i;for(n=0;n>16&255,l[c++]=t>>8&255,l[c++]=255&t;2===s&&(t=r[e.charCodeAt(n)]<<2|r[e.charCodeAt(n+1)]>>4,l[c++]=255&t);1===s&&(t=r[e.charCodeAt(n)]<<10|r[e.charCodeAt(n+1)]<<4|r[e.charCodeAt(n+2)]>>2,l[c++]=t>>8&255,l[c++]=255&t);return l},t.fromByteArray=function(e){for(var t,r=e.length,o=r%3,a=[],i=16383,s=0,u=r-o;su?u:s+i));1===o?(t=e[r-1],a.push(n[t>>2]+n[t<<4&63]+"==")):2===o&&(t=(e[r-2]<<8)+e[r-1],a.push(n[t>>10]+n[t>>4&63]+n[t<<2&63]+"="));return a.join("")};for(var n=[],r=[],o="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",i=0,s=a.length;i0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,r){for(var o,a,i=[],s=t;s>18&63]+n[a>>12&63]+n[a>>6&63]+n[63&a]);return i.join("")}r["-".charCodeAt(0)]=62,r["_".charCodeAt(0)]=63},48764:(e,t,n)=>{"use strict";const r=n(79742),o=n(80645),a="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):null;t.Buffer=u,t.SlowBuffer=function(e){+e!=e&&(e=0);return u.alloc(+e)},t.INSPECT_MAX_BYTES=50;const i=2147483647;function s(e){if(e>i)throw new RangeError('The value "'+e+'" is invalid for option "size"');const t=new Uint8Array(e);return Object.setPrototypeOf(t,u.prototype),t}function u(e,t,n){if("number"==typeof e){if("string"==typeof t)throw new TypeError('The "string" argument must be of type string. Received type number');return p(e)}return l(e,t,n)}function l(e,t,n){if("string"==typeof e)return function(e,t){"string"==typeof t&&""!==t||(t="utf8");if(!u.isEncoding(t))throw new TypeError("Unknown encoding: "+t);const n=0|m(e,t);let r=s(n);const o=r.write(e,t);o!==n&&(r=r.slice(0,o));return r}(e,t);if(ArrayBuffer.isView(e))return function(e){if(G(e,Uint8Array)){const t=new Uint8Array(e);return h(t.buffer,t.byteOffset,t.byteLength)}return f(e)}(e);if(null==e)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e);if(G(e,ArrayBuffer)||e&&G(e.buffer,ArrayBuffer))return h(e,t,n);if("undefined"!=typeof SharedArrayBuffer&&(G(e,SharedArrayBuffer)||e&&G(e.buffer,SharedArrayBuffer)))return h(e,t,n);if("number"==typeof e)throw new TypeError('The "value" argument must not be of type number. Received type number');const r=e.valueOf&&e.valueOf();if(null!=r&&r!==e)return u.from(r,t,n);const o=function(e){if(u.isBuffer(e)){const t=0|d(e.length),n=s(t);return 0===n.length||e.copy(n,0,0,t),n}if(void 0!==e.length)return"number"!=typeof e.length||Z(e.length)?s(0):f(e);if("Buffer"===e.type&&Array.isArray(e.data))return f(e.data)}(e);if(o)return o;if("undefined"!=typeof Symbol&&null!=Symbol.toPrimitive&&"function"==typeof e[Symbol.toPrimitive])return u.from(e[Symbol.toPrimitive]("string"),t,n);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e)}function c(e){if("number"!=typeof e)throw new TypeError('"size" argument must be of type number');if(e<0)throw new RangeError('The value "'+e+'" is invalid for option "size"')}function p(e){return c(e),s(e<0?0:0|d(e))}function f(e){const t=e.length<0?0:0|d(e.length),n=s(t);for(let r=0;r=i)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+i.toString(16)+" bytes");return 0|e}function m(e,t){if(u.isBuffer(e))return e.length;if(ArrayBuffer.isView(e)||G(e,ArrayBuffer))return e.byteLength;if("string"!=typeof e)throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof e);const n=e.length,r=arguments.length>2&&!0===arguments[2];if(!r&&0===n)return 0;let o=!1;for(;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":return $(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return J(e).length;default:if(o)return r?-1:$(e).length;t=(""+t).toLowerCase(),o=!0}}function v(e,t,n){let r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return I(this,t,n);case"utf8":case"utf-8":return A(this,t,n);case"ascii":return O(this,t,n);case"latin1":case"binary":return j(this,t,n);case"base64":return k(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return T(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function g(e,t,n){const r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),Z(n=+n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=u.from(t,r)),u.isBuffer(t))return 0===t.length?-1:b(e,t,n,r,o);if("number"==typeof t)return t&=255,"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):b(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function b(e,t,n,r,o){let a,i=1,s=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;i=2,s/=2,u/=2,n/=2}function l(e,t){return 1===i?e[t]:e.readUInt16BE(t*i)}if(o){let r=-1;for(a=n;as&&(n=s-u),a=n;a>=0;a--){let n=!0;for(let r=0;ro&&(r=o):r=o;const a=t.length;let i;for(r>a/2&&(r=a/2),i=0;i>8,o=n%256,a.push(o),a.push(r);return a}(t,e.length-n),e,n,r)}function k(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function A(e,t,n){n=Math.min(e.length,n);const r=[];let o=t;for(;o239?4:t>223?3:t>191?2:1;if(o+i<=n){let n,r,s,u;switch(i){case 1:t<128&&(a=t);break;case 2:n=e[o+1],128==(192&n)&&(u=(31&t)<<6|63&n,u>127&&(a=u));break;case 3:n=e[o+1],r=e[o+2],128==(192&n)&&128==(192&r)&&(u=(15&t)<<12|(63&n)<<6|63&r,u>2047&&(u<55296||u>57343)&&(a=u));break;case 4:n=e[o+1],r=e[o+2],s=e[o+3],128==(192&n)&&128==(192&r)&&128==(192&s)&&(u=(15&t)<<18|(63&n)<<12|(63&r)<<6|63&s,u>65535&&u<1114112&&(a=u))}}null===a?(a=65533,i=1):a>65535&&(a-=65536,r.push(a>>>10&1023|55296),a=56320|1023&a),r.push(a),o+=i}return function(e){const t=e.length;if(t<=C)return String.fromCharCode.apply(String,e);let n="",r=0;for(;rr.length?(u.isBuffer(t)||(t=u.from(t)),t.copy(r,o)):Uint8Array.prototype.set.call(r,t,o);else{if(!u.isBuffer(t))throw new TypeError('"list" argument must be an Array of Buffers');t.copy(r,o)}o+=t.length}return r},u.byteLength=m,u.prototype._isBuffer=!0,u.prototype.swap16=function(){const e=this.length;if(e%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(let t=0;tn&&(e+=" ... "),""},a&&(u.prototype[a]=u.prototype.inspect),u.prototype.compare=function(e,t,n,r,o){if(G(e,Uint8Array)&&(e=u.from(e,e.offset,e.byteLength)),!u.isBuffer(e))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof e);if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;let a=(o>>>=0)-(r>>>=0),i=(n>>>=0)-(t>>>=0);const s=Math.min(a,i),l=this.slice(r,o),c=e.slice(t,n);for(let e=0;e>>=0,isFinite(n)?(n>>>=0,void 0===r&&(r="utf8")):(r=n,n=void 0)}const o=this.length-t;if((void 0===n||n>o)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");let a=!1;for(;;)switch(r){case"hex":return w(this,e,t,n);case"utf8":case"utf-8":return E(this,e,t,n);case"ascii":case"latin1":case"binary":return x(this,e,t,n);case"base64":return _(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return S(this,e,t,n);default:if(a)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),a=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};const C=4096;function O(e,t,n){let r="";n=Math.min(e.length,n);for(let o=t;or)&&(n=r);let o="";for(let r=t;rn)throw new RangeError("Trying to access beyond buffer length")}function P(e,t,n,r,o,a){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function R(e,t,n,r,o){q(t,r,o,e,n,7);let a=Number(t&BigInt(4294967295));e[n++]=a,a>>=8,e[n++]=a,a>>=8,e[n++]=a,a>>=8,e[n++]=a;let i=Number(t>>BigInt(32)&BigInt(4294967295));return e[n++]=i,i>>=8,e[n++]=i,i>>=8,e[n++]=i,i>>=8,e[n++]=i,n}function M(e,t,n,r,o){q(t,r,o,e,n,7);let a=Number(t&BigInt(4294967295));e[n+7]=a,a>>=8,e[n+6]=a,a>>=8,e[n+5]=a,a>>=8,e[n+4]=a;let i=Number(t>>BigInt(32)&BigInt(4294967295));return e[n+3]=i,i>>=8,e[n+2]=i,i>>=8,e[n+1]=i,i>>=8,e[n]=i,n+8}function D(e,t,n,r,o,a){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function L(e,t,n,r,a){return t=+t,n>>>=0,a||D(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function B(e,t,n,r,a){return t=+t,n>>>=0,a||D(e,0,n,8),o.write(e,t,n,r,52,8),n+8}u.prototype.slice=function(e,t){const n=this.length;(e=~~e)<0?(e+=n)<0&&(e=0):e>n&&(e=n),(t=void 0===t?n:~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),t>>=0,t>>>=0,n||N(e,t,this.length);let r=this[e],o=1,a=0;for(;++a>>=0,t>>>=0,n||N(e,t,this.length);let r=this[e+--t],o=1;for(;t>0&&(o*=256);)r+=this[e+--t]*o;return r},u.prototype.readUint8=u.prototype.readUInt8=function(e,t){return e>>>=0,t||N(e,1,this.length),this[e]},u.prototype.readUint16LE=u.prototype.readUInt16LE=function(e,t){return e>>>=0,t||N(e,2,this.length),this[e]|this[e+1]<<8},u.prototype.readUint16BE=u.prototype.readUInt16BE=function(e,t){return e>>>=0,t||N(e,2,this.length),this[e]<<8|this[e+1]},u.prototype.readUint32LE=u.prototype.readUInt32LE=function(e,t){return e>>>=0,t||N(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},u.prototype.readUint32BE=u.prototype.readUInt32BE=function(e,t){return e>>>=0,t||N(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},u.prototype.readBigUInt64LE=Q((function(e){V(e>>>=0,"offset");const t=this[e],n=this[e+7];void 0!==t&&void 0!==n||W(e,this.length-8);const r=t+256*this[++e]+65536*this[++e]+this[++e]*2**24,o=this[++e]+256*this[++e]+65536*this[++e]+n*2**24;return BigInt(r)+(BigInt(o)<>>=0,"offset");const t=this[e],n=this[e+7];void 0!==t&&void 0!==n||W(e,this.length-8);const r=t*2**24+65536*this[++e]+256*this[++e]+this[++e],o=this[++e]*2**24+65536*this[++e]+256*this[++e]+n;return(BigInt(r)<>>=0,t>>>=0,n||N(e,t,this.length);let r=this[e],o=1,a=0;for(;++a=o&&(r-=Math.pow(2,8*t)),r},u.prototype.readIntBE=function(e,t,n){e>>>=0,t>>>=0,n||N(e,t,this.length);let r=t,o=1,a=this[e+--r];for(;r>0&&(o*=256);)a+=this[e+--r]*o;return o*=128,a>=o&&(a-=Math.pow(2,8*t)),a},u.prototype.readInt8=function(e,t){return e>>>=0,t||N(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){e>>>=0,t||N(e,2,this.length);const n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){e>>>=0,t||N(e,2,this.length);const n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return e>>>=0,t||N(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return e>>>=0,t||N(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readBigInt64LE=Q((function(e){V(e>>>=0,"offset");const t=this[e],n=this[e+7];void 0!==t&&void 0!==n||W(e,this.length-8);const r=this[e+4]+256*this[e+5]+65536*this[e+6]+(n<<24);return(BigInt(r)<>>=0,"offset");const t=this[e],n=this[e+7];void 0!==t&&void 0!==n||W(e,this.length-8);const r=(t<<24)+65536*this[++e]+256*this[++e]+this[++e];return(BigInt(r)<>>=0,t||N(e,4,this.length),o.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return e>>>=0,t||N(e,4,this.length),o.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return e>>>=0,t||N(e,8,this.length),o.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return e>>>=0,t||N(e,8,this.length),o.read(this,e,!1,52,8)},u.prototype.writeUintLE=u.prototype.writeUIntLE=function(e,t,n,r){if(e=+e,t>>>=0,n>>>=0,!r){P(this,e,t,n,Math.pow(2,8*n)-1,0)}let o=1,a=0;for(this[t]=255&e;++a>>=0,n>>>=0,!r){P(this,e,t,n,Math.pow(2,8*n)-1,0)}let o=n-1,a=1;for(this[t+o]=255&e;--o>=0&&(a*=256);)this[t+o]=e/a&255;return t+n},u.prototype.writeUint8=u.prototype.writeUInt8=function(e,t,n){return e=+e,t>>>=0,n||P(this,e,t,1,255,0),this[t]=255&e,t+1},u.prototype.writeUint16LE=u.prototype.writeUInt16LE=function(e,t,n){return e=+e,t>>>=0,n||P(this,e,t,2,65535,0),this[t]=255&e,this[t+1]=e>>>8,t+2},u.prototype.writeUint16BE=u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t>>>=0,n||P(this,e,t,2,65535,0),this[t]=e>>>8,this[t+1]=255&e,t+2},u.prototype.writeUint32LE=u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t>>>=0,n||P(this,e,t,4,4294967295,0),this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e,t+4},u.prototype.writeUint32BE=u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t>>>=0,n||P(this,e,t,4,4294967295,0),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},u.prototype.writeBigUInt64LE=Q((function(e,t=0){return R(this,e,t,BigInt(0),BigInt("0xffffffffffffffff"))})),u.prototype.writeBigUInt64BE=Q((function(e,t=0){return M(this,e,t,BigInt(0),BigInt("0xffffffffffffffff"))})),u.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t>>>=0,!r){const r=Math.pow(2,8*n-1);P(this,e,t,n,r-1,-r)}let o=0,a=1,i=0;for(this[t]=255&e;++o>0)-i&255;return t+n},u.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t>>>=0,!r){const r=Math.pow(2,8*n-1);P(this,e,t,n,r-1,-r)}let o=n-1,a=1,i=0;for(this[t+o]=255&e;--o>=0&&(a*=256);)e<0&&0===i&&0!==this[t+o+1]&&(i=1),this[t+o]=(e/a>>0)-i&255;return t+n},u.prototype.writeInt8=function(e,t,n){return e=+e,t>>>=0,n||P(this,e,t,1,127,-128),e<0&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t>>>=0,n||P(this,e,t,2,32767,-32768),this[t]=255&e,this[t+1]=e>>>8,t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t>>>=0,n||P(this,e,t,2,32767,-32768),this[t]=e>>>8,this[t+1]=255&e,t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t>>>=0,n||P(this,e,t,4,2147483647,-2147483648),this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24,t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t>>>=0,n||P(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},u.prototype.writeBigInt64LE=Q((function(e,t=0){return R(this,e,t,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))})),u.prototype.writeBigInt64BE=Q((function(e,t=0){return M(this,e,t,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))})),u.prototype.writeFloatLE=function(e,t,n){return L(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return L(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return B(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return B(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,r){if(!u.isBuffer(e))throw new TypeError("argument should be a Buffer");if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(o=t;o=r+4;n-=3)t=`_${e.slice(n-3,n)}${t}`;return`${e.slice(0,n)}${t}`}function q(e,t,n,r,o,a){if(e>n||e3?0===t||t===BigInt(0)?`>= 0${r} and < 2${r} ** ${8*(a+1)}${r}`:`>= -(2${r} ** ${8*(a+1)-1}${r}) and < 2 ** ${8*(a+1)-1}${r}`:`>= ${t}${r} and <= ${n}${r}`,new F.ERR_OUT_OF_RANGE("value",o,e)}!function(e,t,n){V(t,"offset"),void 0!==e[t]&&void 0!==e[t+n]||W(t,e.length-(n+1))}(r,o,a)}function V(e,t){if("number"!=typeof e)throw new F.ERR_INVALID_ARG_TYPE(t,"number",e)}function W(e,t,n){if(Math.floor(e)!==e)throw V(e,n),new F.ERR_OUT_OF_RANGE(n||"offset","an integer",e);if(t<0)throw new F.ERR_BUFFER_OUT_OF_BOUNDS;throw new F.ERR_OUT_OF_RANGE(n||"offset",`>= ${n?1:0} and <= ${t}`,e)}z("ERR_BUFFER_OUT_OF_BOUNDS",(function(e){return e?`${e} is outside of buffer bounds`:"Attempt to access memory outside buffer bounds"}),RangeError),z("ERR_INVALID_ARG_TYPE",(function(e,t){return`The "${e}" argument must be of type number. Received type ${typeof t}`}),TypeError),z("ERR_OUT_OF_RANGE",(function(e,t,n){let r=`The value of "${e}" is out of range.`,o=n;return Number.isInteger(n)&&Math.abs(n)>2**32?o=U(String(n)):"bigint"==typeof n&&(o=String(n),(n>BigInt(2)**BigInt(32)||n<-(BigInt(2)**BigInt(32)))&&(o=U(o)),o+="n"),r+=` It must be ${t}. Received ${o}`,r}),RangeError);const H=/[^+/0-9A-Za-z-_]/g;function $(e,t){let n;t=t||1/0;const r=e.length;let o=null;const a=[];for(let i=0;i55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&a.push(239,191,189);continue}if(i+1===r){(t-=3)>-1&&a.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&a.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&a.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;a.push(n)}else if(n<2048){if((t-=2)<0)break;a.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;a.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;a.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return a}function J(e){return r.toByteArray(function(e){if((e=(e=e.split("=")[0]).trim().replace(H,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function K(e,t,n,r){let o;for(o=0;o=t.length||o>=e.length);++o)t[o+n]=e[o];return o}function G(e,t){return e instanceof t||null!=e&&null!=e.constructor&&null!=e.constructor.name&&e.constructor.name===t.name}function Z(e){return e!=e}const Y=function(){const e="0123456789abcdef",t=new Array(256);for(let n=0;n<16;++n){const r=16*n;for(let o=0;o<16;++o)t[r+o]=e[n]+e[o]}return t}();function Q(e){return"undefined"==typeof BigInt?X:e}function X(){throw new Error("BigInt not supported")}},21924:(e,t,n)=>{"use strict";var r=n(40210),o=n(55559),a=o(r("String.prototype.indexOf"));e.exports=function(e,t){var n=r(e,!!t);return"function"==typeof n&&a(e,".prototype.")>-1?o(n):n}},55559:(e,t,n)=>{"use strict";var r=n(58612),o=n(40210),a=o("%Function.prototype.apply%"),i=o("%Function.prototype.call%"),s=o("%Reflect.apply%",!0)||r.call(i,a),u=o("%Object.getOwnPropertyDescriptor%",!0),l=o("%Object.defineProperty%",!0),c=o("%Math.max%");if(l)try{l({},"a",{value:1})}catch(e){l=null}e.exports=function(e){var t=s(r,i,arguments);if(u&&l){var n=u(t,"length");n.configurable&&l(t,"length",{value:1+c(0,e.length-(arguments.length-1))})}return t};var p=function(){return s(r,a,arguments)};l?l(e.exports,"apply",{value:p}):e.exports.apply=p},94184:(e,t)=>{var n;!function(){"use strict";var r={}.hasOwnProperty;function o(){for(var e=[],t=0;t{"use strict";var r=n(11742),o={"text/plain":"Text","text/html":"Url",default:"Text"};e.exports=function(e,t){var n,a,i,s,u,l,c=!1;t||(t={}),n=t.debug||!1;try{if(i=r(),s=document.createRange(),u=document.getSelection(),(l=document.createElement("span")).textContent=e,l.style.all="unset",l.style.position="fixed",l.style.top=0,l.style.clip="rect(0, 0, 0, 0)",l.style.whiteSpace="pre",l.style.webkitUserSelect="text",l.style.MozUserSelect="text",l.style.msUserSelect="text",l.style.userSelect="text",l.addEventListener("copy",(function(r){if(r.stopPropagation(),t.format)if(r.preventDefault(),void 0===r.clipboardData){n&&console.warn("unable to use e.clipboardData"),n&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var a=o[t.format]||o.default;window.clipboardData.setData(a,e)}else r.clipboardData.clearData(),r.clipboardData.setData(t.format,e);t.onCopy&&(r.preventDefault(),t.onCopy(r.clipboardData))})),document.body.appendChild(l),s.selectNodeContents(l),u.addRange(s),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");c=!0}catch(r){n&&console.error("unable to copy using execCommand: ",r),n&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(t.format||"text",e),t.onCopy&&t.onCopy(window.clipboardData),c=!0}catch(r){n&&console.error("unable to copy using clipboardData: ",r),n&&console.error("falling back to prompt"),a=function(e){var t=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C";return e.replace(/#{\s*key\s*}/g,t)}("message"in t?t.message:"Copy to clipboard: #{key}, Enter"),window.prompt(a,e)}}finally{u&&("function"==typeof u.removeRange?u.removeRange(s):u.removeAllRanges()),l&&document.body.removeChild(l),i()}return c}},95299:(e,t,n)=>{var r=n(24848);e.exports=r},83450:(e,t,n)=>{var r=n(83363);e.exports=r},66820:(e,t,n)=>{var r=n(56243);e.exports=r},5023:(e,t,n)=>{var r=n(72369);e.exports=r},90093:(e,t,n)=>{var r=n(28196);e.exports=r},3688:(e,t,n)=>{var r=n(11955);e.exports=r},83838:(e,t,n)=>{var r=n(46279);e.exports=r},15684:(e,t,n)=>{var r=n(19373);e.exports=r},84234:(e,t,n)=>{var r=n(82073);e.exports=r},92182:(e,t,n)=>{var r=n(15868);e.exports=r},65362:(e,t,n)=>{var r=n(63383);e.exports=r},32271:(e,t,n)=>{var r=n(14471);e.exports=r},91254:(e,t,n)=>{var r=n(57396);e.exports=r},43536:(e,t,n)=>{var r=n(41910);e.exports=r},37331:(e,t,n)=>{var r=n(79427);e.exports=r},68522:(e,t,n)=>{var r=n(62857);e.exports=r},73151:(e,t,n)=>{var r=n(9534);e.exports=r},99565:(e,t,n)=>{var r=n(96507);e.exports=r},45012:(e,t,n)=>{var r=n(23059);e.exports=r},78690:(e,t,n)=>{var r=n(16670);e.exports=r},25626:(e,t,n)=>{var r=n(27460);e.exports=r},84670:(e,t,n)=>{var r=n(61895);e.exports=r},41285:(e,t,n)=>{var r=n(18254);e.exports=r},80281:(e,t,n)=>{var r=n(92547);e.exports=r},40031:(e,t,n)=>{var r=n(46509);e.exports=r},54493:(e,t,n)=>{n(77971),n(53242);var r=n(54058);e.exports=r.Array.from},24034:(e,t,n)=>{n(92737);var r=n(54058);e.exports=r.Array.isArray},15367:(e,t,n)=>{n(85906);var r=n(35703);e.exports=r("Array").concat},12710:(e,t,n)=>{n(66274),n(55967);var r=n(35703);e.exports=r("Array").entries},51459:(e,t,n)=>{n(48851);var r=n(35703);e.exports=r("Array").every},6172:(e,t,n)=>{n(80290);var r=n(35703);e.exports=r("Array").fill},62383:(e,t,n)=>{n(21501);var r=n(35703);e.exports=r("Array").filter},60009:(e,t,n)=>{n(44929);var r=n(35703);e.exports=r("Array").findIndex},17671:(e,t,n)=>{n(80833);var r=n(35703);e.exports=r("Array").find},99324:(e,t,n)=>{n(2437);var r=n(35703);e.exports=r("Array").forEach},80991:(e,t,n)=>{n(97690);var r=n(35703);e.exports=r("Array").includes},8700:(e,t,n)=>{n(99076);var r=n(35703);e.exports=r("Array").indexOf},95909:(e,t,n)=>{n(66274),n(55967);var r=n(35703);e.exports=r("Array").keys},6442:(e,t,n)=>{n(75915);var r=n(35703);e.exports=r("Array").lastIndexOf},23866:(e,t,n)=>{n(68787);var r=n(35703);e.exports=r("Array").map},52999:(e,t,n)=>{n(81876);var r=n(35703);e.exports=r("Array").reduce},24900:(e,t,n)=>{n(60186);var r=n(35703);e.exports=r("Array").slice},3824:(e,t,n)=>{n(36026);var r=n(35703);e.exports=r("Array").some},2948:(e,t,n)=>{n(4115);var r=n(35703);e.exports=r("Array").sort},78209:(e,t,n)=>{n(98611);var r=n(35703);e.exports=r("Array").splice},14423:(e,t,n)=>{n(66274),n(55967);var r=n(35703);e.exports=r("Array").values},81103:(e,t,n)=>{n(95160);var r=n(54058);e.exports=r.Date.now},27700:(e,t,n)=>{n(73381);var r=n(35703);e.exports=r("Function").bind},13830:(e,t,n)=>{n(66274),n(77971);var r=n(22902);e.exports=r},91031:(e,t,n)=>{n(52595),e.exports=n(21899)},16246:(e,t,n)=>{var r=n(7046),o=n(27700),a=Function.prototype;e.exports=function(e){var t=e.bind;return e===a||r(a,e)&&t===a.bind?o:t}},56043:(e,t,n)=>{var r=n(7046),o=n(15367),a=Array.prototype;e.exports=function(e){var t=e.concat;return e===a||r(a,e)&&t===a.concat?o:t}},13160:(e,t,n)=>{var r=n(7046),o=n(51459),a=Array.prototype;e.exports=function(e){var t=e.every;return e===a||r(a,e)&&t===a.every?o:t}},80446:(e,t,n)=>{var r=n(7046),o=n(6172),a=Array.prototype;e.exports=function(e){var t=e.fill;return e===a||r(a,e)&&t===a.fill?o:t}},2480:(e,t,n)=>{var r=n(7046),o=n(62383),a=Array.prototype;e.exports=function(e){var t=e.filter;return e===a||r(a,e)&&t===a.filter?o:t}},7147:(e,t,n)=>{var r=n(7046),o=n(60009),a=Array.prototype;e.exports=function(e){var t=e.findIndex;return e===a||r(a,e)&&t===a.findIndex?o:t}},32236:(e,t,n)=>{var r=n(7046),o=n(17671),a=Array.prototype;e.exports=function(e){var t=e.find;return e===a||r(a,e)&&t===a.find?o:t}},58557:(e,t,n)=>{var r=n(7046),o=n(80991),a=n(21631),i=Array.prototype,s=String.prototype;e.exports=function(e){var t=e.includes;return e===i||r(i,e)&&t===i.includes?o:"string"==typeof e||e===s||r(s,e)&&t===s.includes?a:t}},34570:(e,t,n)=>{var r=n(7046),o=n(8700),a=Array.prototype;e.exports=function(e){var t=e.indexOf;return e===a||r(a,e)&&t===a.indexOf?o:t}},57564:(e,t,n)=>{var r=n(7046),o=n(6442),a=Array.prototype;e.exports=function(e){var t=e.lastIndexOf;return e===a||r(a,e)&&t===a.lastIndexOf?o:t}},88287:(e,t,n)=>{var r=n(7046),o=n(23866),a=Array.prototype;e.exports=function(e){var t=e.map;return e===a||r(a,e)&&t===a.map?o:t}},68025:(e,t,n)=>{var r=n(7046),o=n(52999),a=Array.prototype;e.exports=function(e){var t=e.reduce;return e===a||r(a,e)&&t===a.reduce?o:t}},59257:(e,t,n)=>{var r=n(7046),o=n(80454),a=String.prototype;e.exports=function(e){var t=e.repeat;return"string"==typeof e||e===a||r(a,e)&&t===a.repeat?o:t}},69601:(e,t,n)=>{var r=n(7046),o=n(24900),a=Array.prototype;e.exports=function(e){var t=e.slice;return e===a||r(a,e)&&t===a.slice?o:t}},28299:(e,t,n)=>{var r=n(7046),o=n(3824),a=Array.prototype;e.exports=function(e){var t=e.some;return e===a||r(a,e)&&t===a.some?o:t}},69355:(e,t,n)=>{var r=n(7046),o=n(2948),a=Array.prototype;e.exports=function(e){var t=e.sort;return e===a||r(a,e)&&t===a.sort?o:t}},18339:(e,t,n)=>{var r=n(7046),o=n(78209),a=Array.prototype;e.exports=function(e){var t=e.splice;return e===a||r(a,e)&&t===a.splice?o:t}},71611:(e,t,n)=>{var r=n(7046),o=n(3269),a=String.prototype;e.exports=function(e){var t=e.startsWith;return"string"==typeof e||e===a||r(a,e)&&t===a.startsWith?o:t}},62774:(e,t,n)=>{var r=n(7046),o=n(13348),a=String.prototype;e.exports=function(e){var t=e.trim;return"string"==typeof e||e===a||r(a,e)&&t===a.trim?o:t}},84426:(e,t,n)=>{n(32619);var r=n(54058),o=n(79730);r.JSON||(r.JSON={stringify:JSON.stringify}),e.exports=function(e,t,n){return o(r.JSON.stringify,null,arguments)}},91018:(e,t,n)=>{n(66274),n(37501),n(55967),n(77971);var r=n(54058);e.exports=r.Map},45999:(e,t,n)=>{n(49221);var r=n(54058);e.exports=r.Object.assign},35254:(e,t,n)=>{n(53882);var r=n(54058).Object;e.exports=function(e,t){return r.create(e,t)}},7702:(e,t,n)=>{n(74979);var r=n(54058).Object,o=e.exports=function(e,t){return r.defineProperties(e,t)};r.defineProperties.sham&&(o.sham=!0)},48171:(e,t,n)=>{n(86450);var r=n(54058).Object,o=e.exports=function(e,t,n){return r.defineProperty(e,t,n)};r.defineProperty.sham&&(o.sham=!0)},73081:(e,t,n)=>{n(94366);var r=n(54058);e.exports=r.Object.entries},286:(e,t,n)=>{n(46924);var r=n(54058).Object,o=e.exports=function(e,t){return r.getOwnPropertyDescriptor(e,t)};r.getOwnPropertyDescriptor.sham&&(o.sham=!0)},92766:(e,t,n)=>{n(88482);var r=n(54058);e.exports=r.Object.getOwnPropertyDescriptors},30498:(e,t,n)=>{n(35824);var r=n(54058);e.exports=r.Object.getOwnPropertySymbols},13966:(e,t,n)=>{n(17405);var r=n(54058);e.exports=r.Object.getPrototypeOf},48494:(e,t,n)=>{n(21724);var r=n(54058);e.exports=r.Object.keys},3065:(e,t,n)=>{n(90108);var r=n(54058);e.exports=r.Object.setPrototypeOf},98430:(e,t,n)=>{n(26614);var r=n(54058);e.exports=r.Object.values},52956:(e,t,n)=>{n(47627),n(66274),n(55967),n(98881),n(4560),n(91302),n(44349),n(77971);var r=n(54058);e.exports=r.Promise},14983:(e,t,n)=>{n(7453);var r=n(54058);e.exports=r.Reflect.construct},37095:(e,t,n)=>{n(42355);var r=n(54058);e.exports=r.Reflect.get},21631:(e,t,n)=>{n(11035);var r=n(35703);e.exports=r("String").includes},80454:(e,t,n)=>{n(60986);var r=n(35703);e.exports=r("String").repeat},3269:(e,t,n)=>{n(94761);var r=n(35703);e.exports=r("String").startsWith},13348:(e,t,n)=>{n(57398);var r=n(35703);e.exports=r("String").trim},57473:(e,t,n)=>{n(85906),n(55967),n(35824),n(8555),n(52615),n(21732),n(35903),n(1825),n(28394),n(45915),n(61766),n(62737),n(89911),n(74315),n(63131),n(64714),n(70659),n(69120),n(79413),n(1502);var r=n(54058);e.exports=r.Symbol},24227:(e,t,n)=>{n(66274),n(55967),n(77971),n(1825);var r=n(11477);e.exports=r.f("iterator")},32304:(e,t,n)=>{n(66274),n(55967),n(54334);var r=n(54058);e.exports=r.WeakMap},27385:(e,t,n)=>{var r=n(95299);e.exports=r},81522:(e,t,n)=>{var r=n(83450);e.exports=r},32209:(e,t,n)=>{var r=n(66820);e.exports=r},30888:(e,t,n)=>{n(9668);var r=n(5023);e.exports=r},14122:(e,t,n)=>{var r=n(90093);e.exports=r},44442:(e,t,n)=>{var r=n(3688);e.exports=r},57152:(e,t,n)=>{var r=n(83838);e.exports=r},69447:(e,t,n)=>{var r=n(15684);e.exports=r},81493:(e,t,n)=>{var r=n(84234);e.exports=r},86672:(e,t,n)=>{var r=n(92182);n(52453),n(32523),n(66591),n(55121),n(14751),n(52407),n(48580),n(27281),n(36507),n(93647),n(47641),n(66306),n(27693),n(8),n(48514),n(8212),n(89642),n(78485),n(42256),n(68826),e.exports=r},60269:(e,t,n)=>{var r=n(65362);e.exports=r},76094:(e,t,n)=>{var r=n(32271);e.exports=r},70573:(e,t,n)=>{var r=n(91254);e.exports=r},73685:(e,t,n)=>{var r=n(43536);e.exports=r},27533:(e,t,n)=>{var r=n(37331);e.exports=r},39057:(e,t,n)=>{var r=n(68522);e.exports=r},84710:(e,t,n)=>{var r=n(73151);e.exports=r},74303:(e,t,n)=>{var r=n(99565);e.exports=r},93799:(e,t,n)=>{var r=n(45012);e.exports=r},55122:(e,t,n)=>{var r=n(78690);e.exports=r},29531:(e,t,n)=>{var r=n(25626);n(89731),n(55708),n(30014),n(88731),e.exports=r},10856:(e,t,n)=>{var r=n(84670);e.exports=r},31524:(e,t,n)=>{var r=n(41285);e.exports=r},86600:(e,t,n)=>{var r=n(80281);n(28783),n(43975),n(65799),n(45414),n(46774),n(80620),n(36172),e.exports=r},9759:(e,t,n)=>{var r=n(40031);e.exports=r},24883:(e,t,n)=>{var r=n(21899),o=n(57475),a=n(69826),i=r.TypeError;e.exports=function(e){if(o(e))return e;throw i(a(e)+" is not a function")}},174:(e,t,n)=>{var r=n(21899),o=n(24284),a=n(69826),i=r.TypeError;e.exports=function(e){if(o(e))return e;throw i(a(e)+" is not a constructor")}},11851:(e,t,n)=>{var r=n(21899),o=n(57475),a=r.String,i=r.TypeError;e.exports=function(e){if("object"==typeof e||o(e))return e;throw i("Can't set "+a(e)+" as a prototype")}},18479:e=>{e.exports=function(){}},5743:(e,t,n)=>{var r=n(21899),o=n(7046),a=r.TypeError;e.exports=function(e,t){if(o(t,e))return e;throw a("Incorrect invocation")}},96059:(e,t,n)=>{var r=n(21899),o=n(10941),a=r.String,i=r.TypeError;e.exports=function(e){if(o(e))return e;throw i(a(e)+" is not an object")}},97135:(e,t,n)=>{var r=n(95981);e.exports=r((function(){if("function"==typeof ArrayBuffer){var e=new ArrayBuffer(8);Object.isExtensible(e)&&Object.defineProperty(e,"a",{value:8})}}))},91860:(e,t,n)=>{"use strict";var r=n(89678),o=n(59413),a=n(10623);e.exports=function(e){for(var t=r(this),n=a(t),i=arguments.length,s=o(i>1?arguments[1]:void 0,n),u=i>2?arguments[2]:void 0,l=void 0===u?n:o(u,n);l>s;)t[s++]=e;return t}},56837:(e,t,n)=>{"use strict";var r=n(3610).forEach,o=n(34194)("forEach");e.exports=o?[].forEach:function(e){return r(this,e,arguments.length>1?arguments[1]:void 0)}},11354:(e,t,n)=>{"use strict";var r=n(21899),o=n(86843),a=n(78834),i=n(89678),s=n(75196),u=n(6782),l=n(24284),c=n(10623),p=n(55449),f=n(53476),h=n(22902),d=r.Array;e.exports=function(e){var t=i(e),n=l(this),r=arguments.length,m=r>1?arguments[1]:void 0,v=void 0!==m;v&&(m=o(m,r>2?arguments[2]:void 0));var g,y,b,w,E,x,_=h(t),S=0;if(!_||this==d&&u(_))for(g=c(t),y=n?new this(g):d(g);g>S;S++)x=v?m(t[S],S):t[S],p(y,S,x);else for(E=(w=f(t,_)).next,y=n?new this:[];!(b=a(E,w)).done;S++)x=v?s(w,m,[b.value,S],!0):b.value,p(y,S,x);return y.length=S,y}},31692:(e,t,n)=>{var r=n(74529),o=n(59413),a=n(10623),i=function(e){return function(t,n,i){var s,u=r(t),l=a(u),c=o(i,l);if(e&&n!=n){for(;l>c;)if((s=u[c++])!=s)return!0}else for(;l>c;c++)if((e||c in u)&&u[c]===n)return e||c||0;return!e&&-1}};e.exports={includes:i(!0),indexOf:i(!1)}},3610:(e,t,n)=>{var r=n(86843),o=n(95329),a=n(37026),i=n(89678),s=n(10623),u=n(64692),l=o([].push),c=function(e){var t=1==e,n=2==e,o=3==e,c=4==e,p=6==e,f=7==e,h=5==e||p;return function(d,m,v,g){for(var y,b,w=i(d),E=a(w),x=r(m,v),_=s(E),S=0,k=g||u,A=t?k(d,_):n||f?k(d,0):void 0;_>S;S++)if((h||S in E)&&(b=x(y=E[S],S,w),e))if(t)A[S]=b;else if(b)switch(e){case 3:return!0;case 5:return y;case 6:return S;case 2:l(A,y)}else switch(e){case 4:return!1;case 7:l(A,y)}return p?-1:o||c?c:A}};e.exports={forEach:c(0),map:c(1),filter:c(2),some:c(3),every:c(4),find:c(5),findIndex:c(6),filterReject:c(7)}},67145:(e,t,n)=>{"use strict";var r=n(79730),o=n(74529),a=n(62435),i=n(10623),s=n(34194),u=Math.min,l=[].lastIndexOf,c=!!l&&1/[1].lastIndexOf(1,-0)<0,p=s("lastIndexOf"),f=c||!p;e.exports=f?function(e){if(c)return r(l,this,arguments)||0;var t=o(this),n=i(t),s=n-1;for(arguments.length>1&&(s=u(s,a(arguments[1]))),s<0&&(s=n+s);s>=0;s--)if(s in t&&t[s]===e)return s||0;return-1}:l},50568:(e,t,n)=>{var r=n(95981),o=n(99813),a=n(53385),i=o("species");e.exports=function(e){return a>=51||!r((function(){var t=[];return(t.constructor={})[i]=function(){return{foo:1}},1!==t[e](Boolean).foo}))}},34194:(e,t,n)=>{"use strict";var r=n(95981);e.exports=function(e,t){var n=[][e];return!!n&&r((function(){n.call(null,t||function(){throw 1},1)}))}},46499:(e,t,n)=>{var r=n(21899),o=n(24883),a=n(89678),i=n(37026),s=n(10623),u=r.TypeError,l=function(e){return function(t,n,r,l){o(n);var c=a(t),p=i(c),f=s(c),h=e?f-1:0,d=e?-1:1;if(r<2)for(;;){if(h in p){l=p[h],h+=d;break}if(h+=d,e?h<0:f<=h)throw u("Reduce of empty array with no initial value")}for(;e?h>=0:f>h;h+=d)h in p&&(l=n(l,p[h],h,c));return l}};e.exports={left:l(!1),right:l(!0)}},15790:(e,t,n)=>{var r=n(21899),o=n(59413),a=n(10623),i=n(55449),s=r.Array,u=Math.max;e.exports=function(e,t,n){for(var r=a(e),l=o(t,r),c=o(void 0===n?r:n,r),p=s(u(c-l,0)),f=0;l{var r=n(95329);e.exports=r([].slice)},61388:(e,t,n)=>{var r=n(15790),o=Math.floor,a=function(e,t){var n=e.length,u=o(n/2);return n<8?i(e,t):s(e,a(r(e,0,u),t),a(r(e,u),t),t)},i=function(e,t){for(var n,r,o=e.length,a=1;a0;)e[r]=e[--r];r!==a++&&(e[r]=n)}return e},s=function(e,t,n,r){for(var o=t.length,a=n.length,i=0,s=0;i{var r=n(21899),o=n(1052),a=n(24284),i=n(10941),s=n(99813)("species"),u=r.Array;e.exports=function(e){var t;return o(e)&&(t=e.constructor,(a(t)&&(t===u||o(t.prototype))||i(t)&&null===(t=t[s]))&&(t=void 0)),void 0===t?u:t}},64692:(e,t,n)=>{var r=n(5693);e.exports=function(e,t){return new(r(e))(0===t?0:t)}},75196:(e,t,n)=>{var r=n(96059),o=n(7609);e.exports=function(e,t,n,a){try{return a?t(r(n)[0],n[1]):t(n)}catch(t){o(e,"throw",t)}}},21385:(e,t,n)=>{var r=n(99813)("iterator"),o=!1;try{var a=0,i={next:function(){return{done:!!a++}},return:function(){o=!0}};i[r]=function(){return this},Array.from(i,(function(){throw 2}))}catch(e){}e.exports=function(e,t){if(!t&&!o)return!1;var n=!1;try{var a={};a[r]=function(){return{next:function(){return{done:n=!0}}}},e(a)}catch(e){}return n}},82532:(e,t,n)=>{var r=n(95329),o=r({}.toString),a=r("".slice);e.exports=function(e){return a(o(e),8,-1)}},9697:(e,t,n)=>{var r=n(21899),o=n(22885),a=n(57475),i=n(82532),s=n(99813)("toStringTag"),u=r.Object,l="Arguments"==i(function(){return arguments}());e.exports=o?i:function(e){var t,n,r;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=u(e),s))?n:l?i(t):"Object"==(r=i(t))&&a(t.callee)?"Arguments":r}},38694:(e,t,n)=>{var r=n(95329)("".replace),o=String(Error("zxcasd").stack),a=/\n\s*at [^:]*:[^\n]*/,i=a.test(o);e.exports=function(e,t){if(i&&"string"==typeof e)for(;t--;)e=r(e,a,"");return e}},28984:(e,t,n)=>{"use strict";var r=n(78834),o=n(24883),a=n(96059);e.exports=function(){for(var e,t=a(this),n=o(t.delete),i=!0,s=0,u=arguments.length;s{"use strict";var r=n(86843),o=n(78834),a=n(24883),i=n(174),s=n(93091),u=[].push;e.exports=function(e){var t,n,l,c,p=arguments.length,f=p>1?arguments[1]:void 0;return i(this),(t=void 0!==f)&&a(f),null==e?new this:(n=[],t?(l=0,c=r(f,p>2?arguments[2]:void 0),s(e,(function(e){o(u,n,c(e,l++))}))):s(e,u,{that:n}),new this(n))}},45226:(e,t,n)=>{"use strict";var r=n(93765);e.exports=function(){return new this(r(arguments))}},85616:(e,t,n)=>{"use strict";var r=n(65988).f,o=n(29290),a=n(87524),i=n(86843),s=n(5743),u=n(93091),l=n(47771),c=n(94431),p=n(55746),f=n(21647).fastKey,h=n(45402),d=h.set,m=h.getterFor;e.exports={getConstructor:function(e,t,n,l){var c=e((function(e,r){s(e,h),d(e,{type:t,index:o(null),first:void 0,last:void 0,size:0}),p||(e.size=0),null!=r&&u(r,e[l],{that:e,AS_ENTRIES:n})})),h=c.prototype,v=m(t),g=function(e,t,n){var r,o,a=v(e),i=y(e,t);return i?i.value=n:(a.last=i={index:o=f(t,!0),key:t,value:n,previous:r=a.last,next:void 0,removed:!1},a.first||(a.first=i),r&&(r.next=i),p?a.size++:e.size++,"F"!==o&&(a.index[o]=i)),e},y=function(e,t){var n,r=v(e),o=f(t);if("F"!==o)return r.index[o];for(n=r.first;n;n=n.next)if(n.key==t)return n};return a(h,{clear:function(){for(var e=v(this),t=e.index,n=e.first;n;)n.removed=!0,n.previous&&(n.previous=n.previous.next=void 0),delete t[n.index],n=n.next;e.first=e.last=void 0,p?e.size=0:this.size=0},delete:function(e){var t=this,n=v(t),r=y(t,e);if(r){var o=r.next,a=r.previous;delete n.index[r.index],r.removed=!0,a&&(a.next=o),o&&(o.previous=a),n.first==r&&(n.first=o),n.last==r&&(n.last=a),p?n.size--:t.size--}return!!r},forEach:function(e){for(var t,n=v(this),r=i(e,arguments.length>1?arguments[1]:void 0);t=t?t.next:n.first;)for(r(t.value,t.key,this);t&&t.removed;)t=t.previous},has:function(e){return!!y(this,e)}}),a(h,n?{get:function(e){var t=y(this,e);return t&&t.value},set:function(e,t){return g(this,0===e?0:e,t)}}:{add:function(e){return g(this,e=0===e?0:e,e)}}),p&&r(h,"size",{get:function(){return v(this).size}}),c},setStrong:function(e,t,n){var r=t+" Iterator",o=m(t),a=m(r);l(e,t,(function(e,t){d(this,{type:r,target:e,state:o(e),kind:t,last:void 0})}),(function(){for(var e=a(this),t=e.kind,n=e.last;n&&n.removed;)n=n.previous;return e.target&&(e.last=n=n?n.next:e.state.first)?"keys"==t?{value:n.key,done:!1}:"values"==t?{value:n.value,done:!1}:{value:[n.key,n.value],done:!1}:(e.target=void 0,{value:void 0,done:!0})}),n?"entries":"values",!n,!0),c(t)}}},8850:(e,t,n)=>{"use strict";var r=n(95329),o=n(87524),a=n(21647).getWeakData,i=n(96059),s=n(10941),u=n(5743),l=n(93091),c=n(3610),p=n(90953),f=n(45402),h=f.set,d=f.getterFor,m=c.find,v=c.findIndex,g=r([].splice),y=0,b=function(e){return e.frozen||(e.frozen=new w)},w=function(){this.entries=[]},E=function(e,t){return m(e.entries,(function(e){return e[0]===t}))};w.prototype={get:function(e){var t=E(this,e);if(t)return t[1]},has:function(e){return!!E(this,e)},set:function(e,t){var n=E(this,e);n?n[1]=t:this.entries.push([e,t])},delete:function(e){var t=v(this.entries,(function(t){return t[0]===e}));return~t&&g(this.entries,t,1),!!~t}},e.exports={getConstructor:function(e,t,n,r){var c=e((function(e,o){u(e,f),h(e,{type:t,id:y++,frozen:void 0}),null!=o&&l(o,e[r],{that:e,AS_ENTRIES:n})})),f=c.prototype,m=d(t),v=function(e,t,n){var r=m(e),o=a(i(t),!0);return!0===o?b(r).set(t,n):o[r.id]=n,e};return o(f,{delete:function(e){var t=m(this);if(!s(e))return!1;var n=a(e);return!0===n?b(t).delete(e):n&&p(n,t.id)&&delete n[t.id]},has:function(e){var t=m(this);if(!s(e))return!1;var n=a(e);return!0===n?b(t).has(e):n&&p(n,t.id)}}),o(f,n?{get:function(e){var t=m(this);if(s(e)){var n=a(e);return!0===n?b(t).get(e):n?n[t.id]:void 0}},set:function(e,t){return v(this,e,t)}}:{add:function(e){return v(this,e,!0)}}),c}}},24683:(e,t,n)=>{"use strict";var r=n(76887),o=n(21899),a=n(21647),i=n(95981),s=n(32029),u=n(93091),l=n(5743),c=n(57475),p=n(10941),f=n(90904),h=n(65988).f,d=n(3610).forEach,m=n(55746),v=n(45402),g=v.set,y=v.getterFor;e.exports=function(e,t,n){var v,b=-1!==e.indexOf("Map"),w=-1!==e.indexOf("Weak"),E=b?"set":"add",x=o[e],_=x&&x.prototype,S={};if(m&&c(x)&&(w||_.forEach&&!i((function(){(new x).entries().next()})))){var k=(v=t((function(t,n){g(l(t,k),{type:e,collection:new x}),null!=n&&u(n,t[E],{that:t,AS_ENTRIES:b})}))).prototype,A=y(e);d(["add","clear","delete","forEach","get","has","set","keys","values","entries"],(function(e){var t="add"==e||"set"==e;!(e in _)||w&&"clear"==e||s(k,e,(function(n,r){var o=A(this).collection;if(!t&&w&&!p(n))return"get"==e&&void 0;var a=o[e](0===n?0:n,r);return t?this:a}))})),w||h(k,"size",{configurable:!0,get:function(){return A(this).collection.size}})}else v=n.getConstructor(t,e,b,E),a.enable();return f(v,e,!1,!0),S[e]=v,r({global:!0,forced:!0},S),w||n.setStrong(v,e,b),v}},23489:(e,t,n)=>{var r=n(90953),o=n(31136),a=n(49677),i=n(65988);e.exports=function(e,t,n){for(var s=o(t),u=i.f,l=a.f,c=0;c{var r=n(99813)("match");e.exports=function(e){var t=/./;try{"/./"[e](t)}catch(n){try{return t[r]=!1,"/./"[e](t)}catch(e){}}return!1}},64160:(e,t,n)=>{var r=n(95981);e.exports=!r((function(){function e(){}return e.prototype.constructor=null,Object.getPrototypeOf(new e)!==e.prototype}))},31046:(e,t,n)=>{"use strict";var r=n(35143).IteratorPrototype,o=n(29290),a=n(31887),i=n(90904),s=n(12077),u=function(){return this};e.exports=function(e,t,n,l){var c=t+" Iterator";return e.prototype=o(r,{next:a(+!l,n)}),i(e,c,!1,!0),s[c]=u,e}},32029:(e,t,n)=>{var r=n(55746),o=n(65988),a=n(31887);e.exports=r?function(e,t,n){return o.f(e,t,a(1,n))}:function(e,t,n){return e[t]=n,e}},31887:e=>{e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},55449:(e,t,n)=>{"use strict";var r=n(83894),o=n(65988),a=n(31887);e.exports=function(e,t,n){var i=r(t);i in e?o.f(e,i,a(0,n)):e[i]=n}},47771:(e,t,n)=>{"use strict";var r=n(76887),o=n(78834),a=n(82529),i=n(79417),s=n(57475),u=n(31046),l=n(249),c=n(88929),p=n(90904),f=n(32029),h=n(99754),d=n(99813),m=n(12077),v=n(35143),g=i.PROPER,y=i.CONFIGURABLE,b=v.IteratorPrototype,w=v.BUGGY_SAFARI_ITERATORS,E=d("iterator"),x="keys",_="values",S="entries",k=function(){return this};e.exports=function(e,t,n,i,d,v,A){u(n,t,i);var C,O,j,I=function(e){if(e===d&&M)return M;if(!w&&e in P)return P[e];switch(e){case x:case _:case S:return function(){return new n(this,e)}}return function(){return new n(this)}},T=t+" Iterator",N=!1,P=e.prototype,R=P[E]||P["@@iterator"]||d&&P[d],M=!w&&R||I(d),D="Array"==t&&P.entries||R;if(D&&(C=l(D.call(new e)))!==Object.prototype&&C.next&&(a||l(C)===b||(c?c(C,b):s(C[E])||h(C,E,k)),p(C,T,!0,!0),a&&(m[T]=k)),g&&d==_&&R&&R.name!==_&&(!a&&y?f(P,"name",_):(N=!0,M=function(){return o(R,this)})),d)if(O={values:I(_),keys:v?M:I(x),entries:I(S)},A)for(j in O)(w||N||!(j in P))&&h(P,j,O[j]);else r({target:t,proto:!0,forced:w||N},O);return a&&!A||P[E]===M||h(P,E,M,{name:d}),m[t]=M,O}},66349:(e,t,n)=>{var r=n(54058),o=n(90953),a=n(11477),i=n(65988).f;e.exports=function(e){var t=r.Symbol||(r.Symbol={});o(t,e)||i(t,e,{value:a.f(e)})}},55746:(e,t,n)=>{var r=n(95981);e.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},61333:(e,t,n)=>{var r=n(21899),o=n(10941),a=r.document,i=o(a)&&o(a.createElement);e.exports=function(e){return i?a.createElement(e):{}}},63281:e=>{e.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},34342:(e,t,n)=>{var r=n(2861).match(/firefox\/(\d+)/i);e.exports=!!r&&+r[1]},23321:e=>{e.exports="object"==typeof window},81046:(e,t,n)=>{var r=n(2861);e.exports=/MSIE|Trident/.test(r)},4470:(e,t,n)=>{var r=n(2861),o=n(21899);e.exports=/ipad|iphone|ipod/i.test(r)&&void 0!==o.Pebble},22749:(e,t,n)=>{var r=n(2861);e.exports=/(?:ipad|iphone|ipod).*applewebkit/i.test(r)},6049:(e,t,n)=>{var r=n(82532),o=n(21899);e.exports="process"==r(o.process)},58045:(e,t,n)=>{var r=n(2861);e.exports=/web0s(?!.*chrome)/i.test(r)},2861:(e,t,n)=>{var r=n(626);e.exports=r("navigator","userAgent")||""},53385:(e,t,n)=>{var r,o,a=n(21899),i=n(2861),s=a.process,u=a.Deno,l=s&&s.versions||u&&u.version,c=l&&l.v8;c&&(o=(r=c.split("."))[0]>0&&r[0]<4?1:+(r[0]+r[1])),!o&&i&&(!(r=i.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=i.match(/Chrome\/(\d+)/))&&(o=+r[1]),e.exports=o},18938:(e,t,n)=>{var r=n(2861).match(/AppleWebKit\/(\d+)\./);e.exports=!!r&&+r[1]},35703:(e,t,n)=>{var r=n(54058);e.exports=function(e){return r[e+"Prototype"]}},56759:e=>{e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},18780:(e,t,n)=>{var r=n(95981),o=n(31887);e.exports=!r((function(){var e=Error("a");return!("stack"in e)||(Object.defineProperty(e,"stack",o(1,7)),7!==e.stack)}))},76887:(e,t,n)=>{"use strict";var r=n(21899),o=n(79730),a=n(95329),i=n(57475),s=n(49677).f,u=n(37252),l=n(54058),c=n(86843),p=n(32029),f=n(90953),h=function(e){var t=function(n,r,a){if(this instanceof t){switch(arguments.length){case 0:return new e;case 1:return new e(n);case 2:return new e(n,r)}return new e(n,r,a)}return o(e,this,arguments)};return t.prototype=e.prototype,t};e.exports=function(e,t){var n,o,d,m,v,g,y,b,w=e.target,E=e.global,x=e.stat,_=e.proto,S=E?r:x?r[w]:(r[w]||{}).prototype,k=E?l:l[w]||p(l,w,{})[w],A=k.prototype;for(d in t)n=!u(E?d:w+(x?".":"#")+d,e.forced)&&S&&f(S,d),v=k[d],n&&(g=e.noTargetGet?(b=s(S,d))&&b.value:S[d]),m=n&&g?g:t[d],n&&typeof v==typeof m||(y=e.bind&&n?c(m,r):e.wrap&&n?h(m):_&&i(m)?a(m):m,(e.sham||m&&m.sham||v&&v.sham)&&p(y,"sham",!0),p(k,d,y),_&&(f(l,o=w+"Prototype")||p(l,o,{}),p(l[o],d,m),e.real&&A&&!A[d]&&p(A,d,m)))}},95981:e=>{e.exports=function(e){try{return!!e()}catch(e){return!0}}},45602:(e,t,n)=>{var r=n(95981);e.exports=!r((function(){return Object.isExtensible(Object.preventExtensions({}))}))},79730:(e,t,n)=>{var r=n(18285),o=Function.prototype,a=o.apply,i=o.call;e.exports="object"==typeof Reflect&&Reflect.apply||(r?i.bind(a):function(){return i.apply(a,arguments)})},86843:(e,t,n)=>{var r=n(95329),o=n(24883),a=n(18285),i=r(r.bind);e.exports=function(e,t){return o(e),void 0===t?e:a?i(e,t):function(){return e.apply(t,arguments)}}},18285:(e,t,n)=>{var r=n(95981);e.exports=!r((function(){var e=function(){}.bind();return"function"!=typeof e||e.hasOwnProperty("prototype")}))},98308:(e,t,n)=>{"use strict";var r=n(21899),o=n(95329),a=n(24883),i=n(10941),s=n(90953),u=n(93765),l=n(18285),c=r.Function,p=o([].concat),f=o([].join),h={},d=function(e,t,n){if(!s(h,t)){for(var r=[],o=0;o{var r=n(18285),o=Function.prototype.call;e.exports=r?o.bind(o):function(){return o.apply(o,arguments)}},79417:(e,t,n)=>{var r=n(55746),o=n(90953),a=Function.prototype,i=r&&Object.getOwnPropertyDescriptor,s=o(a,"name"),u=s&&"something"===function(){}.name,l=s&&(!r||r&&i(a,"name").configurable);e.exports={EXISTS:s,PROPER:u,CONFIGURABLE:l}},95329:(e,t,n)=>{var r=n(18285),o=Function.prototype,a=o.bind,i=o.call,s=r&&a.bind(i,i);e.exports=r?function(e){return e&&s(e)}:function(e){return e&&function(){return i.apply(e,arguments)}}},626:(e,t,n)=>{var r=n(54058),o=n(21899),a=n(57475),i=function(e){return a(e)?e:void 0};e.exports=function(e,t){return arguments.length<2?i(r[e])||i(o[e]):r[e]&&r[e][t]||o[e]&&o[e][t]}},22902:(e,t,n)=>{var r=n(9697),o=n(14229),a=n(12077),i=n(99813)("iterator");e.exports=function(e){if(null!=e)return o(e,i)||o(e,"@@iterator")||a[r(e)]}},53476:(e,t,n)=>{var r=n(21899),o=n(78834),a=n(24883),i=n(96059),s=n(69826),u=n(22902),l=r.TypeError;e.exports=function(e,t){var n=arguments.length<2?u(e):t;if(a(n))return i(o(n,e));throw l(s(e)+" is not iterable")}},79993:(e,t,n)=>{var r=n(53476);e.exports=r},14229:(e,t,n)=>{var r=n(24883);e.exports=function(e,t){var n=e[t];return null==n?void 0:r(n)}},21899:(e,t,n)=>{var r=function(e){return e&&e.Math==Math&&e};e.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof n.g&&n.g)||function(){return this}()||Function("return this")()},90953:(e,t,n)=>{var r=n(95329),o=n(89678),a=r({}.hasOwnProperty);e.exports=Object.hasOwn||function(e,t){return a(o(e),t)}},27748:e=>{e.exports={}},34845:(e,t,n)=>{var r=n(21899);e.exports=function(e,t){var n=r.console;n&&n.error&&(1==arguments.length?n.error(e):n.error(e,t))}},15463:(e,t,n)=>{var r=n(626);e.exports=r("document","documentElement")},2840:(e,t,n)=>{var r=n(55746),o=n(95981),a=n(61333);e.exports=!r&&!o((function(){return 7!=Object.defineProperty(a("div"),"a",{get:function(){return 7}}).a}))},37026:(e,t,n)=>{var r=n(21899),o=n(95329),a=n(95981),i=n(82532),s=r.Object,u=o("".split);e.exports=a((function(){return!s("z").propertyIsEnumerable(0)}))?function(e){return"String"==i(e)?u(e,""):s(e)}:s},81302:(e,t,n)=>{var r=n(95329),o=n(57475),a=n(63030),i=r(Function.toString);o(a.inspectSource)||(a.inspectSource=function(e){return i(e)}),e.exports=a.inspectSource},53794:(e,t,n)=>{var r=n(10941),o=n(32029);e.exports=function(e,t){r(t)&&"cause"in t&&o(e,"cause",t.cause)}},21647:(e,t,n)=>{var r=n(76887),o=n(95329),a=n(27748),i=n(10941),s=n(90953),u=n(65988).f,l=n(10946),c=n(684),p=n(91584),f=n(99418),h=n(45602),d=!1,m=f("meta"),v=0,g=function(e){u(e,m,{value:{objectID:"O"+v++,weakData:{}}})},y=e.exports={enable:function(){y.enable=function(){},d=!0;var e=l.f,t=o([].splice),n={};n[m]=1,e(n).length&&(l.f=function(n){for(var r=e(n),o=0,a=r.length;o{var r,o,a,i=n(38019),s=n(21899),u=n(95329),l=n(10941),c=n(32029),p=n(90953),f=n(63030),h=n(44262),d=n(27748),m="Object already initialized",v=s.TypeError,g=s.WeakMap;if(i||f.state){var y=f.state||(f.state=new g),b=u(y.get),w=u(y.has),E=u(y.set);r=function(e,t){if(w(y,e))throw new v(m);return t.facade=e,E(y,e,t),t},o=function(e){return b(y,e)||{}},a=function(e){return w(y,e)}}else{var x=h("state");d[x]=!0,r=function(e,t){if(p(e,x))throw new v(m);return t.facade=e,c(e,x,t),t},o=function(e){return p(e,x)?e[x]:{}},a=function(e){return p(e,x)}}e.exports={set:r,get:o,has:a,enforce:function(e){return a(e)?o(e):r(e,{})},getterFor:function(e){return function(t){var n;if(!l(t)||(n=o(t)).type!==e)throw v("Incompatible receiver, "+e+" required");return n}}}},6782:(e,t,n)=>{var r=n(99813),o=n(12077),a=r("iterator"),i=Array.prototype;e.exports=function(e){return void 0!==e&&(o.Array===e||i[a]===e)}},1052:(e,t,n)=>{var r=n(82532);e.exports=Array.isArray||function(e){return"Array"==r(e)}},57475:e=>{e.exports=function(e){return"function"==typeof e}},24284:(e,t,n)=>{var r=n(95329),o=n(95981),a=n(57475),i=n(9697),s=n(626),u=n(81302),l=function(){},c=[],p=s("Reflect","construct"),f=/^\s*(?:class|function)\b/,h=r(f.exec),d=!f.exec(l),m=function(e){if(!a(e))return!1;try{return p(l,c,e),!0}catch(e){return!1}},v=function(e){if(!a(e))return!1;switch(i(e)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return d||!!h(f,u(e))}catch(e){return!0}};v.sham=!0,e.exports=!p||o((function(){var e;return m(m.call)||!m(Object)||!m((function(){e=!0}))||e}))?v:m},77040:(e,t,n)=>{var r=n(90953);e.exports=function(e){return void 0!==e&&(r(e,"value")||r(e,"writable"))}},37252:(e,t,n)=>{var r=n(95981),o=n(57475),a=/#|\.prototype\./,i=function(e,t){var n=u[s(e)];return n==c||n!=l&&(o(t)?r(t):!!t)},s=i.normalize=function(e){return String(e).replace(a,".").toLowerCase()},u=i.data={},l=i.NATIVE="N",c=i.POLYFILL="P";e.exports=i},10941:(e,t,n)=>{var r=n(57475);e.exports=function(e){return"object"==typeof e?null!==e:r(e)}},82529:e=>{e.exports=!0},60685:(e,t,n)=>{var r=n(10941),o=n(82532),a=n(99813)("match");e.exports=function(e){var t;return r(e)&&(void 0!==(t=e[a])?!!t:"RegExp"==o(e))}},56664:(e,t,n)=>{var r=n(21899),o=n(626),a=n(57475),i=n(7046),s=n(32302),u=r.Object;e.exports=s?function(e){return"symbol"==typeof e}:function(e){var t=o("Symbol");return a(t)&&i(t.prototype,u(e))}},93091:(e,t,n)=>{var r=n(21899),o=n(86843),a=n(78834),i=n(96059),s=n(69826),u=n(6782),l=n(10623),c=n(7046),p=n(53476),f=n(22902),h=n(7609),d=r.TypeError,m=function(e,t){this.stopped=e,this.result=t},v=m.prototype;e.exports=function(e,t,n){var r,g,y,b,w,E,x,_=n&&n.that,S=!(!n||!n.AS_ENTRIES),k=!(!n||!n.IS_ITERATOR),A=!(!n||!n.INTERRUPTED),C=o(t,_),O=function(e){return r&&h(r,"normal",e),new m(!0,e)},j=function(e){return S?(i(e),A?C(e[0],e[1],O):C(e[0],e[1])):A?C(e,O):C(e)};if(k)r=e;else{if(!(g=f(e)))throw d(s(e)+" is not iterable");if(u(g)){for(y=0,b=l(e);b>y;y++)if((w=j(e[y]))&&c(v,w))return w;return new m(!1)}r=p(e,g)}for(E=r.next;!(x=a(E,r)).done;){try{w=j(x.value)}catch(e){h(r,"throw",e)}if("object"==typeof w&&w&&c(v,w))return w}return new m(!1)}},7609:(e,t,n)=>{var r=n(78834),o=n(96059),a=n(14229);e.exports=function(e,t,n){var i,s;o(e);try{if(!(i=a(e,"return"))){if("throw"===t)throw n;return n}i=r(i,e)}catch(e){s=!0,i=e}if("throw"===t)throw n;if(s)throw i;return o(i),n}},35143:(e,t,n)=>{"use strict";var r,o,a,i=n(95981),s=n(57475),u=n(29290),l=n(249),c=n(99754),p=n(99813),f=n(82529),h=p("iterator"),d=!1;[].keys&&("next"in(a=[].keys())?(o=l(l(a)))!==Object.prototype&&(r=o):d=!0),null==r||i((function(){var e={};return r[h].call(e)!==e}))?r={}:f&&(r=u(r)),s(r[h])||c(r,h,(function(){return this})),e.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:d}},12077:e=>{e.exports={}},10623:(e,t,n)=>{var r=n(43057);e.exports=function(e){return r(e.length)}},48721:(e,t,n)=>{"use strict";var r=n(78834),o=n(24883),a=n(96059);e.exports=function(e,t){var n=a(this),i=o(n.get),s=o(n.has),u=o(n.set),l=r(s,n,e)&&"update"in t?t.update(r(i,n,e),e,n):t.insert(e,n);return r(u,n,e,l),l}},20716:(e,t,n)=>{"use strict";var r=n(21899),o=n(78834),a=n(24883),i=n(57475),s=n(96059),u=r.TypeError;e.exports=function(e,t){var n,r=s(this),l=a(r.get),c=a(r.has),p=a(r.set),f=arguments.length>2?arguments[2]:void 0;if(!i(t)&&!i(f))throw u("At least one callback required");return o(c,r,e)?(n=o(l,r,e),i(t)&&(n=t(n),o(p,r,e,n))):i(f)&&(n=f(),o(p,r,e,n)),n}},66132:(e,t,n)=>{var r,o,a,i,s,u,l,c,p=n(21899),f=n(86843),h=n(49677).f,d=n(42941).set,m=n(22749),v=n(4470),g=n(58045),y=n(6049),b=p.MutationObserver||p.WebKitMutationObserver,w=p.document,E=p.process,x=p.Promise,_=h(p,"queueMicrotask"),S=_&&_.value;S||(r=function(){var e,t;for(y&&(e=E.domain)&&e.exit();o;){t=o.fn,o=o.next;try{t()}catch(e){throw o?i():a=void 0,e}}a=void 0,e&&e.enter()},m||y||g||!b||!w?!v&&x&&x.resolve?((l=x.resolve(void 0)).constructor=x,c=f(l.then,l),i=function(){c(r)}):y?i=function(){E.nextTick(r)}:(d=f(d,p),i=function(){d(r)}):(s=!0,u=w.createTextNode(""),new b(r).observe(u,{characterData:!0}),i=function(){u.data=s=!s})),e.exports=S||function(e){var t={fn:e,next:void 0};a&&(a.next=t),o||(o=t,i()),a=t}},19297:(e,t,n)=>{var r=n(21899);e.exports=r.Promise},72497:(e,t,n)=>{var r=n(53385),o=n(95981);e.exports=!!Object.getOwnPropertySymbols&&!o((function(){var e=Symbol();return!String(e)||!(Object(e)instanceof Symbol)||!Symbol.sham&&r&&r<41}))},28468:(e,t,n)=>{var r=n(95981),o=n(99813),a=n(82529),i=o("iterator");e.exports=!r((function(){var e=new URL("b?a=1&b=2&c=3","http://a"),t=e.searchParams,n="";return e.pathname="c%20d",t.forEach((function(e,r){t.delete("b"),n+=r+e})),a&&!e.toJSON||!t.sort||"http://a/c%20d?a=1&c=3"!==e.href||"3"!==t.get("c")||"a=1"!==String(new URLSearchParams("?a=1"))||!t[i]||"a"!==new URL("https://a@b").username||"b"!==new URLSearchParams(new URLSearchParams("a=b")).get("a")||"xn--e1aybc"!==new URL("http://тест").host||"#%D0%B1"!==new URL("http://a#б").hash||"a1c3"!==n||"x"!==new URL("http://x",void 0).host}))},38019:(e,t,n)=>{var r=n(21899),o=n(57475),a=n(81302),i=r.WeakMap;e.exports=o(i)&&/native code/.test(a(i))},69520:(e,t,n)=>{"use strict";var r=n(24883),o=function(e){var t,n;this.promise=new e((function(e,r){if(void 0!==t||void 0!==n)throw TypeError("Bad Promise constructor");t=e,n=r})),this.resolve=r(t),this.reject=r(n)};e.exports.f=function(e){return new o(e)}},14649:(e,t,n)=>{var r=n(85803);e.exports=function(e,t){return void 0===e?arguments.length<2?"":t:r(e)}},70344:(e,t,n)=>{var r=n(21899),o=n(60685),a=r.TypeError;e.exports=function(e){if(o(e))throw a("The method doesn't accept regular expressions");return e}},24420:(e,t,n)=>{"use strict";var r=n(55746),o=n(95329),a=n(78834),i=n(95981),s=n(14771),u=n(87857),l=n(36760),c=n(89678),p=n(37026),f=Object.assign,h=Object.defineProperty,d=o([].concat);e.exports=!f||i((function(){if(r&&1!==f({b:1},f(h({},"a",{enumerable:!0,get:function(){h(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var e={},t={},n=Symbol(),o="abcdefghijklmnopqrst";return e[n]=7,o.split("").forEach((function(e){t[e]=e})),7!=f({},e)[n]||s(f({},t)).join("")!=o}))?function(e,t){for(var n=c(e),o=arguments.length,i=1,f=u.f,h=l.f;o>i;)for(var m,v=p(arguments[i++]),g=f?d(s(v),f(v)):s(v),y=g.length,b=0;y>b;)m=g[b++],r&&!a(h,v,m)||(n[m]=v[m]);return n}:f},29290:(e,t,n)=>{var r,o=n(96059),a=n(59938),i=n(56759),s=n(27748),u=n(15463),l=n(61333),c=n(44262),p=c("IE_PROTO"),f=function(){},h=function(e){return"