feat: initial commit

This commit is contained in:
2025-03-26 09:47:08 +01:00
commit 577793e066
28 changed files with 8229 additions and 0 deletions

73
.build/Build.fs Normal file
View File

@@ -0,0 +1,73 @@
open Fake.Core
open Fake.IO
open Farmer
open Farmer.Builders
open Helpers
initializeContext()
let srcPath = Path.getFullName "src"
let testPath = Path.getFullName "test"
let libPath = None
let distPath = Path.getFullName "dist"
let packPath = Path.getFullName "packages"
let versionFile = Path.getFullName ".version"
Target.create "Clean" (fun _ -> Shell.cleanDir distPath)
Target.create "InstallClient" (fun _ ->
run npm "install" "."
run dotnet "tool restore" "."
)
Target.create "Bundle" (fun _ ->
run dotnet $"publish -c Release -o {distPath}" srcPath
)
Target.create "BundleDebug" (fun _ ->
run dotnet $"publish -c Debug -o {distPath}" srcPath
)
Target.create "Pack" (fun _ ->
match libPath with
| Some p -> run dotnet $"pack -c Release -o {packPath}" p
| None -> ()
)
Target.create "Run" (fun _ -> run dotnet "watch run" srcPath)
Target.create "Format" (fun _ ->
run dotnet "fantomas . -r" "src"
)
Target.create "Test" (fun _ ->
if System.IO.Directory.Exists testPath then
run dotnet "run" testPath
else ()
)
open Fake.Core.TargetOperators
let dependencies = [
"Clean"
==> "InstallClient"
==> "Bundle"
"Clean"
==> "BundleDebug"
"Clean"
==> "Test"
"Clean"
==> "InstallClient"
==> "Run"
"Clean"
==> "Pack"
]
[<EntryPoint>]
let main args = runOrDefault args

105
.build/Helpers.fs Normal file
View File

@@ -0,0 +1,105 @@
module Helpers
open Fake.Core
let initializeContext () =
let execContext = Context.FakeExecutionContext.Create false "build.fsx" [ ]
Context.setExecutionContext (Context.RuntimeContext.Fake execContext)
module Proc =
module Parallel =
open System
let locker = obj()
let colors =
[| ConsoleColor.Blue
ConsoleColor.Yellow
ConsoleColor.Magenta
ConsoleColor.Cyan
ConsoleColor.DarkBlue
ConsoleColor.DarkYellow
ConsoleColor.DarkMagenta
ConsoleColor.DarkCyan |]
let print color (colored: string) (line: string) =
lock locker
(fun () ->
let currentColor = Console.ForegroundColor
Console.ForegroundColor <- color
Console.Write colored
Console.ForegroundColor <- currentColor
Console.WriteLine line)
let onStdout index name (line: string) =
let color = colors.[index % colors.Length]
if isNull line then
print color $"{name}: --- END ---" ""
else if String.isNotNullOrEmpty line then
print color $"{name}: " line
let onStderr name (line: string) =
let color = ConsoleColor.Red
if isNull line |> not then
print color $"{name}: " line
let redirect (index, (name, createProcess)) =
createProcess
|> CreateProcess.redirectOutputIfNotRedirected
|> CreateProcess.withOutputEvents (onStdout index name) (onStderr name)
let printStarting indexed =
for (index, (name, c: CreateProcess<_>)) in indexed do
let color = colors.[index % colors.Length]
let wd =
c.WorkingDirectory
|> Option.defaultValue ""
let exe = c.Command.Executable
let args = c.Command.Arguments.ToStartInfo
print color $"{name}: {wd}> {exe} {args}" ""
let run cs =
cs
|> Seq.toArray
|> Array.indexed
|> fun x -> printStarting x; x
|> Array.map redirect
|> Array.Parallel.map Proc.run
let createProcess exe arg dir =
CreateProcess.fromRawCommandLine exe arg
|> CreateProcess.withWorkingDirectory dir
|> CreateProcess.ensureExitCode
let dotnet = createProcess "dotnet"
let npm =
let npmPath =
match ProcessUtils.tryFindFileOnPath "npm" with
| Some path -> path
| None ->
"npm was not found in path. Please install it and make sure it's available from your path. " +
"See https://safe-stack.github.io/docs/quickstart/#install-pre-requisites for more info"
|> failwith
createProcess npmPath
let run proc arg dir =
proc arg dir
|> Proc.run
|> ignore
let runParallel processes =
processes
|> Proc.Parallel.run
|> ignore
let runOrDefault args =
try
match args with
| [| target |] -> Target.runOrDefault target
| _ ->
Target.runOrDefault "Run"
0
with e ->
printfn "%A" e
1

