@explorable-viz/fluid 0.7.30 → 0.7.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,35 +8,50 @@ Fluid is an experimental programming language which integrates a bidirectional d
8
8
  ## Installation
9
9
 
10
10
  ### Software required
11
- - Windows users: Ubuntu (WSL)
12
11
  - git
13
12
  - Node.js >=14.0.0
14
- - yarn
13
+ - yarn >= 1.22
15
14
 
16
- ### For Windows Users
17
- - Clone the repository under Ubuntu WSL
15
+ Additionally, for Windows users only:
18
16
 
19
- ### Notes
20
- - Run `./script/setup/dev-setup.sh` after cloning repository
21
- - Avoid having PureScript installed globally
22
- - `Add Npm Path` is selected in PureScript IDE extension settings
23
- - VSCode for Windows users:
24
- - Launch VSCode through Ubuntu (WSL) terminal
25
- - Install WSL extension in VSCode
17
+ - [Ubuntu WSL](https://ubuntu.com/desktop/wsl)
18
+
19
+ ### Building
20
+
21
+ - Clone the repository (for Windows users, do this under the Ubuntu WSL)
22
+ - Run `./script/setup/dev-setup.sh` from the top-level directory
23
+ - Run `yarn build`
26
24
 
27
25
  #### Running tests on command line
28
- - `yarn build` and then `yarn test-all`
26
+
27
+ After building, tests can be run from the command line via `yarn test-all`
29
28
 
30
29
  #### Running tests in browser
31
- - As per command-line tests above, but run `yarn test-browser`
32
- - Hit Debug in the browser window that opens, and then open Developer Tools or equivalent
30
+ - As per command-line tests above, but run `yarn test-browser`, which opens
31
+ a browser window.
32
+ - To observe the status of tests, click `Debug` in the browser window, and then open the JavaScript Console for your browser (e.g., via the Developer Tools).
33
33
 
34
34
  #### Running the fluid.org website locally
35
- - `yarn build`
36
- - `yarn serve fluid-org`
35
+
36
+ (Assumes you have already run `yarn build`)
37
+
38
+ - `yarn serve fluid-org` (you may be prompted to proceed: type `y`).
37
39
  - Open a browser at the served URL (usually `127.0.0.1:8080`)
38
40
 
39
41
  #### Run Puppeteer tests for page Y of website X
42
+
40
43
  Rebuild with `puppeteerTests.headless` set to `false` to run in browser. Then:
41
44
  - `yarn bundle-website X`
42
45
  - `./script/test-page.sh X X.Y`
46
+
47
+ ## Development via VS Code
48
+
49
+ The following are some notes on developing Fluid using VS Code.
50
+
51
+ - Avoid having PureScript installed globally
52
+ - Install the PureScript IDE extension
53
+ - In the PureScript IDE extension settings, select `Add Npm Path`
54
+
55
+ - For Windows users:
56
+ - Launch VSCode through Ubuntu (WSL) terminal
57
+ - Install WSL extension in VSCode
@@ -0,0 +1,194 @@
1
+ [
2
+ {
3
+ model: "NorESM2-LM",
4
+ world: 15.76,
5
+ world_historical: 14.5,
6
+ changed: 1.01
7
+ },
8
+ {
9
+ model: "NorESM2-MM",
10
+ world: 15.22,
11
+ world_historical: 13.92,
12
+ changed: 1.05
13
+ },
14
+ {
15
+ model: "GFDL-ESM4",
16
+ world: 14.82,
17
+ world_historical: 13.5,
18
+ changed: 1.07
19
+ },
20
+ {
21
+ model: "CAMS-CSM1-0",
22
+ world: 15.13,
23
+ world_historical: 13.8,
24
+ changed: 1.09
25
+ },
26
+ {
27
+ model: "BCC-CSM2-MR",
28
+ world: 16.29,
29
+ world_historical: 14.82,
30
+ changed: 1.22
31
+ },
32
+ {
33
+ model: "INM-CM4-8",
34
+ world: 14.79,
35
+ world_historical: 13.31,
36
+ changed: 1.23
37
+ },
38
+ {
39
+ model: "FGOALS-g3",
40
+ world: 14.3,
41
+ world_historical: 12.81,
42
+ changed: 1.24
43
+ },
44
+ {
45
+ model: "MPI-ESM1-2-LR",
46
+ world: 15.03,
47
+ world_historical: 13.54,
48
+ changed: 1.24
49
+ },
50
+ {
51
+ model: "INM-CM5-0",
52
+ world: 14.64,
53
+ world_historical: 13.14,
54
+ changed: 1.25
55
+ },
56
+ {
57
+ model: "IITM-ESM",
58
+ world: 15.56,
59
+ world_historical: 13.99,
60
+ changed: 1.32
61
+ },
62
+ {
63
+ model: "MPI-ESM1-2-HR",
64
+ world: 15.51,
65
+ world_historical: 13.94,
66
+ changed: 1.32
67
+ },
68
+ {
69
+ model: "MIROC6",
70
+ world: 16.72,
71
+ world_historical: 15.12,
72
+ changed: 1.35
73
+ },
74
+ {
75
+ model: "MIROC-ES2L",
76
+ world: 16.6,
77
+ world_historical: 14.96,
78
+ changed: 1.39
79
+ },
80
+ {
81
+ model: "MRI-ESM2-0",
82
+ world: 15.47,
83
+ world_historical: 13.74,
84
+ changed: 1.47
85
+ },
86
+ {
87
+ model: "KIOST-ESM",
88
+ world: 14.22,
89
+ world_historical: 12.4,
90
+ changed: 1.57
91
+ },
92
+ {
93
+ model: "AWI-CM-1-1-MR",
94
+ world: 15.72,
95
+ world_historical: 13.76,
96
+ changed: 1.72
97
+ },
98
+ {
99
+ model: "NESM3",
100
+ world: 15.64,
101
+ world_historical: 13.66,
102
+ changed: 1.73
103
+ },
104
+ {
105
+ model: "ACCESS-ESM1-5",
106
+ world: 16.54,
107
+ world_historical: 14.54,
108
+ changed: 1.75
109
+ },
110
+ {
111
+ model: "CNRM-ESM2-1",
112
+ world: 15.65,
113
+ world_historical: 13.64,
114
+ changed: 1.76
115
+ },
116
+ {
117
+ model: "EC-Earth3",
118
+ world: 16.02,
119
+ world_historical: 13.94,
120
+ changed: 1.83
121
+ },
122
+ {
123
+ model: "CNRM-CM6-1",
124
+ world: 15.0,
125
+ world_historical: 12.88,
126
+ changed: 1.87
127
+ },
128
+ {
129
+ model: "CESM2",
130
+ world: 16.21,
131
+ world_historical: 14.02,
132
+ changed: 1.94
133
+ },
134
+ {
135
+ model: "IPSL-CM6A-LR",
136
+ world: 15.17,
137
+ world_historical: 12.88,
138
+ changed: 2.04
139
+ },
140
+ {
141
+ model: "CESM2-WACCM",
142
+ world: 16.23,
143
+ world_historical: 13.84,
144
+ changed: 2.14
145
+ },
146
+ {
147
+ model: "ACCESS-CM2",
148
+ world: 16.27,
149
+ world_historical: 13.84,
150
+ changed: 2.18
151
+ },
152
+ {
153
+ model: "UKESM1-0-LL",
154
+ world: 16.06,
155
+ world_historical: 13.45,
156
+ changed: 2.36
157
+ },
158
+ {
159
+ model: "EC-Earth3-Veg",
160
+ world: 16.15,
161
+ world_historical: 13.53,
162
+ changed: 2.37
163
+ },
164
+ {
165
+ model: "HadGEM3-GC31-LL",
166
+ world: 16.34,
167
+ world_historical: 13.71,
168
+ changed: 2.38
169
+ },
170
+ {
171
+ model: "CMCC-CM2-SR5",
172
+ world: 16.87,
173
+ world_historical: 14.1,
174
+ changed: 2.52
175
+ },
176
+ {
177
+ model: "CNRM-CM6-1-HR",
178
+ world: 15.12,
179
+ world_historical: 12.32,
180
+ changed: 2.54
181
+ },
182
+ {
183
+ model: "CanESM5",
184
+ world: 16.39,
185
+ world_historical: 13.54,
186
+ changed: 2.61
187
+ },
188
+ {
189
+ model: "KACE-1-0-G",
190
+ world: 16.47,
191
+ world_historical: 13.55,
192
+ changed: 2.67
193
+ }
194
+ ]
@@ -1 +1 @@
1
- [ x | {fst: x, snd: []} <- [{fst: 5, third: "hello", snd: []}, {fst: 6, snd: [7, 8]}] ]
1
+ [ x | {fst: x, snd: []} <- [{fst: 5, third: "hello", snd: []}, {fst: 6, snd: [7, 8]}] ]
@@ -0,0 +1,2 @@
1
+ let data = mergesort [ x.changed | x <- ssp126]
2
+ in qcut data [ 5, 50, 95 ]
@@ -264,3 +264,13 @@ let nub xs =
264
264
  -- Int -> Int -> [a] -> [a]
265
265
  let slice begin end xs =
266
266
  take (end - begin) (drop begin xs);
267
+
268
+
269
+ -- (a -> Boolean) -> List a -> (List a, List a)
270
+ let splitOn p data =
271
+ let go fls trs [] = (reverse fls, reverse trs);
272
+ go fls trs (x : xs) =
273
+ if p x
274
+ then go fls (x : trs) xs
275
+ else go (x : fls) trs xs
276
+ in go [] [] data;
@@ -0,0 +1,57 @@
1
+ let split [] = ([], []);
2
+ split (x : xs) =
3
+ let (ys, zs) = split xs in (x : zs, ys);
4
+
5
+ let merge xs ys =
6
+ match (xs, ys) as {
7
+ ([], _) -> ys;
8
+ (x : xs', []) -> xs;
9
+ (x : xs', y : ys') ->
10
+ if x < y
11
+ then x : merge xs' ys
12
+ else y : merge xs ys'
13
+ };
14
+
15
+ let mergesort xs =
16
+ if length xs < 2
17
+ then xs
18
+ else
19
+ let (ys, zs) = split xs in
20
+ merge (mergesort ys) (mergesort zs);
21
+
22
+ -- assume data is sorted
23
+ let findQuantile q p data =
24
+ let rank = (p / q) * (length data - 1)
25
+ in if rank == floor rank
26
+ then nth rank data
27
+ else let x1 = floor rank;
28
+ x2 = ceiling rank;
29
+ left = nth x1 data;
30
+ right = nth x2 data
31
+ in left + (rank - x1) * (right - left);
32
+
33
+ let findPercentile = findQuantile 100;
34
+
35
+ let accumBins data Nil = [];
36
+ accumBins data [l] = [];
37
+ accumBins data (l : r : es) =
38
+ let (ge, le) = splitOn (fun x -> x <= r) data
39
+ in (le , r - l) : accumBins ge (r : es);
40
+
41
+ let cut data nbins =
42
+ let low = minimum data;
43
+ binwidth = (maximum data - low) / nbins;
44
+ edges = [ low + (x * binwidth) | x <- enumFromTo 0 nbins ]
45
+ in accumBins data edges;
46
+
47
+ let qcut data qs =
48
+ let low = minimum data;
49
+ high = maximum data;
50
+ edges = append (low : [ findPercentile x data | x <- qs], [high])
51
+ in accumBins data edges;
52
+
53
+ let likelihoodLE data target =
54
+ length (filter (fun x -> x <= target) data) / length data;
55
+
56
+ let likelihoodGE data target =
57
+ length (filter (fun x -> x >= target) data) / length data;
@@ -25066,7 +25066,7 @@ var toAff2 = (f) => (a) => (b) => {
25066
25066
  // output-es/Module.Node/index.js
25067
25067
  var loadFile = (v) => (v1) => (dictMonadAff) => {
25068
25068
  const Monad0 = dictMonadAff.MonadEffect0().Monad0();
25069
- return (dictMonadError) => Monad0.Bind1().bind(dictMonadAff.liftAff(toAff2(readTextFile)(ASCII)(v + "/" + v1 + ".fld")))((buffer) => Monad0.Applicative0().pure(buffer));
25069
+ return (dictMonadError) => Monad0.Bind1().bind(dictMonadAff.liftAff(toAff2(readTextFile)(UTF8)(v + "/" + v1 + ".fld")))((buffer) => Monad0.Applicative0().pure(buffer));
25070
25070
  };
25071
25071
 
25072
25072
  // output-es/Node.ChildProcess/foreign.js
@@ -28365,41 +28365,6 @@ var graphEval2 = /* @__PURE__ */ graphEval(monadErrorAff);
28365
28365
  var fromFoldable29 = /* @__PURE__ */ (() => fromFoldableImpl(foldableList.foldr))();
28366
28366
  var Evaluate = (value0) => $Command("Evaluate", value0);
28367
28367
  var Publish = (value0) => (value1) => $Command("Publish", value0, value1);
28368
- var publish = /* @__PURE__ */ (() => $Parser(
28369
- "MultP",
28370
- $MultPE(
28371
- parserFunctor.map(Publish)(parserFunctor.map(Folder)(option(readerAsk)((() => {
28372
- const $0 = help("root directory of website under dist/");
28373
- const $1 = $0._2._2.tag === "Nothing" ? Nothing : $0._2._2;
28374
- return $Mod(
28375
- (x) => $0._1({
28376
- optNames: [$OptName("OptShort", "w"), $OptName("OptLong", "website"), ...x.optNames],
28377
- optCompleter: x.optCompleter,
28378
- optNoArgError: x.optNoArgError
28379
- }),
28380
- $DefaultProp($Maybe("Just", "Misc"), $1.tag === "Nothing" ? Nothing : $1),
28381
- (x) => $0._3(x)
28382
- );
28383
- })()))),
28384
- $Parser(
28385
- "AltP",
28386
- flag$p(true)(foldableArray.foldMap(modMonoid)(identity3)([
28387
- $Mod(
28388
- flagFieldsHasName.name($OptName("OptLong", "local")),
28389
- $DefaultProp(Nothing, Nothing),
28390
- identity26
28391
- ),
28392
- $Mod(
28393
- flagFieldsHasName.name($OptName("OptShort", "l")),
28394
- $DefaultProp(Nothing, Nothing),
28395
- identity26
28396
- ),
28397
- help("Are you publishing from source (false), or an npm package (true)?")
28398
- ])),
28399
- $Parser("NilP", false)
28400
- )
28401
- )
28402
- ))();
28403
28368
  var parseImports = /* @__PURE__ */ $Parser(
28404
28369
  "BindP",
28405
28370
  /* @__PURE__ */ manyM(/* @__PURE__ */ option(readerAsk)(/* @__PURE__ */ (() => {
@@ -28417,7 +28382,7 @@ var parseImports = /* @__PURE__ */ $Parser(
28417
28382
  );
28418
28383
  })()))
28419
28384
  );
28420
- var output = (v) => {
28385
+ var evaluate = (v) => {
28421
28386
  const $0 = v._1.fileName;
28422
28387
  return _bind(loadProgCxt2(v._1.imports)(v._1.datasets))((progCxt) => _bind(prepConfig2($0)(progCxt))((v1) => _bind(graphEval2(v1.gconfig)(v1.e))((v2) => _pure($Val(
28423
28388
  void 0,
@@ -28436,25 +28401,26 @@ var copyOptions = {
28436
28401
  encoding: Nothing,
28437
28402
  shell: Nothing
28438
28403
  };
28439
- var copyFiles = (website) => (b) => exec2(b ? "./node_modules/@explorable-viz/fluid/script/bundle-website.sh -w " + website + " -r true" : "./script/bundle-website.sh -w " + website)(copyOptions)((v) => {
28404
+ var publish = (website) => ($$package) => exec2($$package ? "./node_modules/@explorable-viz/fluid/script/bundle-website.sh -w " + website + " -r true" : "./script/bundle-website.sh -w " + website)(copyOptions)((v) => {
28440
28405
  if (v.error.tag === "Just") {
28441
28406
  return log(showErrorImpl(v.error._1));
28442
28407
  }
28443
28408
  if (v.error.tag === "Nothing") {
28444
28409
  const $0 = toString2(monadEffect)(ASCII)(v.stdout);
28445
28410
  return () => {
28446
- const out = $0();
28447
- return log(out)();
28411
+ const $1 = $0();
28412
+ return log($1)();
28448
28413
  };
28449
28414
  }
28450
28415
  fail();
28451
28416
  });
28452
28417
  var dispatchCommand = (v) => {
28453
28418
  if (v.tag === "Evaluate") {
28454
- return _bind(output(v._1))((out) => _liftEffect(log(intercalate4("\n")(removeDocWS(prettyVal(highlightableUnit).pretty(out)).lines))));
28419
+ return _bind(evaluate(v._1))((v1) => _liftEffect(log(intercalate4("\n")(removeDocWS(prettyVal(highlightableUnit).pretty(v1)).lines))));
28455
28420
  }
28456
28421
  if (v.tag === "Publish") {
28457
- return _bind(_liftEffect(copyFiles(v._1)(v._2)))(() => _liftEffect(log("Published")));
28422
+ return _bind(_map((v$1) => {
28423
+ })(_liftEffect(publish(v._1)(v._2))))(() => _liftEffect(log("Published")));
28458
28424
  }
28459
28425
  fail();
28460
28426
  };
@@ -28550,9 +28516,47 @@ var program = /* @__PURE__ */ (() => $Parser(
28550
28516
  })())
28551
28517
  )
28552
28518
  ))();
28519
+ var commands = /* @__PURE__ */ (() => ({
28520
+ publish: $Parser(
28521
+ "MultP",
28522
+ $MultPE(
28523
+ parserFunctor.map(Publish)(parserFunctor.map(Folder)(option(readerAsk)((() => {
28524
+ const $0 = help("root directory of website under dist/");
28525
+ const $1 = $0._2._2.tag === "Nothing" ? Nothing : $0._2._2;
28526
+ return $Mod(
28527
+ (x) => $0._1({
28528
+ optNames: [$OptName("OptShort", "w"), $OptName("OptLong", "website"), ...x.optNames],
28529
+ optCompleter: x.optCompleter,
28530
+ optNoArgError: x.optNoArgError
28531
+ }),
28532
+ $DefaultProp($Maybe("Just", "Misc"), $1.tag === "Nothing" ? Nothing : $1),
28533
+ (x) => $0._3(x)
28534
+ );
28535
+ })()))),
28536
+ $Parser(
28537
+ "AltP",
28538
+ flag$p(true)(foldableArray.foldMap(modMonoid)(identity3)([
28539
+ $Mod(
28540
+ flagFieldsHasName.name($OptName("OptLong", "local")),
28541
+ $DefaultProp(Nothing, Nothing),
28542
+ identity26
28543
+ ),
28544
+ $Mod(
28545
+ flagFieldsHasName.name($OptName("OptShort", "l")),
28546
+ $DefaultProp(Nothing, Nothing),
28547
+ identity26
28548
+ ),
28549
+ help("Are you publishing from source (false), or an npm package (true)?")
28550
+ ])),
28551
+ $Parser("NilP", false)
28552
+ )
28553
+ )
28554
+ ),
28555
+ evaluate: parserFunctor.map(Evaluate)(program)
28556
+ }))();
28553
28557
  var commandParser = /* @__PURE__ */ subparser(/* @__PURE__ */ (() => {
28554
28558
  const $0 = command("evaluate")(progDesc("Evaluate a file")({
28555
- infoParser: parserFunctor.map(Evaluate)(program),
28559
+ infoParser: commands.evaluate,
28556
28560
  infoFullDesc: true,
28557
28561
  infoProgDesc: mempty12,
28558
28562
  infoHeader: mempty12,
@@ -28561,7 +28565,7 @@ var commandParser = /* @__PURE__ */ subparser(/* @__PURE__ */ (() => {
28561
28565
  infoPolicy: Intersperse
28562
28566
  }));
28563
28567
  const $1 = command("publish")(progDesc("Publish a file")({
28564
- infoParser: publish,
28568
+ infoParser: commands.publish,
28565
28569
  infoFullDesc: true,
28566
28570
  infoProgDesc: mempty12,
28567
28571
  infoHeader: mempty12,
@@ -44249,7 +44249,7 @@ var gDecodeJsonCons = (dictDecodeJsonField) => (dictGDecodeJson) => (dictIsSymbo
44249
44249
  // output-es/Effect.Aff.Class/index.js
44250
44250
  var monadAffAff = { liftAff: (x2) => x2, MonadEffect0: () => monadEffectAff };
44251
44251
 
44252
- // output-es/Website.LoadFigure/index.js
44252
+ // output-es/App.LoadFigure/index.js
44253
44253
  var gDecodeJsonCons2 = /* @__PURE__ */ gDecodeJsonCons(/* @__PURE__ */ (() => {
44254
44254
  const $0 = decodeArray(caseJsonString($Either(
44255
44255
  "Left",
@@ -44264,7 +44264,6 @@ var gDecodeJsonCons2 = /* @__PURE__ */ gDecodeJsonCons(/* @__PURE__ */ (() => {
44264
44264
  }
44265
44265
  };
44266
44266
  })());
44267
- var specToCxt = (spec) => ({ datasets: spec.datasets, imports: spec.imports, file: spec.file, inputs: spec.inputs });
44268
44267
  var jsonToSpec = /* @__PURE__ */ (() => decodeRecord(gDecodeJsonCons((() => {
44269
44268
  const $0 = decodeArray(decodeTuple(caseJsonString($Either(
44270
44269
  "Left",
@@ -44299,6 +44298,7 @@ var jsonToSpec = /* @__PURE__ */ (() => decodeRecord(gDecodeJsonCons((() => {
44299
44298
  })(gDecodeJsonCons2(gDecodeJsonCons2(gDecodeJsonNil)({ reflectSymbol: () => "inputs" })()())({ reflectSymbol: () => "imports" })()())({
44300
44299
  reflectSymbol: () => "file"
44301
44300
  })()())({ reflectSymbol: () => "datasets" })()())().decodeJson)();
44301
+ var figSpecFromJson = (spec) => ({ datasets: spec.datasets, imports: spec.imports, file: spec.file, inputs: spec.inputs });
44302
44302
  var loadFigure = (fileName) => runAffs_((v) => drawFig(v._1)(v._2))([
44303
44303
  _bind($$get(driver)($ResponseFormat("Json", identity))(fileName))((result) => {
44304
44304
  if (result.tag === "Left") {
@@ -44319,8 +44319,8 @@ var loadFigure = (fileName) => runAffs_((v) => drawFig(v._1)(v._2))([
44319
44319
  var drawCode2 = (folder) => (file) => runAffs_(drawFile)([loadFile$p(folder)(file)(monadAffAff)(monadErrorAff)]);
44320
44320
  export {
44321
44321
  drawCode2 as drawCode,
44322
+ figSpecFromJson,
44322
44323
  gDecodeJsonCons2 as gDecodeJsonCons,
44323
44324
  jsonToSpec,
44324
- loadFigure,
44325
- specToCxt
44325
+ loadFigure
44326
44326
  };
@@ -0,0 +1,36 @@
1
+ const express = require('express');
2
+ const serve = require('express-static');
3
+ require('http-shutdown').extend();
4
+
5
+ const app = express();
6
+
7
+ const root = __dirname + '/dist/' + process.argv[3];
8
+ app.use(serve(root));
9
+
10
+ const server = app.listen(8080, function() {
11
+ console.log("Serving content from " + root);
12
+ }).withShutdown();
13
+
14
+ (async () => {
15
+ try {
16
+ const module = process.argv[2]
17
+ console.log('Loading Puppeteer test module:', module);
18
+ import(module).then(({ main }) => {
19
+ main().then(serverDown);
20
+ }).catch(err => {
21
+ console.error("Failed to load PureScript output:", err);
22
+ });
23
+ } catch (error) {
24
+ console.error('Error:', error);
25
+ }
26
+ })();
27
+
28
+ function serverDown() {
29
+ console.log('Shutting down server')
30
+ server.shutdown(function(err) {
31
+ if (err) {
32
+ return console.log('shutdown failed', err.message);
33
+ }
34
+ console.log('Everything is cleanly shut down.');
35
+ });
36
+ }