refactor: Switch to nix ci and cleanup Lib

Adds packages.lock.json to git, so nix can use it to fetch deps.

Remove dotnet-tool fantomas, and adds it to nix-shell instead.
This commit is contained in:
2025-08-29 16:09:43 +02:00
parent 540985070b
commit 4cf2b12031
24 changed files with 3260 additions and 400 deletions

View File

@@ -1,13 +0,0 @@
{
"version": 1,
"isRoot": true,
"tools": {
"fantomas": {
"version": "7.0.2",
"commands": [
"fantomas"
],
"rollForward": false
}
}
}

11
.envrc
View File

@@ -1,12 +1,9 @@
#!/usr/bin/env bash
# the shebang is ignored, but nice for editors
watch_file npins/sources.json
#!/usr/bin/env bash
# the shebang is ignored, but nice for editors
watch_file "lon.lock"
# Load .env file if it exists
dotenv_if_exists
# Activate development shell
eval "$(lorri direnv)"
# Shell hooks
eval "$shellHook"
use nix

1
.gitignore vendored
View File

@@ -12,7 +12,6 @@ release.cmd
release.sh
*.orig
*.DotSettings.user
packages.lock.json
deploy/
dist/
build/

View File

@@ -3,7 +3,7 @@ variables:
include:
- project: oceanbox/gitlab-ci
ref: v4.1
ref: v4.2
file: DotnetDeployment.gitlab-ci.yml
inputs:
project-name: plume

View File