20
.config/dotnet-tools.json Normal file
View File

@@ -0,0 +1,20 @@
{
"version": 1,
"isRoot": true,
"tools": {
"fantomas": {
"version": "7.0.1",
"commands": [
"fantomas"
],
"rollForward": false
},
"dotnet-outdated-tool": {
"version": "4.6.7",
"commands": [
"dotnet-outdated"
],
"rollForward": false
}
}
}

27
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,27 @@
FROM mcr.microsoft.com/dotnet/sdk:9.0
# Add keys and sources lists
RUN apt-get update && apt-get install -y ca-certificates gnupg
RUN mkdir -p /etc/apt/keyrings
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
ENV NODE_MAJOR=20
RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
# Install node, 7zip, yarn, git, process tools
RUN apt-get update \
&& apt-get install -y nodejs p7zip-full git procps ssh-client libsqlite3-dev gcc-multilib libnetcdf19 libnetcdf-dev
# Clean up
RUN apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
# Trouble brewing
RUN rm /etc/ssl/openssl.cnf
# add dotnet tools to path to pick up fake and paket installation
ENV PATH="/root/.dotnet/tools:${PATH}"
# Copy endpoint specific user settings into container to specify
# .NET Core should be used as the runtime.
COPY settings.vscode.json /root/.vscode-remote/data/Machine/settings.json

View File

@@ -0,0 +1,11 @@
{
"name": "SAFE",
"dockerFile": "Dockerfile",
"appPort": [8080, 8085],
"extensions": [
"ionide.ionide-fsharp",
"ms-dotnettools.csharp",
"editorconfig.editorconfig",
"msjsdiag.debugger-for-chrome"
]
}

View File

@@ -0,0 +1,3 @@
{
"FSharp.fsacRuntime":"netcore"
}

31
.editorconfig Normal file
View File

@@ -0,0 +1,31 @@
root = true
[*]
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = false
[*.js]
indent_size = 2
max_line_length= 80
[*.fs]
max_line_length= 120
fsharp_max_if_then_else_short_width = 60
fsharp_max_infix_operator_expression = 80
fsharp_space_before_uppercase_invocation = true
fsharp_blank_lines_around_nested_multiline_expressions = false
fsharp_newline_between_type_definition_and_members = false
fsharp_multiline_bracket_style = stroustrup
fsharp_array_or_list_multiline_formatter = character_width
fsharp_max_array_or_list_width = 70
fsharp_max_array_or_list_number_of_items = 3
fsharp_record_multiline_formatter = number_of_items
fsharp_max_record_number_of_items = 3
fsharp_max_record_width = 70

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use nix

22
.gitignore vendored Normal file
View File

@@ -0,0 +1,22 @@
.fable/
.fake/
.vs/
.idea/
.ionide/
obj/
bin/
packages/
node_modules/
src/Client/public/js/
release.cmd
release.sh
*.orig
*.DotSettings.user
deploy/
dist/
build/
*.db
build.fsx.lock
_*.yaml
NuGet.Config
*.sif

