feat: Add Initial Plume UI
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
FROM mcr.microsoft.com/dotnet/sdk:9.0
|
||||
FROM mcr.microsoft.com/dotnet/sdk:9.0.301
|
||||
|
||||
# Bun version
|
||||
ARG BUN_INSTALL=/usr/local
|
||||
|
||||
10
README.md
10
README.md
@@ -110,7 +110,7 @@ Now, we should be able to `restore`:
|
||||
|
||||
```sh
|
||||
dotnet tool restore
|
||||
dotnet restore
|
||||
dotnet restore Poseidon.slnx
|
||||
```
|
||||
|
||||
### Mkcert
|
||||
@@ -163,3 +163,11 @@ In order for your browser to allow you to access the web application, you must a
|
||||
2. Click on _"View Certificates",_ then _"Import..."_ in the _"Authorities"_ tab.
|
||||
3. Select the root certificate; `~/.vite-plugin-mkcert/certs/rootCA.pem`.
|
||||
- Make sure to check _"This certificate can identify websites"._
|
||||
|
||||
### Add `user` to OpenFGA
|
||||
|
||||
Ask [sales](moritz.jorg@oceanbox.io) to add your `azure-ad-user` to OpenFGA.
|
||||
|
||||
### CORS for Sorcerer
|
||||
|
||||
Add the `url` of your instance to the CORS list of Sorcerer [here](https://gitlab.com/oceanbox/manifests/-/blob/main/values/sorcerer/kustomize/prod/appsettings.json?ref_type=heads#L52).
|
||||
|
||||
@@ -26,13 +26,13 @@ let fableWatch = $"fable watch -e .jsx -o build --run {vite}"
|
||||
Target.create "Clean" (fun _ -> Shell.cleanDir distPath)
|
||||
|
||||
Target.create "Bundle" (fun _ ->
|
||||
[ "server", dotnet $"publish -tl -c Release -o {distPath}" serverPath
|
||||
[ "server", dotnet $"build -tl -c Release -o {distPath}" serverPath
|
||||
"client", dotnet (fable "-m production") clientPath ]
|
||||
|> runParallel
|
||||
)
|
||||
|
||||
Target.create "BundleDebug" (fun _ ->
|
||||
[ "server", dotnet $"publish -tl -c Debug -o {distPath}" serverPath
|
||||
[ "server", dotnet $"build -tl -c Debug --no-restore -o {distPath}" serverPath
|
||||
"client", dotnet (fable "-m development --minify false --sourcemap true") clientPath ]
|
||||
|> runParallel
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:9.0
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:9.0.6
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y gcc-multilib libnetcdf19 libnetcdf-dev
|
||||
|
||||
|
||||
@@ -162,3 +162,9 @@ let cropStatsApi url =
|
||||
|> Remoting.withRouteBuilder Api.Crop.routeBuilder
|
||||
|> Remoting.withBinarySerialization
|
||||
|> Remoting.buildProxy<Api.Crop.Stats>
|
||||
|
||||
let plumeApi () =
|
||||
Remoting.createApi ()
|
||||
|> Remoting.withCredentials true
|
||||
|> Remoting.withRouteBuilder Api.authorizedRouteBuilder
|
||||
|> Remoting.buildProxy<Api.Plume>
|
||||
|
||||
@@ -606,9 +606,77 @@ type SimArchive =
|
||||
|
||||
}
|
||||
|
||||
type PlumeSimModel = {
|
||||
name: string
|
||||
fvcom: System.Guid
|
||||
start: DateTime
|
||||
stop: DateTime
|
||||
timeIdx: int
|
||||
} with
|
||||
static member empty = {
|
||||
name = ""
|
||||
fvcom = System.Guid.Empty
|
||||
start = DateTime.Now
|
||||
stop = DateTime.Now.AddDays(4)
|
||||
timeIdx = 0
|
||||
}
|
||||
|
||||
type PlumeReleaseSite = {
|
||||
position: float * float
|
||||
radius: float
|
||||
theta: float
|
||||
depth: float
|
||||
// ddepth: float
|
||||
} with
|
||||
static member empty = {
|
||||
position = 0.0, 0.0
|
||||
radius = 1.0
|
||||
theta = 10.0
|
||||
depth = -20.0
|
||||
// ddepth = 10.0
|
||||
}
|
||||
|
||||
type PlumeGroupModel = {
|
||||
name: string option
|
||||
sites: PlumeReleaseSite list
|
||||
} with
|
||||
static member empty i = {
|
||||
name = $"Group-{i}" |> Some
|
||||
sites = List.Empty
|
||||
}
|
||||
|
||||
type PlumeTraits = {
|
||||
temp: float
|
||||
salt: float
|
||||
transport: float
|
||||
} with
|
||||
static member empty = {
|
||||
temp = 0.0
|
||||
salt = 0.0
|
||||
transport = 0.0
|
||||
}
|
||||
|
||||
type PlumeType =
|
||||
| DefaultPlume
|
||||
member this.ToLabel() =
|
||||
match this with
|
||||
| DefaultPlume -> "Plume"
|
||||
|
||||
type SimControlKind =
|
||||
| Drifters of SimType
|
||||
| Plume of PlumeType
|
||||
member this.ToLabel() =
|
||||
match this with
|
||||
| Drifters simType -> simType.ToLabel ()
|
||||
| Plume plumeType -> plumeType.ToLabel ()
|
||||
member this.simTypeOpt =
|
||||
match this with
|
||||
| Drifters simType -> Some simType
|
||||
| Plume plumeType -> None
|
||||
|
||||
type SideNavMode =
|
||||
| OceanControls
|
||||
| SimControls of SimType
|
||||
| SimControls of SimControlKind
|
||||
| AnalysisControls of SimArchive
|
||||
| ColorControls
|
||||
| LayerControls
|
||||
@@ -619,7 +687,7 @@ with
|
||||
member this.ToLabel () =
|
||||
match this with
|
||||
| OceanControls -> "Ocean controls"
|
||||
| SimControls simType -> $"Simulation controls {simType.ToLabel ()}"
|
||||
| SimControls simControlKind -> $"Simulation controls {simControlKind.ToLabel ()}"
|
||||
| AnalysisControls _ -> "Analysis controls"
|
||||
| ColorControls -> "Color controls"
|
||||
| LayerControls -> "Layer controls"
|
||||
|
||||
@@ -214,12 +214,12 @@ let fetchDrifters (api: ArchivesApi) (aid: Guid) : SimArchive [] JS.Promise =
|
||||
|> Array.map (fun (d, n, t) ->
|
||||
let reverse =
|
||||
match d.archiveType with
|
||||
| Drifters (_, DriftersFormat.Particle) ->
|
||||
| ArchiveType.Drifters (_, DriftersFormat.Particle) ->
|
||||
decodeDriftersInput d
|
||||
|> Option.map _.simulation.reverse
|
||||
|> Option.flatten
|
||||
|> Option.defaultValue false
|
||||
| Drifters _ ->
|
||||
| ArchiveType.Drifters _ ->
|
||||
decodePostdriftInput d
|
||||
|> Option.map _.analysis.reverse
|
||||
|> Option.flatten
|
||||
|
||||
@@ -712,7 +712,7 @@ let update cmd model =
|
||||
| _ -> TransportSim
|
||||
let m =
|
||||
{ model with
|
||||
sideNavMode = SideNavMode.SimControls kind
|
||||
sideNavMode = SideNavMode.SimControls (Drifters kind)
|
||||
mode = Mode.Simulation Placing
|
||||
}
|
||||
|
||||
@@ -1561,9 +1561,12 @@ let update cmd model =
|
||||
let n' = if n = abs(model.inboxUnread) then -model.inboxUnread else n
|
||||
// console.log $"unread: {n'}"
|
||||
{ model with inboxUnread = n' }, Cmd.none
|
||||
| SelectPlume id ->
|
||||
| SetPlumeModel modelOpt ->
|
||||
console.debug("[Mapster] SetPlumeModel:", modelOpt)
|
||||
{ model with plumeModelOpt = modelOpt }, Cmd.none
|
||||
| SetSelectedPlume id ->
|
||||
console.log $"Selected plume: {id}"
|
||||
{ model with plume = id }, Cmd.none
|
||||
{ model with selectedPlume = Some id }, Cmd.none
|
||||
| HubMsg msg -> { model with hubAction = Some msg }, Cmd.none
|
||||
| Noop _ -> model, Cmd.none
|
||||
|
||||
@@ -2042,7 +2045,7 @@ let MapAppElement () =
|
||||
let selectInboxItem (id, type': MessageType) =
|
||||
Hub.Action.Inbox (Hub.InboxMsg.MarkRead id) |> (HubMsg >> dispatch)
|
||||
match type' with
|
||||
| MessageType.Plume -> SelectPlume (Some id) |> dispatch
|
||||
| MessageType.Plume -> SetSelectedPlume id |> dispatch
|
||||
| MessageType.Drifters -> SetSelectedDrifter id |> dispatch
|
||||
| _ -> ()
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<Compile Include="Timeline.fs" />
|
||||
<Compile Include="Fiskeridir.fs" />
|
||||
<Compile Include="BarentsWatch.fs" />
|
||||
<Compile Include="Plume.fs" />
|
||||
<Compile Include="Drifters.fs" />
|
||||
<Compile Include="ContourModel.fs" />
|
||||
<Compile Include="Postdrift.fs" />
|
||||
|
||||
@@ -224,6 +224,16 @@ type PostdriftModel = {
|
||||
openLayersMap: OlMap
|
||||
}
|
||||
|
||||
type PlumeModel = {
|
||||
kind: PlumeType
|
||||
simStarted: bool * int option
|
||||
simulation: PlumeSimModel
|
||||
sites: PlumeReleaseSite list
|
||||
traits: PlumeTraits
|
||||
selectedSite: (int * PlumeReleaseSite) option
|
||||
openLayersMap: OlMap
|
||||
}
|
||||
|
||||
type ContourData = (float*float)[][]
|
||||
type ContourModel = {
|
||||
kind: ContourKind
|
||||
@@ -334,7 +344,8 @@ type Model = {
|
||||
identity: Api.UserIdentity
|
||||
inboxUnread: int
|
||||
hubAction: Hub.Action option
|
||||
plume: System.Guid option
|
||||
plumeModelOpt: PlumeModel option
|
||||
selectedPlume: ArchiveId option
|
||||
infectionNetwork: NetworkState
|
||||
}
|
||||
with
|
||||
@@ -399,7 +410,8 @@ with
|
||||
identity = Api.UserIdentity.empty
|
||||
inboxUnread = 0
|
||||
hubAction = None
|
||||
plume = None
|
||||
plumeModelOpt = None
|
||||
selectedPlume = None
|
||||
infectionNetwork = NetworkState.empty
|
||||
}
|
||||
|
||||
@@ -504,7 +516,8 @@ type Msg =
|
||||
| DeleteArchive of System.Guid
|
||||
| SetIdentity of Api.UserIdentity
|
||||
| SetUnread of int
|
||||
| SelectPlume of System.Guid option
|
||||
| SetPlumeModel of PlumeModel option
|
||||
| SetSelectedPlume of System.Guid
|
||||
| HubMsg of Hub.Action
|
||||
| Noop of unit
|
||||
|
||||
|
||||
@@ -140,6 +140,8 @@ let simAccordion (dispatch: Msg -> unit) model =
|
||||
// let canSubmit = model.simPolicies |> Array.fold (fun a x -> a || x.IsAllowed()) false
|
||||
console.debug $"policies: %A{model.simPolicies}"
|
||||
let disabled = model.archive.id = Guid.Empty
|
||||
// TODO(mrtz): Set an actual condition on plumes
|
||||
let disabledPlume = false
|
||||
let disabledTransport = model.simPolicies |> Array.contains (DriftersPolicy.SubmitTransport false)
|
||||
let disabledDeposition = model.simPolicies |> Array.contains (DriftersPolicy.SubmitSedimentation false)
|
||||
let chooseMode kind _ =
|
||||
@@ -178,38 +180,45 @@ let simAccordion (dispatch: Msg -> unit) model =
|
||||
<sp-action-button
|
||||
static="primary"
|
||||
?disabled={disabledTransport}
|
||||
@click={Ev(chooseMode TransportSim)}
|
||||
@click={Ev(chooseMode (Drifters TransportSim))}
|
||||
>
|
||||
Transport
|
||||
</sp-action-button>
|
||||
<sp-action-button
|
||||
static="primary"
|
||||
?disabled={disabledTransport}
|
||||
@click={Ev(chooseMode LiceSim)}
|
||||
@click={Ev(chooseMode (Drifters LiceSim))}
|
||||
>
|
||||
Salmon lice
|
||||
</sp-action-button>
|
||||
<sp-action-button
|
||||
static="primary"
|
||||
?disabled={disabledTransport}
|
||||
@click={Ev(chooseMode VirusSim)}
|
||||
@click={Ev(chooseMode (Drifters VirusSim))}
|
||||
>
|
||||
Virus
|
||||
</sp-action-button>
|
||||
<sp-action-button
|
||||
static="primary"
|
||||
?disabled={disabledDeposition}
|
||||
@click={Ev(chooseMode DepositionSim)}
|
||||
@click={Ev(chooseMode (Drifters DepositionSim))}
|
||||
>
|
||||
Deposition
|
||||
</sp-action-button>
|
||||
<sp-action-button
|
||||
static="primary"
|
||||
?disabled={disabledTransport}
|
||||
@click={Ev(chooseMode WaterContactSim)}
|
||||
@click={Ev(chooseMode (Drifters WaterContactSim))}
|
||||
>
|
||||
Water contact
|
||||
</sp-action-button>
|
||||
<sp-action-button
|
||||
static="primary"
|
||||
?disabled={disabledPlume}
|
||||
@click={Ev (chooseMode(Plume DefaultPlume))}
|
||||
>
|
||||
Plume
|
||||
</sp-action-button>
|
||||
</sp-action-group>
|
||||
</div>
|
||||
"""
|
||||
@@ -572,8 +581,13 @@ let sideNav (dispatch: Msg -> unit) (model: Model) (navMode: SideNavMode) =
|
||||
let simSelector (dispatch: Msg -> unit) (model: Model) =
|
||||
match model.mode with
|
||||
| Mode.Simulation Placing ->
|
||||
console.log $"simControls : {kind}"
|
||||
Drifters.simulationControls kind dispatch model
|
||||
match kind.simTypeOpt with
|
||||
| Some simType ->
|
||||
console.log $"drifter simControls : {kind}"
|
||||
Drifters.simulationControls simType dispatch model
|
||||
| None ->
|
||||
console.log $"plume simControls : {kind}"
|
||||
Plume.simulationControls DefaultPlume dispatch model
|
||||
| Mode.Moot
|
||||
| Mode.Ocean
|
||||
| Mode.Stats _
|
||||
@@ -731,22 +745,21 @@ let toolboxNav setArchivesOpen setInboxOpen model dispatch =
|
||||
| Mode.Ocean -> ()
|
||||
| _ -> SetMode Mode.Ocean |> dispatch
|
||||
|
||||
let selectCompute (driftersModelOpt: DrifterModel option) ev =
|
||||
let selectCompute (driftersModelOpt: DrifterModel option) (plumeModelOpt: PlumeModel option) ev =
|
||||
if canSubmit then
|
||||
match driftersModelOpt with
|
||||
| Some d ->
|
||||
console.debug($"We already have an ongoing sim : {d.simulation.kind}")
|
||||
d.simulation.kind
|
||||
|> SimControls
|
||||
|> SetSideNavMode
|
||||
|> dispatch
|
||||
match driftersModelOpt, plumeModelOpt with
|
||||
| Some d, _ ->
|
||||
console.debug ($"We already have an ongoing driftser sim : {d.simulation.kind}")
|
||||
(Drifters d.simulation.kind) |> SimControls |> SetSideNavMode |> dispatch
|
||||
|
||||
SimMode.Placing
|
||||
|> Mode.Simulation
|
||||
|> SetMode
|
||||
|> dispatch
|
||||
SimMode.Placing |> Mode.Simulation |> SetMode |> dispatch
|
||||
| None, Some p ->
|
||||
console.debug ($"We already have an ongoing plume sim")
|
||||
(Plume p.kind) |> SimControls |> SetSideNavMode |> dispatch
|
||||
|
||||
SimMode.Placing |> Mode.Simulation |> SetMode |> dispatch
|
||||
| _ ->
|
||||
SimType.TransportSim
|
||||
(Drifters SimType.TransportSim)
|
||||
|> SimControls
|
||||
|> SetSideNavMode
|
||||
|> dispatch
|
||||
@@ -804,7 +817,7 @@ let toolboxNav setArchivesOpen setInboxOpen model dispatch =
|
||||
<overlay-trigger id="trigger" placement="right" offset="6">
|
||||
<sp-tooltip slot="hover-content">Compute</sp-tooltip>
|
||||
<div slot="trigger" class="toolbox-control{if canSubmit then " " + isSimControls else ".disabled" }">
|
||||
<div class="toolboxIcon" @click={Ev(selectCompute model.drifterModelOpt)}>
|
||||
<div class="toolboxIcon" @click={Ev(selectCompute model.drifterModelOpt model.plumeModelOpt)}>
|
||||
{if model.drifterModelOpt.IsSome then statusIcon else Lit.nothing}
|
||||
<i class="fas fa-server"></i>
|
||||
</div>
|
||||
|
||||
1006
src/Atlantis/src/Client/Mapster/Plume.fs
Normal file
1006
src/Atlantis/src/Client/Mapster/Plume.fs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -475,6 +475,80 @@ module Handlers =
|
||||
|> Async.AwaitTask
|
||||
}
|
||||
|
||||
let private runPlume
|
||||
(ctx: HttpContext)
|
||||
(plumeJob: PlumeJob)
|
||||
=
|
||||
task {
|
||||
let user = getUserName ctx
|
||||
let group = getGroup ctx
|
||||
|
||||
let id = ActorId user
|
||||
|
||||
try
|
||||
let proxy = ActorProxy.Create<IPlumeActor> (id, "PlumeActor")
|
||||
Log.Information ("runPlume: user {username}, fvcom={@fvcom}, name={@name}", user, plumeJob.fvcom, plumeJob.name)
|
||||
|
||||
match! proxy.Submit plumeJob with
|
||||
| Ok info ->
|
||||
Log.Debug $"jobid is {info.jobId} ({info.archiveId})"
|
||||
return Some info
|
||||
| Error e ->
|
||||
Log.Warning $"job submit failed: {e}"
|
||||
|
||||
match SignalRHub.getHub ctx with
|
||||
| Some h ->
|
||||
do! h.Clients.User(user).Send (Hub.Response.Note (Note.failure $"Job submission failed: {e}"))
|
||||
return None
|
||||
| None ->
|
||||
Log.Error "Could not get signalr hub context"
|
||||
return None
|
||||
with exn ->
|
||||
Log.Error $"runPlume: {exn.Message}"
|
||||
Log.Verbose $"runPlume: %A{exn}"
|
||||
return None
|
||||
}
|
||||
|> Async.AwaitTask
|
||||
|
||||
let private getPlumeSimInfo (ctx: HttpContext) (jobId: int) =
|
||||
task {
|
||||
let user = getUserName ctx
|
||||
let id = ActorId user
|
||||
|
||||
try
|
||||
let proxy = ActorProxy.Create<IJobActor> (id, "PlumeActor")
|
||||
let! job = getJobInfo proxy jobId
|
||||
return job
|
||||
with exn ->
|
||||
Log.Error $"[Plume] getSimInfo: {exn.Message}"
|
||||
Log.Verbose $"[Plume] getSimInfo: %A{exn}"
|
||||
return None
|
||||
}
|
||||
|> Async.AwaitTask
|
||||
|
||||
let private getActivePlumeSims (ctx: HttpContext) (aId: Guid) =
|
||||
task {
|
||||
let user = getUserName ctx
|
||||
let id = ActorId user
|
||||
|
||||
try
|
||||
let proxy = ActorProxy.Create<IJobActor> (id, "PlumeActor")
|
||||
let! jobs = proxy.GetActiveJobs aId
|
||||
Log.Information ("[Plume] Active jobs for {username}@{aid}: {jobs}", user, aId, jobs.Length)
|
||||
return jobs
|
||||
with exn ->
|
||||
Log.Error $"[Plume] getActiveSimulations: %s{exn.Message}"
|
||||
Log.Verbose $"[Plume] getActiveSimulations: %A{exn}"
|
||||
return [||]
|
||||
}
|
||||
|> Async.AwaitTask
|
||||
|
||||
let plumeApi (ctx: HttpContext) : Api.Plume = {
|
||||
startPlume = runPlume ctx
|
||||
getActiveJobs = getActivePlumeSims ctx
|
||||
getSimInfo = getPlumeSimInfo ctx
|
||||
}
|
||||
|
||||
module Endpoints =
|
||||
let authEndpoints: HttpHandler =
|
||||
Remoting.createApi ()
|
||||
@@ -505,3 +579,9 @@ module Endpoints =
|
||||
|> Remoting.fromContext Handlers.inboxApi
|
||||
|> Remoting.withRouteBuilder Api.authorizedRouteBuilder
|
||||
|> Remoting.buildHttpHandler
|
||||
|
||||
let plumeEndpoints: HttpHandler =
|
||||
Remoting.createApi ()
|
||||
|> Remoting.fromContext Handlers.plumeApi
|
||||
|> Remoting.withRouteBuilder Api.authorizedRouteBuilder
|
||||
|> Remoting.buildHttpHandler
|
||||
@@ -425,6 +425,20 @@ module Handlers =
|
||||
|
||||
val inboxApi: ctx: Microsoft.AspNetCore.Http.HttpContext -> Inbox
|
||||
|
||||
val private runPlume:
|
||||
ctx: Microsoft.AspNetCore.Http.HttpContext ->
|
||||
plumeJob: Hipster.Actors.PlumeJob -> Async<Hipster.Job.JobInfo option>
|
||||
|
||||
val private getPlumeSimInfo:
|
||||
ctx: Microsoft.AspNetCore.Http.HttpContext ->
|
||||
jobId: int -> Async<Hipster.Job.JobInfo option>
|
||||
|
||||
val private getActivePlumeSims:
|
||||
ctx: Microsoft.AspNetCore.Http.HttpContext ->
|
||||
aId: System.Guid -> Async<Hipster.Job.JobInfo array>
|
||||
|
||||
val plumeApi: ctx: Microsoft.AspNetCore.Http.HttpContext -> Plume
|
||||
|
||||
module Endpoints =
|
||||
|
||||
val authEndpoints: Giraffe.Core.HttpHandler
|
||||
@@ -437,6 +451,8 @@ module Endpoints =
|
||||
|
||||
val inboxEndpoints: Giraffe.Core.HttpHandler
|
||||
|
||||
val plumeEndpoints: Giraffe.Core.HttpHandler
|
||||
|
||||
|
||||
module Atlantis.Events
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ type PlumeEnv = {
|
||||
member this.toJson() = [
|
||||
"PLUME_ID", Encode.guid this.aid
|
||||
"PLUME_NAME", Encode.string this.job.name
|
||||
"PLUME_LAT", Encode.tuple2 Encode.float Encode.float this.job.pos
|
||||
"PLUME_LNG", Encode.tuple2 Encode.float Encode.float this.job.pos
|
||||
"PLUME_LAT", Encode.float this.job.pos.Lat
|
||||
"PLUME_LNG", Encode.float this.job.pos.Long
|
||||
"PLUME_TEMP", Encode.float this.job.temp
|
||||
"PLUME_SALT", Encode.float this.job.salt
|
||||
"PLUME_DEPTH", Encode.float this.job.depth
|
||||
@@ -128,10 +128,10 @@ type PlumeActor
|
||||
let! allowed = fga.checkRelation tuple
|
||||
|
||||
if allowed then
|
||||
Log.Debug $"DriftersActor.StartDrifters user validated: {this.myId}"
|
||||
Log.Debug $"PlumeActor.StartPlume user validated: {this.myId}"
|
||||
|
||||
if this.validatePoints job.fvcom [ job.pos ] then
|
||||
Log.Debug $"DriftersActor.StartDrifters release points validated: {this.myId}"
|
||||
if this.validatePoints job.fvcom [ (job.pos.Lat, job.pos.Long) ] then
|
||||
Log.Debug $"PlumeActor.StartPlumes release points validated: {this.myId}"
|
||||
return! submitJob ()
|
||||
else
|
||||
let msg = "One or more release points outside boundary."
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
||||
<Deterministic>true</Deterministic>
|
||||
<NetCoreTargetingPackRoot>[UNDEFINED]</NetCoreTargetingPackRoot>
|
||||
<DisableImplicitLibraryPacksFolder>true</DisableImplicitLibraryPacksFolder>
|
||||
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
|
||||
<!-- https://www.gresearch.co.uk/blog/article/improve-nuget-restores-with-static-graph-evaluation/ -->
|
||||
<RestoreUseStaticGraphEvaluation>true</RestoreUseStaticGraphEvaluation>
|
||||
<Version>2.102.0</Version>
|
||||
<RootNamespace>Server</RootNamespace>
|
||||
<OtherFlags>$(OtherFlags) --sig:Atlantis.fsi --test:GraphBasedChecking --test:ParallelOptimization --test:ParallelIlxGen --strict-indentation+</OtherFlags>
|
||||
|
||||
@@ -54,6 +54,7 @@ export default defineConfig({
|
||||
},
|
||||
define: {
|
||||
global: {},
|
||||
'process.env': {},
|
||||
},
|
||||
build: {
|
||||
rollupOptions: {
|
||||
|
||||
@@ -61,3 +61,9 @@ module Api =
|
||||
markRead: Guid -> Async<int>
|
||||
getMessages: unit -> Async<InboxItem[]>
|
||||
}
|
||||
|
||||
type Plume = {
|
||||
startPlume: Hipster.Actors.PlumeJob -> Async<JobInfo option>
|
||||
getSimInfo: int -> Async<JobInfo option>
|
||||
getActiveJobs: Guid -> Async<JobInfo []>
|
||||
}
|
||||
|
||||
@@ -51,12 +51,19 @@ type PostdriftJob = {
|
||||
type PlumeJob = {
|
||||
name: string
|
||||
fvcom: Guid
|
||||
pos: float * float
|
||||
pos: LatLong
|
||||
// TODO: Functions, could be constants
|
||||
// saltfunc: unit
|
||||
// tempfunc: unit
|
||||
/// Example 4 and 0
|
||||
temp: float
|
||||
salt: float
|
||||
/// DOB Depth on Bottom
|
||||
depth: float
|
||||
/// Pipe Angle
|
||||
theta: float
|
||||
transport: float
|
||||
/// Pipe radius
|
||||
radius: float
|
||||
start: DateTime
|
||||
stop: DateTime
|
||||
@@ -65,7 +72,7 @@ type PlumeJob = {
|
||||
static member empty = {
|
||||
name = ""
|
||||
fvcom = System.Guid.Empty
|
||||
pos = 0.0, 0.0
|
||||
pos = {Lat = 0.0; Long = 0.0}
|
||||
temp = 0.0
|
||||
salt = 0.0
|
||||
depth = 0.0
|
||||
|
||||
@@ -12,14 +12,13 @@ type SlurmJobType =
|
||||
| DriftersJob
|
||||
| PlumeJob
|
||||
| UnknownJob
|
||||
with
|
||||
override x.ToString() =
|
||||
match x with
|
||||
| DriftersJob -> "Drifters"
|
||||
| PlumeJob -> "Plume"
|
||||
| UnknownJob -> "Unknown"
|
||||
static member FromString (s: string) =
|
||||
match s.ToLower() with
|
||||
static member FromString(s: string) =
|
||||
match s.ToLower () with
|
||||
| "drifters" -> DriftersJob
|
||||
| "plume" -> PlumeJob
|
||||
| _ -> UnknownJob
|
||||
@@ -28,14 +27,13 @@ type SlurmMessageType =
|
||||
| Status
|
||||
| Progress
|
||||
| Message
|
||||
with
|
||||
override x.ToString() =
|
||||
match x with
|
||||
| Status -> "status"
|
||||
| Progress -> "progress"
|
||||
| Message -> "message"
|
||||
static member FromString (s: string) =
|
||||
match s.ToLower() with
|
||||
static member FromString(s: string) =
|
||||
match s.ToLower () with
|
||||
| "status" -> Status
|
||||
| "progress" -> Progress
|
||||
| _ -> Message
|
||||
@@ -93,3 +91,6 @@ type DriftersPolicy =
|
||||
match x with
|
||||
| SubmitSedimentation v -> v
|
||||
| SubmitTransport v -> v
|
||||
|
||||
type LatLong = { Lat: float; Long: float }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user