@@ -1,23 +1,20 @@
{
sources ? import ./npins,
system ? builtins.currentSystem,
pkgs ? import sources.nixpkgs {
inherit system;
config = { };
overlays = [ ];
},
sources ? import ./lon.nix,
pkgs ? import sources.nixpkgs { },
nix-utils ? import sources.nix-utils { },
env ? "Debug",
}:
let
# Common
pname = "Plume";
port = 7000;
version =
let
version' = builtins.readFile ./.version;
in
pkgs.lib.pipe version' [
(pkgs.lib.removePrefix "v")
(pkgs.lib.removeSuffix "\n")
];
deps = nix-utils.output.lib.nuget.deps;
# Usage: export NETRC="$(agenix -d netrc.age)" in `./nix/secrets`
netrcConfig = builtins.getEnv "NETRC";
# Packages
dotnet-sdk = pkgs.dotnetCorePackages.sdk_9_0;
dotnet-runtime = pkgs.dotnetCorePackages.runtime_9_0;
python-packages = with pkgs.python312Packages; [
@@ -28,61 +25,43 @@ let
];
in
rec {
default = pkgs.callPackage ./nix/package.nix {
packages.plume = pkgs.callPackage ./nix/package.nix {
inherit
deps
env
pname
version
dotnet-sdk
dotnet-runtime
netrcConfig
;
};
container = pkgs.dockerTools.buildLayeredImage {
containers.plume = pkgs.dockerTools.buildLayeredImage {
name = "Plume";
tag = version;
tag = "latest";
created = "now";
contents = [
default
pkgs.dockerTools.binSh
pkgs.dockerTools.caCertificates
pkgs.gcc
pkgs.curl
pkgs.glibc
pkgs.netcdf
packages.plume
python-packages
# Required libraries
pkgs.stdenv.cc.cc.lib
pkgs.dockerTools.caCertificates
]
++ pkgs.lib.optionals (env == "Debug") [
pkgs.busybox
pkgs.dockerTools.binSh
];
extraCommands = ''
# Create necessary directories
mkdir -p app
mkdir -p usr/lib/x86_64-linux-gnu
# Copy application files from dist/
cp -r ${./dist}/* app/
# Create symlink for libdl.so
for dir in usr/share/dotnet/shared/Microsoft.NETCore.App/9.*; do
if [ -d "$dir" ]; then
ln -s ${pkgs.glibc}/lib/libdl.so.2 $dir/libdl.so
fi
done
mkdir -p ./app
cp -r ${packages.plume}/lib/Plume/* ./app/
'';
config = {
cmd = [
"${default}/bin/Plume.Server"
];
cmd = [ "Plume.Server" ];
workingDir = "/app";
};
};
singularity = pkgs.singularity-tools.buildImage {
name = "plume-${version}";
name = "plume";
contents = [
# TODO: Which of these do we actually need?
default
packages.plume
pkgs.coreutils
pkgs.binutils
pkgs.cacert
@@ -92,10 +71,11 @@ rec {
];
# This is for the temporary build image; final output will be smaller
diskSize = 1024 * 20;
memSize = 1024 * 8;
diskSize = 4096; # MB
memSize = 2024; # MB
singularity = pkgs.apptainer;
# TODO: Launch diretly or via bash?
runScript = "#!${pkgs.stdenv.shell}\nexec /app/Plume \"$@\"";
runAsRoot = ''
@@ -110,9 +90,8 @@ rec {
shell = pkgs.mkShellNoCC {
packages = with pkgs; [
bun
apptainer
kustomize
kubernetes-helm
fantomas
fsautocomplete
dotnet-sdk
];

25
lon.lock Normal file
View File

@@ -0,0 +1,25 @@
{
"version": "1",
"sources": {
"nix-utils": {
"type": "Git",
"fetchType": "git",
"branch": "trunk",
"revision": "098f594425d2b9dde0657becad0f6498d074f8b3",
"url": "https://git.sr.ht/~mrtz/nix-utils",
"hash": "sha256-y++BijM+FRkKDhVrL7YXZQiJ0DNVMiRN7yHf6QIXBUI=",
"lastModified": 1756580332,
"submodules": false
},
"nixpkgs": {
"type": "GitHub",
"fetchType": "tarball",
"owner": "nixos",
"repo": "nixpkgs",
"branch": "nixpkgs-unstable",
"revision": "aca2499b79170038df0dbaec8bf2f689b506ad32",
"url": "https://github.com/nixos/nixpkgs/archive/aca2499b79170038df0dbaec8bf2f689b506ad32.tar.gz",
"hash": "sha256-tzo7YvAsGlzo4WiIHT0ooR59VHu+aKRQdHk7sIyoia4="
}
}
}

53
lon.nix Normal file
View File

@@ -0,0 +1,53 @@
# Generated by lon. Do not modify!
let
lock = builtins.fromJSON (builtins.readFile ./lon.lock);
# Override with a path defined in an environment variable. If no variable is
# set, the original path is used.
overrideFromEnv =
name: path:
let
replacement = builtins.getEnv "LON_OVERRIDE_${name}";
in
if replacement == "" then
path
else
# this turns the string into an actual Nix path (for both absolute and
# relative paths)
if builtins.substring 0 1 replacement == "/" then
/. + replacement
else
/. + builtins.getEnv "PWD" + "/${replacement}";
fetchSource =
args@{ fetchType, ... }:
if fetchType == "git" then
builtins.fetchGit (
{
url = args.url;
ref = args.branch;
rev = args.revision;
narHash = args.hash;
submodules = args.submodules;
}
// (
if args ? lastModified then
{
inherit (args) lastModified;
shallow = true;
}
else
{ }
)
)
else if fetchType == "tarball" then
builtins.fetchTarball {
url = args.url;
sha256 = args.hash;
}
else
builtins.throw "Unsupported source type ${fetchType}";
in
builtins.mapAttrs (name: args: overrideFromEnv name (fetchSource args)) lock.sources

View File

@@ -1,48 +1,67 @@
{
lib,
env,
pkgs,
deps,
pname,
version,
dotnet-sdk,
nix-gitignore,
dotnet-runtime,
dotnetCorePackages,
buildDotnetModule,
netrcConfig ? null,
}:
let
buildDotnetModule' = buildDotnetModule.override {
addNuGetDeps = dotnetCorePackages.addNuGetDeps.override {
fetchNupkg = dotnetCorePackages.fetchNupkg.override {
fetchurl =
{
url,
hash ? null,
sha256 ? null,
...
}:
let
sha = if (builtins.isNull hash) then sha256 else hash;
in
builtins.fetchurl {
inherit url;
sha256 = sha;
};
};
};
src = nix-gitignore.gitignoreSource [ ] ../.;
projectFile = "src/Server/Plume.Server.fsproj";
# NOTE(mrtz): Extra the version attribute from the fsharp project (XML)
versionMatch = builtins.match ".*<Version>([^<]+)</Version>.*" (
builtins.readFile (../. + "/${projectFile}")
);
version = builtins.head versionMatch;
# NOTE(mrtz): Gitlab Nuget Registry does not support groupwide fetches :/
packageSources = {
"Oceanbox.FvcomKit" = "https://gitlab.com/api/v4/projects/35569541/packages/nuget/download";
"ProjNet.FSharp" = "https://gitlab.com/api/v4/projects/35009572/packages/nuget/download";
"SDSLite.Oceanbox" = "https://gitlab.com/api/v4/projects/34025102/packages/nuget/download";
"Oceanbox.ServerPack" = "https://gitlab.com/api/v4/projects/67427353/packages/nuget/download";
"Oceanbox.DataAgent" = "https://gitlab.com/api/v4/projects/37541600/packages/nuget/download";
# TODO(mrtz): Move to poseidon
# "Drifters.Api" = "https://gitlab.com/api/v4/projects/37086336/packages/nuget/download";
# "Fable.SignalR.AspNetCore" = "https://gitlab.com/api/v4/projects/40255650/packages/nuget/download";
# "Fable.SignalR.Saturn" = "https://gitlab.com/api/v4/projects/40255650/packages/nuget/download";
# "Fable.SignalR.Shared" = "https://gitlab.com/api/v4/projects/40255650/packages/nuget/download";
# "Fable.SignalR" = "https://gitlab.com/api/v4/projects/40255650/packages/nuget/download";
# "Fable.SignalR.Elmish" = "https://gitlab.com/api/v4/projects/40255650/packages/nuget/download";
# "Fable.Lit" = "https://gitlab.com/api/v4/projects/61744837/packages/nuget/download";
# "Fable.Lit.Elmish" = "https://gitlab.com/api/v4/projects/61744837/packages/nuget/download";
# "Fable.Lit.React" = "https://gitlab.com/api/v4/projects/61744837/packages/nuget/download";
# "Fable.OpenLayers" = "https://gitlab.com/api/v4/projects/36202053/packages/nuget/download";
# "Matplotlib.ColorMaps" = "https://gitlab.com/api/v4/projects/36675671/packages/nuget/download";
};
in
buildDotnetModule' {
pkgs.dotnetCorePackages.buildDotnetModule rec {
inherit
src
pname
version
projectFile
dotnet-sdk
dotnet-runtime
;
name = "Plume";
src = lib.cleanSource ../.;
projectFile = "./src/Server/Plume.Server.fsproj";
nugetDeps = ./deps.json; # nix-build . -A default.fetch-deps && ./result nix/deps.json
runtimeDeps = [
pkgs.netcdf
];
nugetDeps = deps {
inherit
name
pkgs
netrcConfig
packageSources
;
lockfiles = [
../src/Server/packages.lock.json
];
};
buildType = env;
doCheck = true;
# postInstall = ''
# mkdir -p $out/app
# cp src/Server/plot_plume.py $out/app/
# '';
}

View File

@@ -1,146 +0,0 @@
/*
This file is provided under the MIT licence:
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
# Generated by npins. Do not modify; will be overwritten regularly
let
data = builtins.fromJSON (builtins.readFile ./sources.json);
version = data.version;
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
range =
first: last: if first > last then [ ] else builtins.genList (n: first + n) (last - first + 1);
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
concatMapStrings = f: list: concatStrings (map f list);
concatStrings = builtins.concatStringsSep "";
# If the environment variable NPINS_OVERRIDE_${name} is set, then use
# the path directly as opposed to the fetched source.
# (Taken from Niv for compatibility)
mayOverride =
name: path:
let
envVarName = "NPINS_OVERRIDE_${saneName}";
saneName = stringAsChars (c: if (builtins.match "[a-zA-Z0-9]" c) == null then "_" else c) name;
ersatz = builtins.getEnv envVarName;
in
if ersatz == "" then
path
else
# this turns the string into an actual Nix path (for both absolute and
# relative paths)
builtins.trace "Overriding path of \"${name}\" with \"${ersatz}\" due to set \"${envVarName}\"" (
if builtins.substring 0 1 ersatz == "/" then
/. + ersatz
else
/. + builtins.getEnv "PWD" + "/${ersatz}"
);
mkSource =
name: spec:
assert spec ? type;
let
path =
if spec.type == "Git" then
mkGitSource spec
else if spec.type == "GitRelease" then
mkGitSource spec
else if spec.type == "PyPi" then
mkPyPiSource spec
else if spec.type == "Channel" then
mkChannelSource spec
else if spec.type == "Tarball" then
mkTarballSource spec
else
builtins.throw "Unknown source type ${spec.type}";
in
spec // { outPath = mayOverride name path; };
mkGitSource =
{
repository,
revision,
url ? null,
submodules,
hash,
branch ? null,
...
}:
assert repository ? type;
# At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository
# In the latter case, there we will always be an url to the tarball
if url != null && !submodules then
builtins.fetchTarball {
inherit url;
sha256 = hash; # FIXME: check nix version & use SRI hashes
}
else
let
url =
if repository.type == "Git" then
repository.url
else if repository.type == "GitHub" then
"https://github.com/${repository.owner}/${repository.repo}.git"
else if repository.type == "GitLab" then
"${repository.server}/${repository.repo_path}.git"
else
throw "Unrecognized repository type ${repository.type}";
urlToName =
url: rev:
let
matched = builtins.match "^.*/([^/]*)(\\.git)?$" url;
short = builtins.substring 0 7 rev;
appendShort = if (builtins.match "[a-f0-9]*" rev) != null then "-${short}" else "";
in
"${if matched == null then "source" else builtins.head matched}${appendShort}";
name = urlToName url revision;
in
builtins.fetchGit {
rev = revision;
inherit name;
# hash = hash;
inherit url submodules;
};
mkPyPiSource =
{ url, hash, ... }:
builtins.fetchurl {
inherit url;
sha256 = hash;
};
mkChannelSource =
{ url, hash, ... }:
builtins.fetchTarball {
inherit url;
sha256 = hash;
};
mkTarballSource =
{
url,
locked_url ? url,
hash,
...
}:
builtins.fetchTarball {
url = locked_url;
sha256 = hash;
};
in
if version == 5 then
builtins.mapAttrs mkSource data.pins
else
throw "Unsupported format version ${toString version} in sources.json. Try running `npins upgrade`"

View File

@@ -1,18 +0,0 @@
{
"pins": {
"nixpkgs": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "nixos",
"repo": "nixpkgs"
},
"branch": "nixpkgs-unstable",
"submodules": false,
"revision": "f72be405a10668b8b00937b452f2145244103ebc",
"url": "https://github.com/nixos/nixpkgs/archive/f72be405a10668b8b00937b452f2145244103ebc.tar.gz",
"hash": "0m1vnvngpxrawsgg306c9sdhbzsiigjgb03yfbdpa2fsb1fs0zm9"
}
},
"version": 5
}

View File

@@ -1,5 +1 @@
{
sources ? import ./npins,
system ? builtins.currentSystem,
}:
(import ./. { inherit sources system; }).shell
(import ./. { }).shell

View File

@@ -195,20 +195,20 @@ let main argv =
let dischargeRho =
let ts = Array.zip dischargeTemp dischargeSalt
ts
|> Array.map (fun (t, s) -> eq_of_state t s (abs z0))
|> Array.map (fun (t, s) -> dens t s (abs z0))
let rhoa =
ambientarray
|> Array.map (fun a ->
let ta, sa = ambientWmass a.z a.temp a.salt z0
eq_of_state ta sa (abs z0))
dens ta sa (abs z0))
let up = upward theta0 rhoa dischargeRho
let buoyancyTermination =
let rhoa =
ambientarray
|> Array.map (fun a ->
let ta, sa = ambientWmass a.z a.temp a.salt z0
eq_of_state ta sa (abs z0))
dens ta sa (abs z0))
rhoa
|> Array.mapi (fun i _ ->
if up[i] && (rhoa[i] - dischargeRho[i] > 0.0) then
@@ -235,7 +235,7 @@ let main argv =
let ds0 = (ambient.zeta + h) / 100.0
let _, va0 = ambientWmass ambient.z ambient.v ambient.v z0
let Ta, Sa = ambientWmass ambient.z ambient.temp ambient.salt z0
let rhoa = eq_of_state Ta Sa (abs z0)
let rhoa = dens Ta Sa (abs z0)
let rho = dischargeRho[i]
let rg = 9.81 * (rhoa - rho) / rhoref
let w0 = U / (Math.PI * R0 * R0) //Initial plume velocity
@@ -289,4 +289,4 @@ let main argv =
writeFullPlume2NetCDF plume_fname solution dilution
|> ignore
0
0

View File

@@ -17,7 +17,7 @@
<PackageReference Include="Argu" Version="6.2.5"/>
<PackageReference Include="FSharpPlus" Version="1.7.0"/>
<PackageReference Include="Oceanbox.FvcomKit" Version="5.12.0"/>
<PackageReference Include="SDSLite-o" Version="2.7.2"/>
<PackageReference Include="SDSLite.Oceanbox" Version="2.7.2"/>
<PackageReference Include="Serilog" Version="4.2.0"/>
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0"/>
<PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0"/>

View File

@@ -0,0 +1,682 @@
{
"version": 1,
"dependencies": {
"net9.0": {
"Argu": {
"type": "Direct",
"requested": "[6.2.5, )",
"resolved": "6.2.5",
"contentHash": "68vfXYZCcyTFtC11Z26+S4cSyEPiUJ8PL+iGuYpIbCsH+TN27bIxV/QczHXus/+iSCOfjMJsBffBC90mlzKXrw==",
"dependencies": {
"FSharp.Core": "6.0.0",
"System.Configuration.ConfigurationManager": "4.4.0"
}
},
"FSharp.Core": {
"type": "Direct",
"requested": "[9.0.300, )",
"resolved": "9.0.300",
"contentHash": "TVt2J7RCE1KCS2IaONF+p8/KIZ1eHNbW+7qmKF6hGoD4tXl+o07ja1mPtFjMqRa5uHMFaTrGTPn/m945WnDLiQ=="
},
"FSharpPlus": {
"type": "Direct",
"requested": "[1.7.0, )",
"resolved": "1.7.0",
"contentHash": "9+PXT3nG7K5bzgYOzxgwZu5ij25BH7OtMkMJUrWkf+HcfbvsEGCvIf3InF8MCvJ5lO02NfGb9fC8slLEytqw0Q==",
"dependencies": {
"FSharp.Core": "6.0.6"
}
},
"Oceanbox.FvcomKit": {
"type": "Direct",
"requested": "[5.12.0, )",
"resolved": "5.12.0",
"contentHash": "78qkFpO2819Ddg6hYqRKXwCj2/ZBqrNKJ3536Q9R+4lx7dfMox97VPcpHviPRb/NsFG1M60TaYpm2DxuZclPaA==",
"dependencies": {
"FSharp.Core": "9.0.201",
"FSharp.Data": "6.4.1",
"FSharpPlus": "1.7.0",
"FsPickler": "5.3.2",
"KDTree": "1.4.1",
"MathNet.Numerics.FSharp": "5.0.0",
"MessagePack": "3.1.3",
"ProjNet.FSharp": "5.2.0",
"SDSlite.Oceanbox": "2.7.3",
"Serilog": "4.2.0",
"Serilog.Sinks.Console": "6.0.0",
"Serilog.Sinks.Seq": "9.0.0",
"Thoth.Json.Net": "12.0.0"
}
},
"SDSLite.Oceanbox": {
"type": "Direct",
"requested": "[2.7.2, )",
"resolved": "2.7.3",
"contentHash": "tmTPsEUmQhwaCzHwuSw7he2FfjcVpZ/Sy2ewfTwm1IKnwOZazKouTS5t4LNUpaGtjK1o/gdfz1b+0KxXnUl97g==",
"dependencies": {
"DynamicInterop": "0.9.1"
}
},
"Serilog": {
"type": "Direct",
"requested": "[4.2.0, )",
"resolved": "4.2.0",
"contentHash": "gmoWVOvKgbME8TYR+gwMf7osROiWAURterc6Rt2dQyX7wtjZYpqFiA/pY6ztjGQKKV62GGCyOcmtP1UKMHgSmA=="
},
"Serilog.Sinks.Console": {
"type": "Direct",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "fQGWqVMClCP2yEyTXPIinSr5c+CBGUvBybPxjAGcf7ctDhadFhrQw03Mv8rJ07/wR5PDfFjewf2LimvXCDzpbA==",
"dependencies": {
"Serilog": "4.0.0"
}
},
"Serilog.Sinks.Seq": {
"type": "Direct",
"requested": "[9.0.0, )",
"resolved": "9.0.0",
"contentHash": "aNU8A0K322q7+voPNmp1/qNPH+9QK8xvM1p72sMmCG0wGlshFzmtDW9QnVSoSYCj0MgQKcMOlgooovtBhRlNHw==",
"dependencies": {
"Serilog": "4.2.0",
"Serilog.Sinks.File": "6.0.0"
}
},
"Thoth.Json.Net": {
"type": "Direct",
"requested": "[12.0.0, )",
"resolved": "12.0.0",
"contentHash": "n2YyONYdWCFS4Pu7wrqgV/l5tPuN+t3gxEfs/2RwqCiQkRnbgKs9dK61zHeZS5YganAoFbxLSwbaNL7SvSrS9g==",
"dependencies": {
"FSharp.Core": "4.7.2",
"Fable.Core": "3.1.6",
"Newtonsoft.Json": "13.0.1"
}
},
"Dapr.Actors": {
"type": "Transitive",
"resolved": "1.14.0",
"contentHash": "CUds5JTUGE8xJTcMw6fbSGbnJm7p7TNe7ZHymvSJb0apowFZRZQFm72rqSf3791nQtTdyioVYDi6cZGhUgrkWg==",
"dependencies": {
"Dapr.Client": "1.14.0",
"Microsoft.Extensions.Logging.Abstractions": "3.1.0"
}
},
"Dapr.Client": {
"type": "Transitive",
"resolved": "1.14.0",
"contentHash": "gvoxV+nKOLHTeDx+WLwV79GJ/ldJuCsRrFmyxq4NodIeE9XfEi5z08Nc+EAwn1NibD3Wi4B0CPZpm+El+UKFCA==",
"dependencies": {
"Google.Api.CommonProtos": "2.2.0",
"Google.Protobuf": "3.15.0",
"Grpc.Net.Client": "2.52.0"
}
},
"DynamicInterop": {
"type": "Transitive",
"resolved": "0.9.1",
"contentHash": "n21+Hd+tceX8lgaOosPV+Pne+YqnZUd5RLW3OhnsVxWRzYXiAIAKmKweHIePYeY+fmcn3N5tjkJyQUccFuL3bg=="
},
"Fable.Core": {
"type": "Transitive",
"resolved": "3.1.6",
"contentHash": "w6M1F0zoLk4kTFc1Lx6x1Ft6BD3QwRe0eaLiinAqbjVkcF+iK+NiXGJO+a6q9RAF9NCg0vI48Xku7aNeqG4JVw==",
"dependencies": {
"FSharp.Core": "4.7.1"
}
},
"Fable.Remoting.DotnetClient": {
"type": "Transitive",
"resolved": "3.35.0",
"contentHash": "xaxt9nKfqIWh30+cOrG9GNl06+7yTy5htrcF5eXsZ7QJLLy7T5ZD3xeGpAb0xbh+TZTVQGluSQzxh/opIZm2PQ==",
"dependencies": {
"FSharp.Core": "6.0.0",
"Fable.Remoting.Json": "2.25.0",
"Fable.Remoting.MsgPack": "1.24.0"
}
},
"Fable.Remoting.Json": {
"type": "Transitive",
"resolved": "2.25.0",
"contentHash": "ycmxT5L7jUKLkSJ4uti+WiX1OU50UYhLLiFQwJpQzwPWpNbSXowPjUtGycl8G5429edzeIHGW/77hUlIAufiAg==",
"dependencies": {
"FSharp.Core": "6.0.0",
"Newtonsoft.Json": "13.0.3"
}
},
"Fable.Remoting.MsgPack": {
"type": "Transitive",
"resolved": "1.24.0",
"contentHash": "Bn3nzoZbib6lPk70bIJumEu2wFMxciB4o8k0Zw6tRfAOpNKvUsi79OOll2nW3FU1P6MVBepT43m+R8JvfYnNiw==",
"dependencies": {
"FSharp.Core": "4.7.2"
}
},
"FSharp.Data": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "P/ShAsNsuKrV9cpK7Mb/fSJ/kpinjOnVGRDXDzi/dYECS/lmlDrAvNVlodPbqCo5hIXvMMkKMc5C4f8ULLW7JQ==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Csv.Core": "6.4.1",
"FSharp.Data.Html.Core": "6.4.1",
"FSharp.Data.Http": "6.4.1",
"FSharp.Data.Json.Core": "6.4.1",
"FSharp.Data.Runtime.Utilities": "6.4.1",
"FSharp.Data.WorldBank.Core": "6.4.1",
"FSharp.Data.Xml.Core": "6.4.1"
}
},
"FSharp.Data.Csv.Core": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "/RmEq3HSafm4RPAPATDsDTY0aAkJ8ioDDJ0Qf/NuJW7c7/CC3xeU0XC3sHmDkp9v98aeQOSJdTa+NJrMTHzT7g==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Runtime.Utilities": "6.4.1"
}
},
"FSharp.Data.Html.Core": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "/T7k5FkR8nRJ3fZ8Bfaf/c9eda2ru0xCIbM+i2Qt/PgtHp2d1ZmDvQIWbYfDLWVcKjRVu/YpRYOw/2fX0RT8ew==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Csv.Core": "6.4.1",
"FSharp.Data.Runtime.Utilities": "6.4.1"
}
},
"FSharp.Data.Http": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "7KxlBNwnSIiR1nsPal2ofmgU4Rag8dyDJ+cziW1L9Z+iA55aXeXO/RapQDnyVIwl/Fbm1scGAuSTWP36JNpQFg==",
"dependencies": {
"FSharp.Core": "6.0.1"
}
},
"FSharp.Data.Json.Core": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "mUyqLZiI0XPEiE9FIJLJ3Ndof4hEc2paW049Cw224knmp/b0brMwznLaOqtlmCr49QCELj0tcT0ZCKfb2cFS0g==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Http": "6.4.1",
"FSharp.Data.Runtime.Utilities": "6.4.1"
}
},
"FSharp.Data.Runtime.Utilities": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "pG4X3QWilYMF3qjZWpod6QgO38uiYUM3/bkEsEyT69E3zAlFQFO9uUy0tqEhDznHvNx4QtZaScUM+06r94HHnQ==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Http": "6.4.1"
}
},
"FSharp.Data.WorldBank.Core": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "opXr3YMArDQCiA1nkEnhSf1s6E0QsotO0VZ5nvQcMXmDuDU4IA1i1DlYp4QVmCXRKj5EHPKMwZkTVNeQDuZ5Bg==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Http": "6.4.1",
"FSharp.Data.Json.Core": "6.4.1",
"FSharp.Data.Runtime.Utilities": "6.4.1"
}
},
"FSharp.Data.Xml.Core": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "TprbqQu+DdrR6Kl5biNCAsM8yeQs+pgqRpQYDorbbFIroGw1LBMoX+1iiigJcK89TwJAtiEzVrZCQzHvCDrCbA==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Http": "6.4.1",
"FSharp.Data.Json.Core": "6.4.1",
"FSharp.Data.Runtime.Utilities": "6.4.1"
}
},
"FsPickler": {
"type": "Transitive",
"resolved": "5.3.2",
"contentHash": "LFtxXpQNor8az1ez3rN9oz2cqf/06i9yTrPyJ9R83qLEpFAU7Of0WL2hoSXzLHer4lh+6mO1NV4VQFiBzNRtjw==",
"dependencies": {
"FSharp.Core": "4.3.2",
"System.Reflection.Emit.Lightweight": "4.3.0"
}
},
"Google.Api.CommonProtos": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "mxXNYkHYL7T6NG8cdbodxpixQZfpozBkZj2g+jGCB/sO13RqfUvh9YHd8G2QI5HP24brl+nILJReC3/gzgsrrg==",
"dependencies": {
"Google.Protobuf": "[3.13.0, 4.0.0)"
}
},
"Google.Protobuf": {
"type": "Transitive",
"resolved": "3.15.0",
"contentHash": "2na7LsYrtxkEQaVCNjaafBzVu4IJ4U4+dwwBazK8oUkpDiIFjO0GkyTc+IbStx4xNVAV4EqHl+qp2uegFgFiiA==",
"dependencies": {
"System.Memory": "4.5.3",
"System.Runtime.CompilerServices.Unsafe": "4.5.2"
}
},
"Grpc.Core.Api": {
"type": "Transitive",
"resolved": "2.52.0",
"contentHash": "SQiPyBczG4vKPmI6Fd+O58GcxxDSFr6nfRAJuBDUNj+PgdokhjWJvZE/La1c09AkL2FVm/jrDloG89nkzmVF7A==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"Grpc.Net.Client": {
"type": "Transitive",
"resolved": "2.52.0",
"contentHash": "hWVH9g/Nnjz40ni//2S8UIOyEmhueQREoZIkD0zKHEPqLxXcNlbp4eebXIOicZtkwDSx0TFz9NpkbecEDn6rBw==",
"dependencies": {
"Grpc.Net.Common": "2.52.0",
"Microsoft.Extensions.Logging.Abstractions": "3.0.3"
}
},
"Grpc.Net.Common": {
"type": "Transitive",
"resolved": "2.52.0",
"contentHash": "di9qzpdx525IxumZdYmu6sG2y/gXJyYeZ1ruFUzB9BJ1nj4kU1/dTAioNCMt1VLRvNVDqh8S8B1oBdKhHJ4xRg==",
"dependencies": {
"Grpc.Core.Api": "2.52.0"
}
},
"KdTree": {
"type": "Transitive",
"resolved": "1.4.1",
"contentHash": "yWbb35v/V9y88SLLMUPTlAN3pQEoPhDfZf9PApFnlU4kLtwVQ75U9vW5mW4/alQnLBuLKWBKcy4W5xK95mYsuA=="
},
"MathNet.Numerics": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "pg1W2VwaEQMAiTpGK840hZgzavnqjlCMTVSbtVCXVyT+7AX4mc1o89SPv4TBlAjhgCOo9c1Y+jZ5m3ti2YgGgA=="
},
"MathNet.Numerics.FSharp": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "lKYhd68fReW5odX/q+Uzxw3357Duq3zmvkYvnZVqqcc2r/EmrYGDoOdUGuHnhfr8yj9V34js5gQH/7IWcxZJxg==",
"dependencies": {
"FSharp.Core": "6.0.2",
"MathNet.Numerics": "5.0.0"
}
},
"MessagePack": {
"type": "Transitive",
"resolved": "3.1.3",
"contentHash": "UiNv3fknvPzh5W+S0VV96R17RBZQQU71qgmsMnjjRZU2rtQM/XcTnOB+klT2dA6T1mxjnNKYrEm164AoXvGmYg==",
"dependencies": {
"MessagePack.Annotations": "3.1.3",
"MessagePackAnalyzer": "3.1.3",
"Microsoft.NET.StringTools": "17.11.4"
}
},
"MessagePack.Annotations": {
"type": "Transitive",
"resolved": "3.1.3",
"contentHash": "XTy4njgTAf6UVBKFj7c7ad5R0WVKbvAgkbYZy4f00kplzX2T3VOQ34AUke/Vn/QgQZ7ETdd34/IDWS3KBInSGA=="
},
"MessagePackAnalyzer": {
"type": "Transitive",
"resolved": "3.1.3",
"contentHash": "19u1oVNv2brCs5F/jma8O8CnsKMMpYwNqD0CAEDEzvqwDTAhqC9r7xHZP4stPb3APs/ryO/zVn7LvjoEHfvs7Q=="
},
"Microsoft.EntityFrameworkCore": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "wpG+nfnfDAw87R3ovAsUmjr3MZ4tYXf6bFqEPVAIKE6IfPml3DS//iX0DBnf8kWn5ZHSO5oi1m4d/Jf+1LifJQ==",
"dependencies": {
"Microsoft.EntityFrameworkCore.Abstractions": "9.0.0",
"Microsoft.EntityFrameworkCore.Analyzers": "9.0.0",
"Microsoft.Extensions.Caching.Memory": "9.0.0",
"Microsoft.Extensions.Logging": "9.0.0"
}
},
"Microsoft.EntityFrameworkCore.Abstractions": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "fnmifFL8KaA4ZNLCVgfjCWhZUFxkrDInx5hR4qG7Q8IEaSiy/6VOSRFyx55oH7MV4y7wM3J3EE90nSpcVBI44Q=="
},
"Microsoft.EntityFrameworkCore.Analyzers": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "Qje+DzXJOKiXF72SL0XxNlDtTkvWWvmwknuZtFahY5hIQpRKO59qnGuERIQ3qlzuq5x4bAJ8WMbgU5DLhBgeOQ=="
},
"Microsoft.EntityFrameworkCore.Relational": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "j+msw6fWgAE9M3Q/5B9Uhv7pdAdAQUvFPJAiBJmoy+OXvehVbfbCE8ftMAa51Uo2ZeiqVnHShhnv4Y4UJJmUzA==",
"dependencies": {
"Microsoft.EntityFrameworkCore": "9.0.0",
"Microsoft.Extensions.Caching.Memory": "9.0.0",
"Microsoft.Extensions.Configuration.Abstractions": "9.0.0",
"Microsoft.Extensions.Logging": "9.0.0"
}
},
"Microsoft.Extensions.Caching.Abstractions": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "FPWZAa9c0H4dvOj351iR1jkUIs4u9ykL4Bm592yhjDyO5lCoWd+TMAHx2EMbarzUvCvgjWjJIoC6//Q9kH6YhA==",
"dependencies": {
"Microsoft.Extensions.Primitives": "9.0.0"
}
},
"Microsoft.Extensions.Caching.Memory": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "zbnPX/JQ0pETRSUG9fNPBvpIq42Aufvs15gGYyNIMhCun9yhmWihz0WgsI7bSDPjxWTKBf8oX/zv6v2uZ3W9OQ==",
"dependencies": {
"Microsoft.Extensions.Caching.Abstractions": "9.0.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
"Microsoft.Extensions.Logging.Abstractions": "9.0.0",
"Microsoft.Extensions.Options": "9.0.0",
"Microsoft.Extensions.Primitives": "9.0.0"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "lqvd7W3FGKUO1+ZoUEMaZ5XDJeWvjpy2/M/ptCGz3tXLD4HWVaSzjufsAsjemasBEg+2SxXVtYVvGt5r2nKDlg==",
"dependencies": {
"Microsoft.Extensions.Primitives": "9.0.0"
}
},
"Microsoft.Extensions.DependencyInjection": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "MCPrg7v3QgNMr0vX4vzRXvkNGgLg8vKWX0nKCWUxu2uPyMsaRgiRc1tHBnbTcfJMhMKj2slE/j2M9oGkd25DNw==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "+6f2qv2a3dLwd5w6JanPIPs47CxRbnk+ZocMJUhv9NxP88VlOcJYZs9jY+MYSjxvady08bUZn6qgiNh7DadGgg=="
},
"Microsoft.Extensions.Logging": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "crjWyORoug0kK7RSNJBTeSE6VX8IQgLf3nUpTB9m62bPXp/tzbnOsnbe8TXEG0AASNaKZddnpHKw7fET8E++Pg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.0",
"Microsoft.Extensions.Logging.Abstractions": "9.0.0",
"Microsoft.Extensions.Options": "9.0.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "g0UfujELzlLbHoVG8kPKVBaW470Ewi+jnptGS9KUi6jcb+k2StujtK3m26DFSGGwQ/+bVgZfsWqNzlP6YOejvw==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0"
}
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "y2146b3jrPI3Q0lokKXdKLpmXqakYbDIPDV6r3M8SqvSf45WwOTzkyfDpxnZXJsJQEpAsAqjUq5Pu8RCJMjubg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
"Microsoft.Extensions.Primitives": "9.0.0"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "N3qEBzmLMYiASUlKxxFIISP4AiwuPTHF5uCh+2CWSwwzAJiIYx0kBJsS30cp1nvhSySFAVi30jecD307jV+8Kg=="
},
"Microsoft.NET.StringTools": {
"type": "Transitive",
"resolved": "17.11.4",
"contentHash": "mudqUHhNpeqIdJoUx2YDWZO/I9uEDYVowan89R6wsomfnUJQk6HteoQTlNjZDixhT2B4IXMkMtgZtoceIjLRmA=="
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
"resolved": "1.1.0",
"contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
},
"Microsoft.NETCore.Targets": {
"type": "Transitive",
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
"NetTopologySuite": {
"type": "Transitive",
"resolved": "2.5.0",
"contentHash": "5/+2O2ADomEdUn09mlSigACdqvAf0m/pVPGtIPEPQWnyrVykYY0NlfXLIdkMgi41kvH9kNrPqYaFBTZtHYH7Xw==",
"dependencies": {
"System.Memory": "4.5.4"
}
},
"NetTopologySuite.IO.PostGis": {
"type": "Transitive",
"resolved": "2.1.0",
"contentHash": "3W8XTFz8iP6GQ5jDXK1/LANHiU+988k1kmmuPWNKcJLpmSg6CvFpbTpz+s4+LBzkAp64wHGOldSlkSuzYfrIKA==",
"dependencies": {
"NetTopologySuite": "[2.0.0, 3.0.0-A)"
}
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"Npgsql": {
"type": "Transitive",
"resolved": "9.0.2",
"contentHash": "hCbO8box7i/XXiTFqCJ3GoowyLqx3JXxyrbOJ6om7dr+eAknvBNhhUHeJVGAQo44sySZTfdVffp4BrtPeLZOAA==",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "8.0.2"
}
},
"Npgsql.EntityFrameworkCore.PostgreSQL": {
"type": "Transitive",
"resolved": "9.0.2",
"contentHash": "cYdOGplIvr9KgsG8nJ8xnzBTImeircbgetlzS1OmepS5dAQW6PuGpVrLOKBNEwEvGYZPsV8037X5vZ/Dmpwz7Q==",
"dependencies": {
"Microsoft.EntityFrameworkCore": "[9.0.0, 10.0.0)",
"Microsoft.EntityFrameworkCore.Relational": "[9.0.0, 10.0.0)",
"Npgsql": "9.0.2"
}
},
"Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite": {
"type": "Transitive",
"resolved": "9.0.2",
"contentHash": "D38a3+CF8dO7nPiwt/NtQ/sLbrzZpX910jaaGiETdeS18KI0yMYEFvWWO5I/JBjVXLVnruodsukIUupdoD4fRA==",
"dependencies": {
"Npgsql.EntityFrameworkCore.PostgreSQL": "9.0.2",
"Npgsql.NetTopologySuite": "9.0.2"
}
},
"Npgsql.NetTopologySuite": {
"type": "Transitive",
"resolved": "9.0.2",
"contentHash": "DCwN+IVl3yWfOftPe0UBUUDOqa877ca+z+xSDQVi5ShDnOIAipaaYZlzDYm8Nga8hcxx6UrIQuImFnXv8fDpwg==",
"dependencies": {
"NetTopologySuite": "2.5.0",
"NetTopologySuite.IO.PostGIS": "2.1.0",
"Npgsql": "9.0.2"
}
},
"Oceanbox.DataAgent": {
"type": "Transitive",
"resolved": "6.23.1",
"contentHash": "GT2YFD57o4LGcpnTHkgUvvKtncvm7FKE2/KGuAqcNl87/qJyc41L2+sMot1WUABBUEBZ86zZ4h3DnOa2wi67JQ==",
"dependencies": {
"Dapr.Actors": "1.14.0",
"FSharp.Core": "9.0.100",
"FSharp.Data": "6.4.0",
"FSharpPlus": "1.7.0",
"Fable.Remoting.DotnetClient": "3.35.0",
"Microsoft.EntityFrameworkCore": "9.0.0",
"Microsoft.EntityFrameworkCore.Relational": "9.0.0",
"NetTopologySuite": "2.5.0",
"Npgsql.EntityFrameworkCore.PostgreSQL": "9.0.2",
"Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite": "9.0.2",
"Oceanbox.FvcomKit": "5.6.0",
"SDSLite.Oceanbox": "2.7.3",
"Serilog.Sinks.Console": "6.0.0",
"Thoth.Json.Net": "12.0.0"
}
},
"ProjNET": {
"type": "Transitive",
"resolved": "2.0.0",
"contentHash": "iMJG8qpGJ8SjFrB044O8wgo0raAWCdG1Bvly0mmVcjzsrexDHhC+dUct6Wb1YwQtupMBjSTWq7Fn00YeNErprA==",
"dependencies": {
"System.Memory": "4.5.3",
"System.Numerics.Vectors": "4.5.0"
}
},
"ProjNet.FSharp": {
"type": "Transitive",
"resolved": "5.2.0",
"contentHash": "sYSePg/0sVo16Fk3r7okVSga6i9GAN0kkjt1haEXVw25SF8A4S3Gcpf5+6lgknBGdYiZBmJ+3S6v5g1WSSCp2g==",
"dependencies": {
"FSharp.Core": "8.0.100",
"FSharp.Data": "6.3.0",
"FSharpPlus": "1.5.0",
"ProjNet": "2.0.0"
}
},
"Serilog.Sinks.File": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "lxjg89Y8gJMmFxVkbZ+qDgjl+T4yC5F7WSLTvA+5q0R04tfKVLRL/EHpYoJ/MEQd2EeCKDuylBIVnAYMotmh2A==",
"dependencies": {
"Serilog": "4.0.0"
}
},
"System.Configuration.ConfigurationManager": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "gWwQv/Ug1qWJmHCmN17nAbxJYmQBM/E94QxKLksvUiiKB1Ld3Sc/eK1lgmbSjDFxkQhVuayI/cGFZhpBSodLrg==",
"dependencies": {
"System.Security.Cryptography.ProtectedData": "4.4.0"
}
},
"System.IO": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.4",
"contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw=="
},
"System.Numerics.Vectors": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
},
"System.Reflection": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Emit.ILGeneration": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==",
"dependencies": {
"System.Reflection": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Emit.Lightweight": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==",
"dependencies": {
"System.Reflection": "4.3.0",
"System.Reflection.Emit.ILGeneration": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "4.5.2",
"contentHash": "wprSFgext8cwqymChhrBLu62LMg/1u92bU+VOwyfBimSPVFXtsNqEWC92Pf9ofzJFlk4IHmJA75EDJn1b2goAQ=="
},
"System.Security.Cryptography.ProtectedData": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog=="
},
"System.Text.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Threading.Tasks": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"plume.lib": {
"type": "Project",
"dependencies": {
"FSharp.Core": "[9.0.300, )",
"FSharpPlus": "[1.7.0, )",
"Oceanbox.DataAgent": "[6.23.1, )",
"Oceanbox.FvcomKit": "[5.12.0, )",
"SDSLite.Oceanbox": "[2.7.2, )",
"Serilog": "[4.2.0, )",
"Serilog.Sinks.Console": "[6.0.0, )",
"Thoth.Json.Net": "[12.0.0, )"
}
}
}
}
}

