@explorable-viz/fluid 0.7.30 → 0.7.32

Sign up to get free protection for your applications and to get access to all the features.
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
+ }