8
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,8 @@
variables:
DEPLOY_NAME: s3noddy
SKIP_TESTS: "true"
include:
- project: oceanbox/gitlab-ci
ref: v2
file: Dotnet.gitlab-ci.yml

41
.releaserc.yaml Normal file
View File

@@ -0,0 +1,41 @@
branches:
- main
- master
- name: develop
prerelease: true
plugins:
- '@semantic-release/commit-analyzer'
- '@semantic-release/release-notes-generator'
- - '@semantic-release/changelog'
- changelogFile: RELEASE_NOTES.md
changelogTitle: "# Changelog"
- - 'semantic-release-dotnet'
- paths: [ "src/*.fsproj", "src/*/*.fsproj" ]
- - '@semantic-release/exec'
- generateNotesCmd: "echo ${nextRelease.version} > .version"
- - '@semantic-release/git'
- message: "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}"
assets: [ "RELEASE_NOTES.md", ".version", "src/*.fsproj", "src/*/*.fsproj" ]
- - '@semantic-release/gitlab'
- assets: []
analyzeCommits:
- path: "@semantic-release/commit-analyzer"
releaseRules:
- type: "fix"
release: "patch"
- type: "patch"
release: "patch"
- type: "feat"
release: "minor"
- type: "feature"
release: "minor"
- type: "minor"
release: "minor"
- type: "breaking"
release: "major"
- type: "major"
release: "major"

1
.version Normal file
View File

@@ -0,0 +1 @@
1.3.1

17
Build.fsproj Normal file
View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include=".build/Helpers.fs" />
<Compile Include=".build/Build.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Fake.Core.Target" Version="6.1.3" />
<PackageReference Include="Fake.DotNet.Cli" Version="6.1.3" />
<PackageReference Include="Fake.IO.FileSystem" Version="6.1.3" />
<PackageReference Include="Farmer" Version="1.9.11" />
<PackageReference Update="FSharp.Core" Version="9.0.201" />
</ItemGroup>
</Project>

6
Dockerfile Normal file
View File

@@ -0,0 +1,6 @@
FROM mcr.microsoft.com/dotnet/runtime:9.0
COPY deploy/ /app
WORKDIR /app
CMD /app/Noddy

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Serit Tromsø AS
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.

15
Noddy.slnx Normal file
View File

@@ -0,0 +1,15 @@
<Solution>
<Configurations>
<Platform Name="Any CPU" />
<Platform Name="x64" />
<Platform Name="x86" />
</Configurations>
<Folder Name="/Solution Items/">
<File Path=".gitlab-ci.yml" />
<File Path="Dockerfile" />
<File Path="LICENSE" />
<File Path="README.md" />
</Folder>
<Project Path="Build.fsproj" />
<Project Path="src/Noddy.fsproj" />
</Solution>

9
README.md Normal file
View File

@@ -0,0 +1,9 @@
# Noddy
## Run
`dotnet run`
## Build
`dotnet run Bundle`

1
RELEASE_NOTES.md Normal file
View File

@@ -0,0 +1 @@
# Changelog

7109
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

11
package.json Normal file
View File

@@ -0,0 +1,11 @@
{
"private": true,
"devDependencies": {
"@semantic-release/changelog": "^6.0.1",
"@semantic-release/exec": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@semantic-release/gitlab": "^7.0.4",
"semantic-release-dotnet": "^1.0.0"
},
"dependencies": {}
}

51
s3noddy.def Normal file
View File