View File

@@ -2,24 +2,21 @@ module Plume.Lib.Input
open System
let makeConstTemp (time: float[]) (T0: float) = Array.create time.Length T0
let makeConstTemp (time: float array) (T0: float) = Array.create time.Length T0
let makeSineTemp (time: float[]) (amplitude: float) (phase: float) (offset: float) =
time
|> Array.map (fun ti -> (amplitude * (sin (ti + phase)) + offset))
let makeSineTemp (time: float array) (amplitude: float) (phase: float) (offset: float) =
time |> Array.map (fun ti -> (amplitude * (sin (ti + phase)) + offset))
let makeTempKalvehagen (time: float[]) =
let makeTempKalvehagen (time: float array) =
let amplitude = 6.
let phase = -1028.45
let offset = 10.
let t =
time
|> Array.map (fun ti -> 2. * Math.PI * ti / 365.)
let t = time |> Array.map (fun ti -> 2. * Math.PI * ti / 365.)
makeSineTemp t amplitude phase offset
let makeInputTemp (case: string) (time: float[]) (T0: float) =
let makeInputTemp (case: string) (time: float array) (T0: float) =
match case with
| "const" -> makeConstTemp time T0
| "Kalvehagen" -> makeTempKalvehagen time
| _ -> makeConstTemp time T0
| _ -> makeConstTemp time T0

