All Downloads are FREE. Search and download functionalities are using the official Maven repository.

lucuma.odb.json.stepconfig.scala Maven / Gradle / Ivy

// Copyright (c) 2016-2023 Association of Universities for Research in Astronomy, Inc. (AURA)
// For license information see LICENSE or https://opensource.org/licenses/BSD-3-Clause

package lucuma.odb.json

import cats.syntax.either.*
import io.circe.Decoder
import io.circe.DecodingFailure
import io.circe.Encoder
import io.circe.Json
import io.circe.syntax.*
import lucuma.core.enums.GcalArc
import lucuma.core.enums.GcalContinuum
import lucuma.core.enums.GcalDiffuser
import lucuma.core.enums.GcalFilter
import lucuma.core.enums.GcalShutter
import lucuma.core.enums.SmartGcalType
import lucuma.core.enums.StepGuideState
import lucuma.core.enums.StepType
import lucuma.core.math.Offset
import lucuma.core.model.sequence.StepConfig

trait StepConfigCodec {

  import offset.decoder.given

  given given_Decoder_Lamp: Decoder[StepConfig.Gcal.Lamp] =
    Decoder.instance { c =>
      for {
        u <- c.downField("continuum").as[Option[GcalContinuum]]
        a <- c.downField("arcs").as[List[GcalArc]]
        r <- StepConfig.Gcal.Lamp.fromContinuumOrArcs(u, a).leftMap(msg => DecodingFailure(msg, c.history))
      } yield r
    }

  given given_Encoder_Lamp: Encoder[StepConfig.Gcal.Lamp] =
    Encoder.instance { (a: StepConfig.Gcal.Lamp) =>
      Json.obj(
        "continuum" -> a.continuum.asJson,
        "arcs"      -> a.toArcsSortedSet.asJson
      )
    }

  given Decoder[StepConfig.Gcal] =
    Decoder.instance { c =>
      for {
        l <- given_Decoder_Lamp(c)
        f <- c.downField("filter").as[GcalFilter]
        d <- c.downField("diffuser").as[GcalDiffuser]
        s <- c.downField("shutter").as[GcalShutter]
      } yield StepConfig.Gcal(l, f, d, s)
    }

  given Encoder[StepConfig.Gcal] =
    Encoder.instance { (a: StepConfig.Gcal) =>
      given_Encoder_Lamp(a.lamp).mapObject { jo =>
        jo.add("filter",   a.filter.asJson)
          .add("diffuser", a.diffuser.asJson)
          .add("shutter",  a.shutter.asJson)
      }
    }

  given Decoder[StepConfig.Science] =
    Decoder.instance { c =>
      for {
        o <- c.downField("offset").as[Offset]
        g <- c.downField("guiding").as[StepGuideState]
      } yield StepConfig.Science(o, g)
    }

  given (using Encoder[Offset]): Encoder[StepConfig.Science] =
    Encoder.instance { (a: StepConfig.Science) =>
      Json.obj(
        "offset"  -> a.offset.asJson,
        "guiding" -> a.guiding.asJson
      )
    }

  given Decoder[StepConfig.SmartGcal] =
    Decoder.instance { c =>
      c.downField("smartGcalType").as[SmartGcalType].map { sgt =>
        StepConfig.SmartGcal(sgt)
      }
    }

  given Encoder[StepConfig.SmartGcal] =
    Encoder.instance { (a: StepConfig.SmartGcal) =>
      Json.obj(
        "smartGcalType" -> a.smartGcalType.asJson
      )
    }

  given Decoder[StepConfig] =
    Decoder.instance { c =>
      c.downField("stepType").as[StepType].flatMap {
        case StepType.Bias      => StepConfig.Bias.asRight[DecodingFailure]
        case StepType.Dark      => StepConfig.Dark.asRight[DecodingFailure]
        case StepType.Gcal      => c.as[StepConfig.Gcal]
        case StepType.Science   => c.as[StepConfig.Science]
        case StepType.SmartGcal => c.as[StepConfig.SmartGcal]
      }
    }

  given (using Encoder[Offset]): Encoder[StepConfig] =
    Encoder.instance { (a: StepConfig) =>
      (a match {
        case _: StepConfig.Bias.type => Json.obj()
        case _: StepConfig.Dark.type => Json.obj()
        case s: StepConfig.Science   => s.asJson
        case g: StepConfig.Gcal      => g.asJson
        case m: StepConfig.SmartGcal => m.asJson
      }).mapObject(("stepType" -> a.stepType.asJson) +: _)
    }

}

object stepconfig extends StepConfigCodec





© 2015 - 2024 Weber Informatics LLC | Privacy Policy