@@ -0,0 +1,51 @@
Bootstrap: docker
From: mcr.microsoft.com/dotnet/sdk:9.0
Stage: build
%files
. /build
%post
apt-get update && apt-get install -y ca-certificates gnupg
mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=20
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
# Install node, 7zip, yarn, git, process tools
apt update \
&& apt install -y nodejs p7zip-full git procps ssh-client libnetcdf19 libnetcdf-dev
# Clean up
apt autoremove -y \
&& apt clean -y \
&& rm -rf /var/lib/apt/lists/*
# Install dotnet tools
dotnet tool restore
cd /build
dotnet run bundle
Bootstrap: docker
From: mcr.microsoft.com/dotnet/runtime:9.0
Stage: runtime
%files from build
/build/dist /app
%post
apt update \
&& apt install -y libnetcdf19
apt autoremove -y \
&& apt clean -y \
&& rm -rf /var/lib/apt/lists/*
cp -s /usr/lib/x86_64-linux-gnu/libdl.so.2 /usr/lib/x86_64-linux-gnu/libdl.so
cp /usr/lib/x86_64-linux-gnu/libnetcdf.so.19 /usr/lib/libnetcdf.so
%environment
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/x86_64-linux-gnu
%runscript
exec /app/Noddy "$@"

13
shell.nix Normal file
View File

@@ -0,0 +1,13 @@
with import <nixpkgs> {};
mkShell {
nativeBuildInputs = [];
buildInputs = [
netcdf
];
LOG_LEVEL = "verbose";
LD_LIBRARY_PATH = lib.makeLibraryPath [ netcdf ];
shellHook = '' '';
}

47
src/Main.fs Normal file
View File

@@ -0,0 +1,47 @@
module Main
open System
open Serilog
open Serilog.Events
open Argu
open NetCDF
open Settings
let configureSerilog level =
let n =
match level with
| 0 -> LogEventLevel.Verbose
| 1 -> LogEventLevel.Debug
| 2 -> LogEventLevel.Information
| 3 -> LogEventLevel.Warning
| _ -> LogEventLevel.Error
LoggerConfiguration()
.MinimumLevel.Is(n)
.WriteTo.Console(standardErrorFromLevel = LogEventLevel.Verbose)
.CreateLogger ()
let colorizer =
function
| ErrorCode.HelpText -> None
| _ -> Some ConsoleColor.Red
let errorHandler = ProcessExiter (colorizer = colorizer)
type Arguments =
| Log_level of int
interface IArgParserTemplate with
member this.Usage =
match this with
| Log_level _ -> "Log level (0 = Verbose, 4 = Error)"
[<EntryPoint>]
let main argv =
printfn "%s" "Start"
let parser =
ArgumentParser.Create<Arguments> (programName = "Excavator", errorHandler = errorHandler)
let args = parser.Parse argv
let loglevel = args.GetResult(Arguments.Log_level, 2)
Log.Logger <- configureSerilog loglevel
0

122
src/NetCDF.fs Normal file
View File

@@ -0,0 +1,122 @@
module NetCDF
open System
open Microsoft.Research.Science.Data.NetCDF4
let readArray3D (a: float[,,]) (inds: int[]) =
let d = Array3D.zeroCreate (Array3D.length1 a) (Array3D.length2 a) inds.Length
inds |> Array.iteri (fun i ind -> d[*, *, i] <- a[*, *, ind])
d
let readArray2D (a: float[,]) (inds: int[]) =
let d = Array2D.zeroCreate (Array2D.length1 a) inds.Length
inds |> Array.iteri (fun i ind -> d[*, i] <- a[*, i])
d
let readArray (a: float[]) (inds: int[]) = inds |> Array.map (fun i -> a[i])
let readNcArray (nc: NetCDFDataSet) (var: string) (inds: int[]) =
let v = nc[var].GetData () :?> float32[] |> Array.map float
readArray v inds
let readNcArray2D (nc: NetCDFDataSet) (var: string) (inds: int[]) =
let v = nc[var].GetData () :?> float32[,] |> Array2D.map float
readArray2D v inds
let readNcFileTime (fname: string) (timeInd: (int * int)) =
let t1, t2 = timeInd
let nc =
NetCDFDataSet.Open (fname, openMode = Microsoft.Research.Science.Data.ResourceOpenMode.ReadOnly)
let time = nc["time"].GetData () :?> float32[]
let Itime = nc["Itime"].GetData () :?> int32[]
let Itime2 = nc["Itime2"].GetData () :?> int32[]
nc.Dispose ()
time[t1..t2], Itime[t1..t2], Itime2[t1..t2]
let readNcFileData (fname: string) (var: string) (grdInd: int) (timeInd: (int * int)) (nSiglays: int) =
//printfn "%s %s %d" fname var grdInd
let t1, t2 = timeInd
let nTimeSteps = t2 - t1 + 1
let nc =
NetCDFDataSet.Open (fname, openMode = Microsoft.Research.Science.Data.ResourceOpenMode.ReadOnly)
//let dataFull = nc[var].GetData() :?> float32[,,] |> Array3D.map float
let dataFull =
nc[var].GetData ([| t1; 0; grdInd |], [| nTimeSteps; nSiglays; 1 |]) :?> float32[,,] //|> Array3D.map float
//printfn "%d %d %d" (Array3D.length1 dataFull) (Array3D.length2 dataFull) (Array3D.length3 dataFull)
nc.Dispose ()
//let data = dataFull[t1..t2, *, grdInd]
let data = dataFull[*, *, 0]
//printfn "%d %d" (Array2D.length1 data) (Array2D.length2 data)
data //|> Array2D.map float32
let readNcFileZeta (fname: string) (nodeInds: int[]) (timeInd: (int * int)) =
printfn "%s %s" fname "zeta"
let t1, t2 = timeInd
let nTimeSteps = t2 - t1 + 1
let data = Array2D.zeroCreate nTimeSteps nodeInds.Length
let nc =
NetCDFDataSet.Open (fname, openMode = Microsoft.Research.Science.Data.ResourceOpenMode.ReadOnly)
let zeta = nc["zeta"].GetData () :?> float32[,]
nc.Dispose ()
nodeInds |> Array.iteri (fun i ind -> data[*, i] <- zeta[t1..t2, ind])
data
let readNcVar (fname: string) (var: string) (nSiglays: int) (nodeInds: int[]) (cellInds: int[]) (timeInd: (int * int)) =
printfn "%s %s" fname var
let t1, t2 = timeInd
let nTimeSteps = t2 - t1 + 1
let grdInd =
match var with
| "u" -> cellInds
| "v" -> cellInds
| _ -> nodeInds
let data = Array3D.zeroCreate nTimeSteps nSiglays grdInd.Length
//printfn "%d %d %d" (Array3D.length1 data) (Array3D.length2 data) (Array3D.length3 data)
grdInd
|> Array.iteri (fun i ind ->
let d = readNcFileData fname var ind timeInd nSiglays
data[*, *, i] <- d)
data
let readNcVarTimeStep
(fname: string)
(var: string)
(nSiglays: int)
(nodeInds: int[])
(cellInds: int[])
(timeInd: (int))
=
let nc =
NetCDFDataSet.Open (fname, openMode = Microsoft.Research.Science.Data.ResourceOpenMode.ReadOnly)
let grdInd, n =
match var with
| "u" -> cellInds, nc.Dimensions["nele"].Length
| "v" -> cellInds, nc.Dimensions["nele"].Length
| _ -> nodeInds, nc.Dimensions["node"].Length
let nc =
NetCDFDataSet.Open (fname, openMode = Microsoft.Research.Science.Data.ResourceOpenMode.ReadOnly)
let d =
nc[var].GetData ([| timeInd; 0; 0 |], [| 1; nSiglays; n |]) :?> float32[,,]
|> Array3D.map float
//let d2 = d1[0, *, *] |> Array2D.map float
readArray3D d grdInd |> Array3D.map float32

29
src/Noddy.fsproj Normal file
View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<Version>1.3.1</Version>
</PropertyGroup>
<ItemGroup>
<Compile Include="Settings.fs" />
<Compile Include="NetCDF.fs" />
<Compile Include="S3.fs" />
<Compile Include="Main.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Argu" Version="6.2.5" />
<PackageReference Include="AWSSDK.S3" Version="3.7.415.25" />
<PackageReference Include="FSharp.Data" Version="6.4.1" />
<PackageReference Include="FSharpPlus" Version="1.7.0" />
<PackageReference Include="MessagePack" Version="3.1.3" />
<PackageReference Include="Oceanbox.FvcomKit" Version="5.12.0" />
<PackageReference Include="sdslite-o" 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" />
<PackageReference Include="Thoth.Json.Net" Version="12.0.0" />
<PackageReference Update="FSharp.Core" Version="9.0.201" />
</ItemGroup>
</Project>

2
src/S3.fs Normal file
View File

@@ -0,0 +1,2 @@
module S3

12
src/Settings.fs Normal file
View File

@@ -0,0 +1,12 @@
module Settings
type Settings = { Setting: string }
let tryGetEnv =
System.Environment.GetEnvironmentVariable
>> function
| null
| "" -> None
| x -> Some x
let mutable projection = CoordSys.UTMn 33

421
src/packages.lock.json Normal file
View File

@@ -0,0 +1,421 @@
{
"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"
}
},
"AWSSDK.S3": {
"type": "Direct",
"requested": "[3.7.415.25, )",
"resolved": "3.7.415.25",
"contentHash": "UhM0VH1NubDx/j1YWDvnY2T1KKpw8kbx63Hd9YWXcjYY0vQIo8CNANwD/+Lg65gATGs+s6MPeFvdqjtQV+oG4Q==",
"dependencies": {
"AWSSDK.Core": "[3.7.402.26, 4.0.0)"
}
},
"FSharp.Core": {
"type": "Direct",
"requested": "[9.0.201, )",
"resolved": "9.0.201",
"contentHash": "Ozq4T0ISTkqTYJ035XW/JkdDDaXofbykvfyVwkjLSqaDZ/4uNXfpf92cjcMI9lf9CxWqmlWHScViPh/4AvnWcw=="
},
"FSharp.Data": {
"type": "Direct",
"requested": "[6.4.1, )",
"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"
}
},
"FSharpPlus": {
"type": "Direct",
"requested": "[1.7.0, )",
"resolved": "1.7.0",
"contentHash": "9+PXT3nG7K5bzgYOzxgwZu5ij25BH7OtMkMJUrWkf+HcfbvsEGCvIf3InF8MCvJ5lO02NfGb9fC8slLEytqw0Q==",
"dependencies": {
"FSharp.Core": "6.0.6"
}
},
"MessagePack": {
"type": "Direct",
"requested": "[3.1.3, )",
"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"
}
},
"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-O": {
"type": "Direct",
"requested": "[2.7.2, )",
"resolved": "2.7.2",
"contentHash": "UzRh4jECBP4Ee/6lDHRowiEMDhT0tPuJd5Fr1Y2lwvKx4Sfk3MzaZBaKuaeJliwvuUm6wEupHoGELWhQVTuwBw==",
"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"
}
},
"AWSSDK.Core": {
"type": "Transitive",
"resolved": "3.7.402.26",
"contentHash": "pChqa8AqDplFfVvJoI1JbxkYuBRmp+UAjNRBnNsh18jEoW/mbazIucJjaKpAKFdSWgQMfinpiU2tWWvlnbq6iQ=="
},
"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"
}
},
"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"
}
},
"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.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.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=="
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.1",
"contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A=="
},
"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"
}
},
"SDSLite.Oceanbox": {
"type": "Transitive",
"resolved": "2.7.3",
"contentHash": "tmTPsEUmQhwaCzHwuSw7he2FfjcVpZ/Sy2ewfTwm1IKnwOZazKouTS5t4LNUpaGtjK1o/gdfz1b+0KxXnUl97g==",
"dependencies": {
"DynamicInterop": "0.9.1"
}
},
"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.3",
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
},
"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.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"
}
}
}
}
}