View File

@@ -5,6 +5,7 @@ open FSharpPlus.Data.NonEmptySeq
open Tools
open Serilog
[<Struct>]
type AmbientData = {
temp: float array
salt: float array
@@ -16,6 +17,7 @@ type AmbientData = {
time: float
}
[<Struct>]
type ModelSolution = {
temp: float array
salt: float array
@@ -30,8 +32,11 @@ type ModelSolution = {
time: float
}
let eq_of_state (temp: float) (salt: float) (pres: float) =
/// Compute density of seawater from salinity, temperature, and pressure
let dens (temp: float) (salt: float) (pres: float) =
// From Bjørn Aadlandsvik https://github.com/bjornaa/seawater/blob/master/seawater/density.py
/// Density of seawater at zero pressure
let dens0 (salt: float) (temp: float) =
// --- Define constants ---
let a0 = 999.842594
@@ -53,72 +58,69 @@ let eq_of_state (temp: float) (salt: float) (pres: float) =
let d0 = 4.8314e-4
// # --- Computations ---
// # Density of pure water
// --- Computations ---
// Density of pure water
let SMOW = a0 + (a1 + (a2 + (a3 + (a4 + a5 * temp) * temp) * temp) * temp) * temp
// # More temperature polynomials
// More temperature polynomials
let RB = b0 + (b1 + (b2 + (b3 + b4 * temp) * temp) * temp) * temp
let RC = c0 + (c1 + c2 * temp) * temp
SMOW + RB * salt + RC * (salt ** 1.5) + d0 * salt * salt
SMOW + RB * salt + RC * salt ** 1.5 + d0 * salt * salt
/// Secant bulk modulus
let seck salt temp pres =
// """Secant bulk modulus"""
// # --- Pure water terms ---
// --- Pure water terms ---
let h0 = 3.239908
let h1 = 1.43713E-3
let h2 = 1.16092E-4
let h3 = -5.77905E-7
let h1 = 1.43713e-3
let h2 = 1.16092e-4
let h3 = -5.77905e-7
let AW = h0 + (h1 + (h2 + h3 * temp) * temp) * temp
let k0 = 8.50935E-5
let k1 = -6.12293E-6
let k2 = 5.2787E-8
let k0 = 8.50935e-5
let k1 = -6.12293e-6
let k2 = 5.2787e-8
let BW = k0 + (k1 + k2 * temp) * temp
let e0 = 19652.21
let e1 = 148.4206
let e2 = -2.327105
let e3 = 1.360477E-2
let e4 = -5.155288E-5
let e3 = 1.360477e-2
let e4 = -5.155288e-5
let KW = e0 + (e1 + (e2 + (e3 + e4 * temp) * temp) * temp) * temp
// # --- seawater, P = 0 ---
// --- Seawater, P = 0 ---
let SR = salt ** 0.5
let i0 = 2.2838E-3
let i1 = -1.0981E-5
let i2 = -1.6078E-6
let j0 = 1.91075E-4
let i0 = 2.2838e-3
let i1 = -1.0981e-5
let i2 = -1.6078e-6
let j0 = 1.91075e-4
let A = AW + (i0 + (i1 + i2 * temp) * temp + j0 * SR) * salt
let f0 = 54.6746
let f1 = -0.603459
let f2 = 1.09987E-2
let f3 = -6.1670E-5
let g0 = 7.944E-2
let g1 = 1.6483E-2
let g2 = -5.3009E-4
let f2 = 1.09987e-2
let f3 = -6.1670e-5
let g0 = 7.944e-2
let g1 = 1.6483e-2
let g2 = -5.3009e-4
let K0 =
KW
+ (f0 + (f1 + (f2 + f3 * temp) * temp) * temp + (g0 + (g1 + g2 * temp) * temp) * SR)
* salt
// # --- General expression ---
let m0 = -9.9348E-7
let m1 = 2.0816E-8
let m2 = 9.1697E-10
// --- General expression ---
let m0 = -9.9348e-7
let m1 = 2.0816e-8
let m2 = 9.1697e-10
let B = BW + (m0 + (m1 + m2 * temp) * temp) * salt
K0 + (A + B * pres) * pres
let p = 0.1 * pres // Convert to bar
(dens0 salt temp) / (1.0 - p / (seck salt temp p))
// Convert to bar
let pres = 0.1 * pres
dens0 salt temp / (1.0 - pres / seck salt temp pres)
let ambientWmass (za: float array) (Ta: float array) (Sa: float array) (zp: float) =
let i1 =
@@ -166,32 +168,46 @@ let zstep0 (s0: ModelSolution) (awm: AmbientData) (rhoref: float) (alpha: float)
-pi - theta0
else
failwith "theta larger than -pi for downward plume"
let vat = va * (cos th) // ambient velocity tangential to plume
let van = va * (sin theta0) // ambient velocity normal to plume (in theta direction)
let ve = alpha * abs (v0 - vat) + beta * abs van //entrainment velocity
let rho = eq_of_state T0 S0 (abs z)
let rhoa = eq_of_state Ta Sa (abs z)
// Ambient velocity tangential to plume
let vat = va * cos th
// Ambient velocity normal to plume (in theta direction)
let van = va * sin theta0
// Entrainment velocity
let ve = alpha * abs (v0 - vat) + beta * abs van
let rho = dens T0 S0 (abs z)
let rhoa = dens Ta Sa (abs z)
let gp = 9.81 * (rhoa - rho) / rhoref
let dr2v = 2.0 * R0 * ve
// Continuity equation
let r2v = R0 * R0 * v0 + dr2v * ds
// Momentum equation in tangential direction
let r2v2 = R0 * R0 * v0 * v0 + dr2v * vat * ds + R0 * R0 * gp * (sin theta0) * ds
let r2v2 = R0 * R0 * v0 * v0 + dr2v * vat * ds + R0 * R0 * gp * sin theta0 * ds
// Momentum equation in normal (theta) direction
let theta =
if up then
theta0 + (-dr2v * van + R0 * R0 * gp * (cos theta0)) * ds / r2v2
theta0 + (-dr2v * van + R0 * R0 * gp * cos theta0) * ds / r2v2
else
theta0 + (dr2v * van + R0 * R0 * gp * (cos theta0)) * ds / r2v2
theta0 + (dr2v * van + R0 * R0 * gp * cos theta0) * ds / r2v2
// Equations for temperature and salinity
let r2vt = R0 * R0 * (v0 * (Ta - T0) + dTz * (sin theta0) * ds)
let r2vs = R0 * R0 * (v0 * (Sa - S0) + dSz * (sin theta0) * ds)
let r2vt = R0 * R0 * (v0 * (Ta - T0) + dTz * sin theta0 * ds)
let r2vs = R0 * R0 * (v0 * (Sa - S0) + dSz * sin theta0 * ds)
let T = Ta - r2vt / r2v
let S = Sa - r2vs / r2v
let v = r2v2 / r2v
let R = r2v / v |> sqrt
let vTr = Math.PI * R * R * v
let sol = {
// ModelSolution
{
temp = Array.append s0.temp [| T |]
salt = Array.append s0.salt [| S |]
dens0 = Array.append s0.dens0 [| rho |]
@@ -200,11 +216,10 @@ let zstep0 (s0: ModelSolution) (awm: AmbientData) (rhoref: float) (alpha: float)
R = Array.append s0.R [| R |]
vTr = Array.append s0.vTr [| vTr |]
redgrav = Array.append s0.redgrav [| gp |]
z = Array.append s0.z [| (Array.last s0.z) + ds * (sin theta) |]
x = Array.append s0.x [| (Array.last s0.x) + ds * (cos theta) |]
z = Array.append s0.z [| Array.last s0.z + ds * sin theta |]
x = Array.append s0.x [| Array.last s0.x + ds * cos theta |]
time = awm.time
}
sol
let zstep (s0: ModelSolution) (awm: AmbientData) (rhoref: float) (alpha: float) (beta: float) (ds: float) (up: bool) =
let pi = Math.PI
@@ -228,30 +243,42 @@ let zstep (s0: ModelSolution) (awm: AmbientData) (rhoref: float) (alpha: float)
-pi - theta0
else
failwith "theta larger than -pi for downward plume"
let vat = va * (cos th) // ambient velocity tangential to plume
let van = va * (sin theta0) // ambient velocity normal to plume (in theta direction)
let ve = alpha * abs (v0 - vat) + beta * abs van //entrainment velocity
let rho = eq_of_state T0 S0 (abs z)
let rhoa = eq_of_state Ta Sa (abs z)
// Ambient velocity tangential to plume
let vat = va * cos th
// Ambient velocity normal to plume (in theta direction)
let van = va * sin theta0
// Entrainment velocity
let ve = alpha * abs (v0 - vat) + beta * abs van
let rho = dens T0 S0 (abs z)
let rhoa = dens Ta Sa (abs z)
let gp = 9.81 * (rhoa - rho) / rhoref
let dr2v = 2.0 * R0 * ve
// Continuity equation
let r2v = R0 * R0 * v0 + dr2v * ds
// Momentum equation in tangential direction
let r2v2 = R0 * R0 * v0 * v0 + dr2v * vat * ds + R0 * R0 * gp * (sin theta0) * ds
let r2v2 = R0 * R0 * v0 * v0 + dr2v * vat * ds + R0 * R0 * gp * sin theta0 * ds
// Momentum equation in normal (theta) direction
let theta =
if up then
theta0 + (-dr2v * van + R0 * R0 * gp * (cos theta0)) * ds / r2v2
theta0 + (-dr2v * van + R0 * R0 * gp * cos theta0) * ds / r2v2
else
theta0 + (dr2v * van + R0 * R0 * gp * (cos theta0)) * ds / r2v2
theta0 + (dr2v * van + R0 * R0 * gp * cos theta0) * ds / r2v2
// Equations for temperature and salinity
let r2vt = R0 * R0 * (v0 * (Ta - T0) + dTz * (sin theta0) * ds)
let r2vs = R0 * R0 * (v0 * (Sa - S0) + dSz * (sin theta0) * ds)
let r2vt = R0 * R0 * (v0 * (Ta - T0) + dTz * sin theta0 * ds)
let r2vs = R0 * R0 * (v0 * (Sa - S0) + dSz * sin theta0 * ds)
let T = Ta - r2vt / r2v
let S = Sa - r2vs / r2v
let v =
if ((r2v2 / r2v) / (Array.last s0.v) > 0.5) then
if r2v2 / r2v / Array.last s0.v > 0.5 then
Some (r2v2 / r2v)
else
None
@@ -259,25 +286,24 @@ let zstep (s0: ModelSolution) (awm: AmbientData) (rhoref: float) (alpha: float)
match v with
| Some v -> r2v / v |> sqrt
| None -> -999.9
let sol =
match v with
| Some v ->
let vTr = Math.PI * R * R * v
{
temp = Array.append s0.temp [| T |]
salt = Array.append s0.salt [| S |]
dens0 = Array.append s0.dens0 [| rho |]
theta = Array.append s0.theta [| theta |]
v = Array.append s0.v [| v |]
R = Array.append s0.R [| R |]
vTr = Array.append s0.vTr [| vTr |]
redgrav = Array.append s0.redgrav [| gp |]
z = Array.append s0.z [| (Array.last s0.z) + ds * (sin theta) |]
x = Array.append s0.x [| (Array.last s0.x) + ds * (cos theta) |]
time = awm.time
}
| None -> s0
sol
match v with
| None -> s0
| Some v ->
let vTr = Math.PI * R * R * v
{
temp = Array.append s0.temp [| T |]
salt = Array.append s0.salt [| S |]
dens0 = Array.append s0.dens0 [| rho |]
theta = Array.append s0.theta [| theta |]
v = Array.append s0.v [| v |]
R = Array.append s0.R [| R |]
vTr = Array.append s0.vTr [| vTr |]
redgrav = Array.append s0.redgrav [| gp |]
z = Array.append s0.z [| Array.last s0.z + ds * sin theta |]
x = Array.append s0.x [| Array.last s0.x + ds * cos theta |]
time = awm.time
}
let writeSolution (sol: ModelSolution) (filename: string) =
let datastring =
@@ -286,14 +312,12 @@ let writeSolution (sol: ModelSolution) (filename: string) =
$"{sol.temp[i]} {sol.salt[i]} {sol.theta[i]} {sol.v[i]} {sol.R[i]} {sol.redgrav[i]} {sol.z[i]} {sol.x[i]}")
IO.File.WriteAllLines (filename, datastring)
let calcDilution (solution: ModelSolution) =
let vTr0 = solution.vTr[0]
solution.vTr |> Array.map (fun s -> s / vTr0)
let calcDilutionAll (solution: ModelSolution[]) = solution |> Array.map calcDilution
let solver
(s0: ModelSolution)
(awm: AmbientData)
@@ -335,7 +359,7 @@ let writeAmbient (amb: AmbientData) (filename: string) =
let currentDirection (u: float array) (v: float array) =
let uv = Array.zip u v
let angles = uv |> Array.map (fun (u, v) -> angle u v)
let binangles = [| for i in 0..30 -> 2.0 * Math.PI / 30.0 * (float i) |]
let binangles = [| for i in 0..30 -> 2.0 * Math.PI / 30.0 * float i |]
let idxs =
let t = 2.0 * Math.PI / 30.0
angles |> Array.map (fun a -> floor (a / t) |> int)
@@ -350,7 +374,6 @@ let currentDirection (u: float array) (v: float array) =
|> Array.max
binangles[idx]
let unzip4 (t: (float * float * float * float)[]) =
let c1 = t |> Array.map (fun (ci, _, _, _) -> ci)
let c2 = t |> Array.map (fun (_, ci, _, _) -> ci)

View File

@@ -174,7 +174,7 @@ let writeAmbientFile (amb: AmbientData array) (file: string) (sol: ModelSolution
let vel = Array2D.zeroCreate amb.Length amb[0].v.Length
let temp = Array2D.zeroCreate amb.Length amb[0].temp.Length
let salt = Array2D.zeroCreate amb.Length amb[0].salt.Length
let dens = Array2D.zeroCreate amb.Length amb[0].salt.Length
let dens' = Array2D.zeroCreate amb.Length amb[0].salt.Length
let dens0 = Array2D.zeroCreate amb.Length amb[0].salt.Length
let z = Array2D.zeroCreate amb.Length amb[0].z.Length
for t = 0 to amb.Length - 1 do
@@ -184,17 +184,17 @@ let writeAmbientFile (amb: AmbientData array) (file: string) (sol: ModelSolution
z[t, *] <- amb[t].z
let d =
Array.zip3 amb[t].temp amb[t].salt amb[t].z
|> Array.map (fun (ti, si, zi) -> eq_of_state ti si (abs zi))
dens[t, *] <- d
|> Array.map (fun (ti, si, zi) -> dens ti si (abs zi))
dens'[t, *] <- d
let d0 =
Array.zip3 amb[t].temp amb[t].salt amb[t].z
|> Array.map (fun (ti, si, _) -> eq_of_state ti si 0.0)
|> Array.map (fun (ti, si, _) -> dens ti si 0.0)
dens0[t, *] <- d0
let _ = nc.AddVariable<float> ("temp", temp, [| "time"; "sigma" |])
let _ = nc.AddVariable<float> ("salt", salt, [| "time"; "sigma" |])
let _ = nc.AddVariable<float> ("z", z, [| "time"; "sigma" |])
let _ = nc.AddVariable<float> ("dens", dens, [| "time"; "sigma" |])
let _ = nc.AddVariable<float> ("dens", dens', [| "time"; "sigma" |])
let _ = nc.AddVariable<float> ("dens0", dens0, [| "time"; "sigma" |])
let _ = nc.AddVariable<float> ("vel", vel, [| "time"; "sigma" |])
let zeta = amb |> Array.map _.zeta

View File

@@ -19,7 +19,7 @@
<PackageReference Include="FSharpPlus" Version="1.7.0"/>
<PackageReference Include="Oceanbox.FvcomKit" Version="5.12.0"/>
<PackageReference Include="Oceanbox.DataAgent" Version="6.23.1"/>
<PackageReference Include="SDSLite-o" Version="2.7.2"/>
<PackageReference Include="SDSLite.Oceanbox" Version="2.7.2"/>
<PackageReference Include="Serilog" Version="4.2.0"/>
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0"/>
<PackageReference Include="Thoth.Json.Net" Version="12.0.0"/>

646
src/Lib/packages.lock.json Normal file
View File

@@ -0,0 +1,646 @@
{
"version": 1,
"dependencies": {
"net9.0": {
"FSharp.Core": {
"type": "Direct",
"requested": "[9.0.300, )",
"resolved": "9.0.300",
"contentHash": "TVt2J7RCE1KCS2IaONF+p8/KIZ1eHNbW+7qmKF6hGoD4tXl+o07ja1mPtFjMqRa5uHMFaTrGTPn/m945WnDLiQ=="
},
"FSharpPlus": {
"type": "Direct",
"requested": "[1.7.0, )",
"resolved": "1.7.0",
"contentHash": "9+PXT3nG7K5bzgYOzxgwZu5ij25BH7OtMkMJUrWkf+HcfbvsEGCvIf3InF8MCvJ5lO02NfGb9fC8slLEytqw0Q==",
"dependencies": {
"FSharp.Core": "6.0.6"
}
},
"Oceanbox.DataAgent": {
"type": "Direct",
"requested": "[6.23.1, )",
"resolved": "6.23.1",
"contentHash": "GT2YFD57o4LGcpnTHkgUvvKtncvm7FKE2/KGuAqcNl87/qJyc41L2+sMot1WUABBUEBZ86zZ4h3DnOa2wi67JQ==",
"dependencies": {
"Dapr.Actors": "1.14.0",
"FSharp.Core": "9.0.100",
"FSharp.Data": "6.4.0",
"FSharpPlus": "1.7.0",
"Fable.Remoting.DotnetClient": "3.35.0",
"Microsoft.EntityFrameworkCore": "9.0.0",
"Microsoft.EntityFrameworkCore.Relational": "9.0.0",
"NetTopologySuite": "2.5.0",
"Npgsql.EntityFrameworkCore.PostgreSQL": "9.0.2",
"Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite": "9.0.2",
"Oceanbox.FvcomKit": "5.6.0",
"SDSLite.Oceanbox": "2.7.3",
"Serilog.Sinks.Console": "6.0.0",
"Thoth.Json.Net": "12.0.0"
}
},
"Oceanbox.FvcomKit": {
"type": "Direct",
"requested": "[5.12.0, )",
"resolved": "5.12.0",
"contentHash": "78qkFpO2819Ddg6hYqRKXwCj2/ZBqrNKJ3536Q9R+4lx7dfMox97VPcpHviPRb/NsFG1M60TaYpm2DxuZclPaA==",
"dependencies": {
"FSharp.Core": "9.0.201",
"FSharp.Data": "6.4.1",
"FSharpPlus": "1.7.0",
"FsPickler": "5.3.2",
"KDTree": "1.4.1",
"MathNet.Numerics.FSharp": "5.0.0",
"MessagePack": "3.1.3",
"ProjNet.FSharp": "5.2.0",
"SDSlite.Oceanbox": "2.7.3",
"Serilog": "4.2.0",
"Serilog.Sinks.Console": "6.0.0",
"Serilog.Sinks.Seq": "9.0.0",
"Thoth.Json.Net": "12.0.0"
}
},
"SDSLite.Oceanbox": {
"type": "Direct",
"requested": "[2.7.2, )",
"resolved": "2.7.3",
"contentHash": "tmTPsEUmQhwaCzHwuSw7he2FfjcVpZ/Sy2ewfTwm1IKnwOZazKouTS5t4LNUpaGtjK1o/gdfz1b+0KxXnUl97g==",
"dependencies": {
"DynamicInterop": "0.9.1"
}
},
"Serilog": {
"type": "Direct",
"requested": "[4.2.0, )",
"resolved": "4.2.0",
"contentHash": "gmoWVOvKgbME8TYR+gwMf7osROiWAURterc6Rt2dQyX7wtjZYpqFiA/pY6ztjGQKKV62GGCyOcmtP1UKMHgSmA=="
},
"Serilog.Sinks.Console": {
"type": "Direct",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "fQGWqVMClCP2yEyTXPIinSr5c+CBGUvBybPxjAGcf7ctDhadFhrQw03Mv8rJ07/wR5PDfFjewf2LimvXCDzpbA==",
"dependencies": {
"Serilog": "4.0.0"
}
},
"Thoth.Json.Net": {
"type": "Direct",
"requested": "[12.0.0, )",
"resolved": "12.0.0",
"contentHash": "n2YyONYdWCFS4Pu7wrqgV/l5tPuN+t3gxEfs/2RwqCiQkRnbgKs9dK61zHeZS5YganAoFbxLSwbaNL7SvSrS9g==",
"dependencies": {
"FSharp.Core": "4.7.2",
"Fable.Core": "3.1.6",
"Newtonsoft.Json": "13.0.1"
}
},
"Dapr.Actors": {
"type": "Transitive",
"resolved": "1.14.0",
"contentHash": "CUds5JTUGE8xJTcMw6fbSGbnJm7p7TNe7ZHymvSJb0apowFZRZQFm72rqSf3791nQtTdyioVYDi6cZGhUgrkWg==",
"dependencies": {
"Dapr.Client": "1.14.0",
"Microsoft.Extensions.Logging.Abstractions": "3.1.0"
}
},
"Dapr.Client": {
"type": "Transitive",
"resolved": "1.14.0",
"contentHash": "gvoxV+nKOLHTeDx+WLwV79GJ/ldJuCsRrFmyxq4NodIeE9XfEi5z08Nc+EAwn1NibD3Wi4B0CPZpm+El+UKFCA==",
"dependencies": {
"Google.Api.CommonProtos": "2.2.0",
"Google.Protobuf": "3.15.0",
"Grpc.Net.Client": "2.52.0"
}
},
"DynamicInterop": {
"type": "Transitive",
"resolved": "0.9.1",
"contentHash": "n21+Hd+tceX8lgaOosPV+Pne+YqnZUd5RLW3OhnsVxWRzYXiAIAKmKweHIePYeY+fmcn3N5tjkJyQUccFuL3bg=="
},
"Fable.Core": {
"type": "Transitive",
"resolved": "3.1.6",
"contentHash": "w6M1F0zoLk4kTFc1Lx6x1Ft6BD3QwRe0eaLiinAqbjVkcF+iK+NiXGJO+a6q9RAF9NCg0vI48Xku7aNeqG4JVw==",
"dependencies": {
"FSharp.Core": "4.7.1"
}
},
"Fable.Remoting.DotnetClient": {
"type": "Transitive",
"resolved": "3.35.0",
"contentHash": "xaxt9nKfqIWh30+cOrG9GNl06+7yTy5htrcF5eXsZ7QJLLy7T5ZD3xeGpAb0xbh+TZTVQGluSQzxh/opIZm2PQ==",
"dependencies": {
"FSharp.Core": "6.0.0",
"Fable.Remoting.Json": "2.25.0",
"Fable.Remoting.MsgPack": "1.24.0"
}
},
"Fable.Remoting.Json": {
"type": "Transitive",
"resolved": "2.25.0",
"contentHash": "ycmxT5L7jUKLkSJ4uti+WiX1OU50UYhLLiFQwJpQzwPWpNbSXowPjUtGycl8G5429edzeIHGW/77hUlIAufiAg==",
"dependencies": {
"FSharp.Core": "6.0.0",
"Newtonsoft.Json": "13.0.3"
}
},
"Fable.Remoting.MsgPack": {
"type": "Transitive",
"resolved": "1.24.0",
"contentHash": "Bn3nzoZbib6lPk70bIJumEu2wFMxciB4o8k0Zw6tRfAOpNKvUsi79OOll2nW3FU1P6MVBepT43m+R8JvfYnNiw==",
"dependencies": {
"FSharp.Core": "4.7.2"
}
},
"FSharp.Data": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "P/ShAsNsuKrV9cpK7Mb/fSJ/kpinjOnVGRDXDzi/dYECS/lmlDrAvNVlodPbqCo5hIXvMMkKMc5C4f8ULLW7JQ==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Csv.Core": "6.4.1",
"FSharp.Data.Html.Core": "6.4.1",
"FSharp.Data.Http": "6.4.1",
"FSharp.Data.Json.Core": "6.4.1",
"FSharp.Data.Runtime.Utilities": "6.4.1",
"FSharp.Data.WorldBank.Core": "6.4.1",
"FSharp.Data.Xml.Core": "6.4.1"
}
},
"FSharp.Data.Csv.Core": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "/RmEq3HSafm4RPAPATDsDTY0aAkJ8ioDDJ0Qf/NuJW7c7/CC3xeU0XC3sHmDkp9v98aeQOSJdTa+NJrMTHzT7g==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Runtime.Utilities": "6.4.1"
}
},
"FSharp.Data.Html.Core": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "/T7k5FkR8nRJ3fZ8Bfaf/c9eda2ru0xCIbM+i2Qt/PgtHp2d1ZmDvQIWbYfDLWVcKjRVu/YpRYOw/2fX0RT8ew==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Csv.Core": "6.4.1",
"FSharp.Data.Runtime.Utilities": "6.4.1"
}
},
"FSharp.Data.Http": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "7KxlBNwnSIiR1nsPal2ofmgU4Rag8dyDJ+cziW1L9Z+iA55aXeXO/RapQDnyVIwl/Fbm1scGAuSTWP36JNpQFg==",
"dependencies": {
"FSharp.Core": "6.0.1"
}
},
"FSharp.Data.Json.Core": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "mUyqLZiI0XPEiE9FIJLJ3Ndof4hEc2paW049Cw224knmp/b0brMwznLaOqtlmCr49QCELj0tcT0ZCKfb2cFS0g==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Http": "6.4.1",
"FSharp.Data.Runtime.Utilities": "6.4.1"
}
},
"FSharp.Data.Runtime.Utilities": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "pG4X3QWilYMF3qjZWpod6QgO38uiYUM3/bkEsEyT69E3zAlFQFO9uUy0tqEhDznHvNx4QtZaScUM+06r94HHnQ==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Http": "6.4.1"
}
},
"FSharp.Data.WorldBank.Core": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "opXr3YMArDQCiA1nkEnhSf1s6E0QsotO0VZ5nvQcMXmDuDU4IA1i1DlYp4QVmCXRKj5EHPKMwZkTVNeQDuZ5Bg==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Http": "6.4.1",
"FSharp.Data.Json.Core": "6.4.1",
"FSharp.Data.Runtime.Utilities": "6.4.1"
}
},
"FSharp.Data.Xml.Core": {
"type": "Transitive",
"resolved": "6.4.1",
"contentHash": "TprbqQu+DdrR6Kl5biNCAsM8yeQs+pgqRpQYDorbbFIroGw1LBMoX+1iiigJcK89TwJAtiEzVrZCQzHvCDrCbA==",
"dependencies": {
"FSharp.Core": "6.0.1",
"FSharp.Data.Http": "6.4.1",
"FSharp.Data.Json.Core": "6.4.1",
"FSharp.Data.Runtime.Utilities": "6.4.1"
}
},
"FsPickler": {
"type": "Transitive",
"resolved": "5.3.2",
"contentHash": "LFtxXpQNor8az1ez3rN9oz2cqf/06i9yTrPyJ9R83qLEpFAU7Of0WL2hoSXzLHer4lh+6mO1NV4VQFiBzNRtjw==",
"dependencies": {
"FSharp.Core": "4.3.2",
"System.Reflection.Emit.Lightweight": "4.3.0"
}
},
"Google.Api.CommonProtos": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "mxXNYkHYL7T6NG8cdbodxpixQZfpozBkZj2g+jGCB/sO13RqfUvh9YHd8G2QI5HP24brl+nILJReC3/gzgsrrg==",
"dependencies": {
"Google.Protobuf": "[3.13.0, 4.0.0)"
}
},
"Google.Protobuf": {
"type": "Transitive",
"resolved": "3.15.0",
"contentHash": "2na7LsYrtxkEQaVCNjaafBzVu4IJ4U4+dwwBazK8oUkpDiIFjO0GkyTc+IbStx4xNVAV4EqHl+qp2uegFgFiiA==",
"dependencies": {
"System.Memory": "4.5.3",
"System.Runtime.CompilerServices.Unsafe": "4.5.2"
}
},
"Grpc.Core.Api": {
"type": "Transitive",
"resolved": "2.52.0",
"contentHash": "SQiPyBczG4vKPmI6Fd+O58GcxxDSFr6nfRAJuBDUNj+PgdokhjWJvZE/La1c09AkL2FVm/jrDloG89nkzmVF7A==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"Grpc.Net.Client": {
"type": "Transitive",
"resolved": "2.52.0",
"contentHash": "hWVH9g/Nnjz40ni//2S8UIOyEmhueQREoZIkD0zKHEPqLxXcNlbp4eebXIOicZtkwDSx0TFz9NpkbecEDn6rBw==",
"dependencies": {
"Grpc.Net.Common": "2.52.0",
"Microsoft.Extensions.Logging.Abstractions": "3.0.3"
}
},
"Grpc.Net.Common": {
"type": "Transitive",
"resolved": "2.52.0",
"contentHash": "di9qzpdx525IxumZdYmu6sG2y/gXJyYeZ1ruFUzB9BJ1nj4kU1/dTAioNCMt1VLRvNVDqh8S8B1oBdKhHJ4xRg==",
"dependencies": {
"Grpc.Core.Api": "2.52.0"
}
},
"KdTree": {
"type": "Transitive",
"resolved": "1.4.1",
"contentHash": "yWbb35v/V9y88SLLMUPTlAN3pQEoPhDfZf9PApFnlU4kLtwVQ75U9vW5mW4/alQnLBuLKWBKcy4W5xK95mYsuA=="
},
"MathNet.Numerics": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "pg1W2VwaEQMAiTpGK840hZgzavnqjlCMTVSbtVCXVyT+7AX4mc1o89SPv4TBlAjhgCOo9c1Y+jZ5m3ti2YgGgA=="
},
"MathNet.Numerics.FSharp": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "lKYhd68fReW5odX/q+Uzxw3357Duq3zmvkYvnZVqqcc2r/EmrYGDoOdUGuHnhfr8yj9V34js5gQH/7IWcxZJxg==",
"dependencies": {
"FSharp.Core": "6.0.2",
"MathNet.Numerics": "5.0.0"
}
},
"MessagePack": {
"type": "Transitive",
"resolved": "3.1.3",
"contentHash": "UiNv3fknvPzh5W+S0VV96R17RBZQQU71qgmsMnjjRZU2rtQM/XcTnOB+klT2dA6T1mxjnNKYrEm164AoXvGmYg==",
"dependencies": {
"MessagePack.Annotations": "3.1.3",
"MessagePackAnalyzer": "3.1.3",
"Microsoft.NET.StringTools": "17.11.4"
}
},
"MessagePack.Annotations": {
"type": "Transitive",
"resolved": "3.1.3",
"contentHash": "XTy4njgTAf6UVBKFj7c7ad5R0WVKbvAgkbYZy4f00kplzX2T3VOQ34AUke/Vn/QgQZ7ETdd34/IDWS3KBInSGA=="
},
"MessagePackAnalyzer": {
"type": "Transitive",
"resolved": "3.1.3",
"contentHash": "19u1oVNv2brCs5F/jma8O8CnsKMMpYwNqD0CAEDEzvqwDTAhqC9r7xHZP4stPb3APs/ryO/zVn7LvjoEHfvs7Q=="
},
"Microsoft.EntityFrameworkCore": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "wpG+nfnfDAw87R3ovAsUmjr3MZ4tYXf6bFqEPVAIKE6IfPml3DS//iX0DBnf8kWn5ZHSO5oi1m4d/Jf+1LifJQ==",
"dependencies": {
"Microsoft.EntityFrameworkCore.Abstractions": "9.0.0",
"Microsoft.EntityFrameworkCore.Analyzers": "9.0.0",
"Microsoft.Extensions.Caching.Memory": "9.0.0",
"Microsoft.Extensions.Logging": "9.0.0"
}
},
"Microsoft.EntityFrameworkCore.Abstractions": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "fnmifFL8KaA4ZNLCVgfjCWhZUFxkrDInx5hR4qG7Q8IEaSiy/6VOSRFyx55oH7MV4y7wM3J3EE90nSpcVBI44Q=="
},
"Microsoft.EntityFrameworkCore.Analyzers": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "Qje+DzXJOKiXF72SL0XxNlDtTkvWWvmwknuZtFahY5hIQpRKO59qnGuERIQ3qlzuq5x4bAJ8WMbgU5DLhBgeOQ=="
},
"Microsoft.EntityFrameworkCore.Relational": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "j+msw6fWgAE9M3Q/5B9Uhv7pdAdAQUvFPJAiBJmoy+OXvehVbfbCE8ftMAa51Uo2ZeiqVnHShhnv4Y4UJJmUzA==",
"dependencies": {
"Microsoft.EntityFrameworkCore": "9.0.0",
"Microsoft.Extensions.Caching.Memory": "9.0.0",
"Microsoft.Extensions.Configuration.Abstractions": "9.0.0",
"Microsoft.Extensions.Logging": "9.0.0"
}
},
"Microsoft.Extensions.Caching.Abstractions": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "FPWZAa9c0H4dvOj351iR1jkUIs4u9ykL4Bm592yhjDyO5lCoWd+TMAHx2EMbarzUvCvgjWjJIoC6//Q9kH6YhA==",
"dependencies": {
"Microsoft.Extensions.Primitives": "9.0.0"
}
},
"Microsoft.Extensions.Caching.Memory": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "zbnPX/JQ0pETRSUG9fNPBvpIq42Aufvs15gGYyNIMhCun9yhmWihz0WgsI7bSDPjxWTKBf8oX/zv6v2uZ3W9OQ==",
"dependencies": {
"Microsoft.Extensions.Caching.Abstractions": "9.0.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
"Microsoft.Extensions.Logging.Abstractions": "9.0.0",
"Microsoft.Extensions.Options": "9.0.0",
"Microsoft.Extensions.Primitives": "9.0.0"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "lqvd7W3FGKUO1+ZoUEMaZ5XDJeWvjpy2/M/ptCGz3tXLD4HWVaSzjufsAsjemasBEg+2SxXVtYVvGt5r2nKDlg==",
"dependencies": {
"Microsoft.Extensions.Primitives": "9.0.0"
}
},
"Microsoft.Extensions.DependencyInjection": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "MCPrg7v3QgNMr0vX4vzRXvkNGgLg8vKWX0nKCWUxu2uPyMsaRgiRc1tHBnbTcfJMhMKj2slE/j2M9oGkd25DNw==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "+6f2qv2a3dLwd5w6JanPIPs47CxRbnk+ZocMJUhv9NxP88VlOcJYZs9jY+MYSjxvady08bUZn6qgiNh7DadGgg=="
},
"Microsoft.Extensions.Logging": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "crjWyORoug0kK7RSNJBTeSE6VX8IQgLf3nUpTB9m62bPXp/tzbnOsnbe8TXEG0AASNaKZddnpHKw7fET8E++Pg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.0",
"Microsoft.Extensions.Logging.Abstractions": "9.0.0",
"Microsoft.Extensions.Options": "9.0.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "g0UfujELzlLbHoVG8kPKVBaW470Ewi+jnptGS9KUi6jcb+k2StujtK3m26DFSGGwQ/+bVgZfsWqNzlP6YOejvw==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0"
}
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "y2146b3jrPI3Q0lokKXdKLpmXqakYbDIPDV6r3M8SqvSf45WwOTzkyfDpxnZXJsJQEpAsAqjUq5Pu8RCJMjubg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
"Microsoft.Extensions.Primitives": "9.0.0"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "N3qEBzmLMYiASUlKxxFIISP4AiwuPTHF5uCh+2CWSwwzAJiIYx0kBJsS30cp1nvhSySFAVi30jecD307jV+8Kg=="
},
"Microsoft.NET.StringTools": {
"type": "Transitive",
"resolved": "17.11.4",
"contentHash": "mudqUHhNpeqIdJoUx2YDWZO/I9uEDYVowan89R6wsomfnUJQk6HteoQTlNjZDixhT2B4IXMkMtgZtoceIjLRmA=="
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
"resolved": "1.1.0",
"contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
},
"Microsoft.NETCore.Targets": {
"type": "Transitive",
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
"NetTopologySuite": {
"type": "Transitive",
"resolved": "2.5.0",
"contentHash": "5/+2O2ADomEdUn09mlSigACdqvAf0m/pVPGtIPEPQWnyrVykYY0NlfXLIdkMgi41kvH9kNrPqYaFBTZtHYH7Xw==",
"dependencies": {
"System.Memory": "4.5.4"
}
},
"NetTopologySuite.IO.PostGis": {
"type": "Transitive",
"resolved": "2.1.0",
"contentHash": "3W8XTFz8iP6GQ5jDXK1/LANHiU+988k1kmmuPWNKcJLpmSg6CvFpbTpz+s4+LBzkAp64wHGOldSlkSuzYfrIKA==",
"dependencies": {
"NetTopologySuite": "[2.0.0, 3.0.0-A)"
}
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"Npgsql": {
"type": "Transitive",
"resolved": "9.0.2",
"contentHash": "hCbO8box7i/XXiTFqCJ3GoowyLqx3JXxyrbOJ6om7dr+eAknvBNhhUHeJVGAQo44sySZTfdVffp4BrtPeLZOAA==",
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "8.0.2"
}
},
"Npgsql.EntityFrameworkCore.PostgreSQL": {
"type": "Transitive",
"resolved": "9.0.2",
"contentHash": "cYdOGplIvr9KgsG8nJ8xnzBTImeircbgetlzS1OmepS5dAQW6PuGpVrLOKBNEwEvGYZPsV8037X5vZ/Dmpwz7Q==",
"dependencies": {
"Microsoft.EntityFrameworkCore": "[9.0.0, 10.0.0)",
"Microsoft.EntityFrameworkCore.Relational": "[9.0.0, 10.0.0)",
"Npgsql": "9.0.2"
}
},
"Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite": {
"type": "Transitive",
"resolved": "9.0.2",
"contentHash": "D38a3+CF8dO7nPiwt/NtQ/sLbrzZpX910jaaGiETdeS18KI0yMYEFvWWO5I/JBjVXLVnruodsukIUupdoD4fRA==",
"dependencies": {
"Npgsql.EntityFrameworkCore.PostgreSQL": "9.0.2",
"Npgsql.NetTopologySuite": "9.0.2"
}
},
"Npgsql.NetTopologySuite": {
"type": "Transitive",
"resolved": "9.0.2",
"contentHash": "DCwN+IVl3yWfOftPe0UBUUDOqa877ca+z+xSDQVi5ShDnOIAipaaYZlzDYm8Nga8hcxx6UrIQuImFnXv8fDpwg==",
"dependencies": {
"NetTopologySuite": "2.5.0",
"NetTopologySuite.IO.PostGIS": "2.1.0",
"Npgsql": "9.0.2"
}
},
"ProjNET": {
"type": "Transitive",
"resolved": "2.0.0",
"contentHash": "iMJG8qpGJ8SjFrB044O8wgo0raAWCdG1Bvly0mmVcjzsrexDHhC+dUct6Wb1YwQtupMBjSTWq7Fn00YeNErprA==",
"dependencies": {
"System.Memory": "4.5.3",
"System.Numerics.Vectors": "4.5.0"
}
},
"ProjNet.FSharp": {
"type": "Transitive",
"resolved": "5.2.0",
"contentHash": "sYSePg/0sVo16Fk3r7okVSga6i9GAN0kkjt1haEXVw25SF8A4S3Gcpf5+6lgknBGdYiZBmJ+3S6v5g1WSSCp2g==",
"dependencies": {
"FSharp.Core": "8.0.100",
"FSharp.Data": "6.3.0",
"FSharpPlus": "1.5.0",
"ProjNet": "2.0.0"
}
},
"Serilog.Sinks.File": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "lxjg89Y8gJMmFxVkbZ+qDgjl+T4yC5F7WSLTvA+5q0R04tfKVLRL/EHpYoJ/MEQd2EeCKDuylBIVnAYMotmh2A==",
"dependencies": {
"Serilog": "4.0.0"
}
},
"Serilog.Sinks.Seq": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "aNU8A0K322q7+voPNmp1/qNPH+9QK8xvM1p72sMmCG0wGlshFzmtDW9QnVSoSYCj0MgQKcMOlgooovtBhRlNHw==",
"dependencies": {
"Serilog": "4.2.0",
"Serilog.Sinks.File": "6.0.0"
}
},
"System.IO": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading.Tasks": "4.3.0"
}
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.4",
"contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw=="
},
"System.Numerics.Vectors": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
},
"System.Reflection": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Emit.ILGeneration": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==",
"dependencies": {
"System.Reflection": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Emit.Lightweight": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==",
"dependencies": {
"System.Reflection": "4.3.0",
"System.Reflection.Emit.ILGeneration": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "4.5.2",
"contentHash": "wprSFgext8cwqymChhrBLu62LMg/1u92bU+VOwyfBimSPVFXtsNqEWC92Pf9ofzJFlk4IHmJA75EDJn1b2goAQ=="
},
"System.Text.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.Threading.Tasks": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
}
}
}
}

View File

@@ -84,13 +84,13 @@ type JobMessage =
[<CLIMutable>]
type JobProgress = {
/// <summary>
/// Percentage [0-100]
/// Percentage [0-100]
/// </summary>
progress: int
progress: int
/// <summary>
/// Time remaining in seconds
/// </summary>
eta: int
eta: int
}
type MessageType =
@@ -314,14 +314,14 @@ let processPlumeJob (plume: PlumeJob) (jobId: int) (guid: Guid) (agent: string)
let dischargeRho =
let ts = Array.zip dischargeTemp dischargeSalt
ts
|> Array.map (fun (t, s) -> Model.eq_of_state t s (abs z0))
|> Array.map (fun (t, s) -> Model.dens t s (abs z0))
let rhoa =
ambientarray
|> Array.map (fun a ->
Log.Debug $"z {a.z}, temp {a.temp} salt {a.salt} z0 {z0}"
let ta, sa = Model.ambientWmass a.z a.temp a.salt z0
Model.eq_of_state ta sa (abs z0))
Model.dens ta sa (abs z0))
let up = Tools.upward theta0 rhoa dischargeRho
@@ -354,7 +354,7 @@ let processPlumeJob (plume: PlumeJob) (jobId: int) (guid: Guid) (agent: string)
let ds0 = (ambient.zeta + h) / 100.0
let _, va0 = Model.ambientWmass ambient.z ambient.v ambient.v z0
let Ta, Sa = Model.ambientWmass ambient.z ambient.temp ambient.salt z0
let rhoa = Model.eq_of_state Ta Sa (abs z0)
let rhoa = Model.dens Ta Sa (abs z0)
let rho = dischargeRho[i]
let rg = 9.81 * (rhoa - rho) / rhoref
/// Initial plume velocity
@@ -490,7 +490,7 @@ let jobProcessor (statusPublisher: StatusPublisher) =
// Calculate ETA
let currentProgress = stage.ToProgress()
let eta = calculateEta startTime currentProgress
// Publish progress update
let jobProgress = { progress = currentProgress; eta = eta }
let content = encodeToBase64 (JsonSerializer.Serialize(jobProgress))

View File

@@ -37,7 +37,7 @@
<PackageReference Include="FSharpPlus" Version="1.7.0"/>
<PackageReference Include="Oceanbox.FvcomKit" Version="5.12.0"/>
<PackageReference Include="Oceanbox.ServerPack" Version="1.20.2"/>
<PackageReference Include="SDSLite-o" Version="2.7.2"/>
<PackageReference Include="SDSLite.Oceanbox" Version="2.7.3"/>
<PackageReference Include="Sentry.AspNetCore" Version="5.11.0"/>
<PackageReference Include="Serilog" Version="4.2.0"/>
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0"/>

View File

@@ -185,7 +185,7 @@ let sentryOptions (opt: SentryAspNetCoreOptions) =
// Custom sampler
// opt.TracesSampler <- sentrySampler
// NOTE(mrtz): Disable tracing
opt.TracesSampleRate <- 0.5
opt.TracesSampleRate <- 0.0
// Maximum amount of breadcrumbs sent to Sentry
opt.MaxBreadcrumbs <- 200
// Maximum amount of queued items

File diff suppressed because it is too large Load Diff

View File

@@ -13,20 +13,20 @@ module ModelTests =
let ``eq_of_state calculates reasonable density values`` () =
expect {
snapshot "True"
let seawaterDensity = eq_of_state 15.0 35.0 10.0
let seawaterDensity = dens 15.0 35.0 10.0
return seawaterDensity > 1020.0 && seawaterDensity < 1035.0
}
expect {
snapshot "True"
let seawaterDensity = eq_of_state 15.0 35.0 10.0
let freshwaterDensity = eq_of_state 15.0 0.0 10.0
let seawaterDensity = dens 15.0 35.0 10.0
let freshwaterDensity = dens 15.0 0.0 10.0
return freshwaterDensity < seawaterDensity
}
expect {
snapshot "True"
let freshwaterDensity = eq_of_state 15.0 0.0 10.0
let freshwaterDensity = dens 15.0 0.0 10.0
return freshwaterDensity > 995.0 && freshwaterDensity < 1005.0
}
@@ -36,9 +36,9 @@ module ModelTests =
snapshot "True"
let temp = 20.0
let pressure = 0.0
let density1 = eq_of_state temp 30.0 pressure
let density2 = eq_of_state temp 35.0 pressure
let density3 = eq_of_state temp 40.0 pressure
let density1 = dens temp 30.0 pressure
let density2 = dens temp 35.0 pressure
let density3 = dens temp 40.0 pressure
return density1 < density2 && density2 < density3
}
@@ -48,8 +48,8 @@ module ModelTests =
snapshot "True"
let salinity = 35.0
let pressure = 0.0
let densityCold = eq_of_state 5.0 salinity pressure
let densityWarm = eq_of_state 25.0 salinity pressure
let densityCold = dens 5.0 salinity pressure
let densityWarm = dens 25.0 salinity pressure
return densityCold > densityWarm
}