From 4a634b27fc81b410fb12397f30fb292c2009d01a Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 27 Nov 2019 12:18:58 -0800 Subject: [PATCH 01/25] implement working pie charts --- src/runtime-arr/chart.arr | 115 ++++++++++++++++++++++++++------- src/runtime/chart-lib.arr.js | 14 +++- src/runtime/chart-lib.arr.json | 1 + 3 files changed, 105 insertions(+), 25 deletions(-) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index b0931a2ae4..b43d1acc56 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -39,6 +39,10 @@ fun to-table2(xs :: L.List, ys :: L.List) -> TableIntern: L.to-raw-array(L.map2({(x, y): [G.raw-array: x, y]}, xs, ys)) end +fun to-table3(xs :: L.List, ys :: L.List, zs :: L.List) -> TableIntern: + L.to-raw-array(L.map3({(x, y, z): [G.raw-array: x, y, z]}, xs, ys, zs)) +end + # TODO(tiffany): add in get-vs-from-img after VS is implemented ################################################################################ @@ -94,6 +98,12 @@ end # DEFAULT VALUES ################################################################################ +type PieChartSeries = { + tab :: TableIntern, +} + +default-pie-chart-series = {} + type BarChartSeries = { tab :: TableIntern, legends :: RawArray, @@ -118,6 +128,15 @@ default-chart-window-object :: ChartWindowObject = { render: method(self): G.raise('unimplemented') end, } +type PieChartWindowObject = { + title :: String, + width :: Number, + height :: Number, + render :: ( -> IM.Image), +} + +default-pie-chart-window-object :: PieChartWindowObject = default-chart-window-object + type BarChartWindowObject = { title :: String, width :: Number, @@ -141,9 +160,12 @@ default-bar-chart-window-object :: BarChartWindowObject = default-chart-window-o ################################################################################ data DataSeries: + | pie-chart-series(obj :: PieChartSeries) with: + is-single: true, + #constr: {(): pie-chart-series}, | bar-chart-series(obj :: BarChartSeries) with: is-single: true, - constr: {(): bar-chart-series}, + #constr: {(): bar-chart-series}, # TODO(tiffany): add _output and test get-vs-from-img after VS is implemented end @@ -156,30 +178,50 @@ fun check-chart-window(p :: ChartWindowObject) -> Nothing: end data ChartWindow: + | pie-chart-window(obj :: PieChartWindowObject) with: + #constr: {(): pie-chart-window}, + title: method(self, title :: String): pie-chart-window(self.obj.{title: title}) end, + width: method(self, width :: Number): pie-chart-window(self.obj.{width: width}) end, + height: method(self, height :: Number): pie-chart-window(self.obj.{height: height}) end, + display: method(self): + _ = check-chart-window(self.obj) + self.obj.{interact: true}.render() + end, + get-image: method(self): + _ = check-chart-window(self.obj) + self.obj.{interact: false}.render() + end, | bar-chart-window(obj :: BarChartWindowObject) with: - constr: {(): bar-chart-window}, - x-axis: method(self, x-axis :: String): self.constr()(self.obj.{x-axis: x-axis}) end, - y-axis: method(self, y-axis :: String): self.constr()(self.obj.{y-axis: y-axis}) end, - y-min: method(self, y-min :: Number): self.constr()(self.obj.{y-min: O.some(y-min)}) end, - y-max: method(self, y-max :: Number): self.constr()(self.obj.{y-max: O.some(y-max)}) end, -sharing: - method display(self): - _ = check-chart-window(self.obj) - self.obj.{interact: true}.render() - end, - method get-image(self): - _ = check-chart-window(self.obj) - self.obj.{interact: false}.render() - end, - method title(self, title :: String): - self.constr()(self.obj.{title: title}) - end, - method width(self, width :: Number): - self.constr()(self.obj.{width: width}) - end, - method height(self, height :: Number): - self.constr()(self.obj.{height: height}) - end, + #constr: {(): bar-chart-window}, + x-axis: method(self, x-axis :: String): bar-chart-window(self.obj.{x-axis: x-axis}) end, + y-axis: method(self, y-axis :: String): bar-chart-window(self.obj.{y-axis: y-axis}) end, + y-min: method(self, y-min :: Number): bar-chart-window(self.obj.{y-min: O.some(y-min)}) end, + y-max: method(self, y-max :: Number): bar-chart-window(self.obj.{y-max: O.some(y-max)}) end, + title: method(self, title :: String): bar-chart-window(self.obj.{title: title}) end, + width: method(self, width :: Number): bar-chart-window(self.obj.{width: width}) end, + height: method(self, height :: Number): bar-chart-window(self.obj.{height: height}) end, + display: method(self): + _ = check-chart-window(self.obj) + self.obj.{interact: true}.render() + end, + get-image: method(self): + _ = check-chart-window(self.obj) + self.obj.{interact: false}.render() + end, +#sharing: + # TODO(tiffany): add the following 3 methods to every ChartWindow + # title: method(self, title :: String): self.constr()(self.obj.{title: title}) end, + # width: method(self, width :: Number): self.constr()(self.obj.{width: width}) end, + # height: method(self, height :: Number): self.constr()(self.obj.{height: height}) end, + #display: method(self): + # _ = check-chart-window(self.obj) + # self.obj.{interact: true}.render() + # end, + # get-image: method(self): + # _ = check-chart-window(self.obj) + # self.obj.{interact: false}.render() + # end, + # # TODO(tiffany): add _output and test get-vs-from-img after VS is implemented end @@ -187,6 +229,27 @@ end # FUNCTIONS ################################################################################ +fun pie-chart-from-list(labels :: L.List, values :: L.List) -> DataSeries block: + doc: ``` + Consume labels, a list of string, and values, a list of numbers + and construct a pie chart + ``` + label-length = L.length(labels) + value-length = L.length(values) + when label-length <> value-length: + G.raise('pie-chart: labels and values should have the same length') + end + when label-length == 0: + G.raise('pie-chart: need at least one data') + end + # TODO(tiffany): uncomment after implementing each + #values.each(check-num) + #labels.each(check-string) + pie-chart-series(default-pie-chart-series.{ + tab: to-table2(labels, values) + }) +end + fun bar-chart-from-list(labels :: L.List, values :: L.List) -> DataSeries block: doc: ``` Consume labels, a list of string, and values, a list of numbers @@ -214,6 +277,10 @@ end fun render-chart(s :: DataSeries) -> ChartWindow: doc: 'Render it!' cases (DataSeries) s: + | pie-chart-series(obj) => + pie-chart-window(default-pie-chart-window-object.{ + render: method(self): CL.pie-chart(obj.tab) end + }) | bar-chart-series(obj) => bar-chart-window(default-bar-chart-window-object.{ render: method(self): diff --git a/src/runtime/chart-lib.arr.js b/src/runtime/chart-lib.arr.js index fb4f7fd42e..ee592a25bd 100644 --- a/src/runtime/chart-lib.arr.js +++ b/src/runtime/chart-lib.arr.js @@ -20,7 +20,6 @@ function checkColor(val) { /* @stopify flat */ function barChart(tableFromRawArray) { headers = ["",""]; - return { "$brand": "chart", "chartType": "BarChart", @@ -39,6 +38,16 @@ function barChartFromTable(table) { }; } +/* @stopify flat */ +function pieChart(tableFromRawArray) { + return { + "$brand": "chart", + "chartType": "PieChart", + "_headers": ["",""], + "_rows": tableFromRawArray + }; +} + /* @stopify flat */ function pieChartFromTable(table) { return { @@ -89,6 +98,9 @@ return module.exports = { "bar-chart-from-table": /* @stopify flat */ function (table) { return barChartFromTable(table); }, + "pie-chart": /* @stopify flat */ function (tableFromRawArray) { + return pieChart(tableFromRawArray); + }, "pie-chart-from-table": /* @stopify flat */ function (table) { return pieChartFromTable(table); }, diff --git a/src/runtime/chart-lib.arr.json b/src/runtime/chart-lib.arr.json index ef0ec1aa29..1dd3e38a39 100644 --- a/src/runtime/chart-lib.arr.json +++ b/src/runtime/chart-lib.arr.json @@ -19,6 +19,7 @@ "check-color": ["arrow", ["Any"], "Any"], "bar-chart": ["arrow", ["rOfR"], "Chart"], "bar-chart-from-table": ["arrow", ["Table"], "Chart"], + "pie-chart": ["arrow", ["rOfR"], "Chart"], "pie-chart-from-table": ["arrow", ["Table"], "Chart"], "histogram-from-table": ["arrow", ["Table"], "Chart"], "scatter-chart-from-table": ["arrow", ["Table"], "Chart"], From 660258d65490eaca4a5ea649643963c15d1f9a7d Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 27 Nov 2019 12:33:56 -0800 Subject: [PATCH 02/25] clean up comments --- src/runtime-arr/chart.arr | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index b43d1acc56..cd5c0a68ea 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -162,10 +162,8 @@ default-bar-chart-window-object :: BarChartWindowObject = default-chart-window-o data DataSeries: | pie-chart-series(obj :: PieChartSeries) with: is-single: true, - #constr: {(): pie-chart-series}, | bar-chart-series(obj :: BarChartSeries) with: is-single: true, - #constr: {(): bar-chart-series}, # TODO(tiffany): add _output and test get-vs-from-img after VS is implemented end @@ -209,19 +207,20 @@ data ChartWindow: self.obj.{interact: false}.render() end, #sharing: + # TODO(tiffany): add the following 3 methods to every ChartWindow # title: method(self, title :: String): self.constr()(self.obj.{title: title}) end, # width: method(self, width :: Number): self.constr()(self.obj.{width: width}) end, # height: method(self, height :: Number): self.constr()(self.obj.{height: height}) end, - #display: method(self): - # _ = check-chart-window(self.obj) - # self.obj.{interact: true}.render() - # end, - # get-image: method(self): - # _ = check-chart-window(self.obj) - # self.obj.{interact: false}.render() - # end, - # + # display: method(self): + # _ = check-chart-window(self.obj) + # self.obj.{interact: true}.render() + # end, + # get-image: method(self): + # _ = check-chart-window(self.obj) + # self.obj.{interact: false}.render() + # end, + # TODO(tiffany): add _output and test get-vs-from-img after VS is implemented end From 07e66b6689966a50c40c6585ab8e209c2673dffa Mon Sep 17 00:00:00 2001 From: thao13039 Date: Sun, 1 Dec 2019 23:01:17 -0800 Subject: [PATCH 03/25] implement merge bounding box --- src/runtime-arr/chart.arr | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index cd5c0a68ea..7a9a1a8843 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -94,6 +94,24 @@ fun get-bounding-box(ps :: L.List) -> BoundingBox: end end +fun merge-bounding-box(bs :: L.List) -> BoundingBox: + for L.fold(prev from default-bounding-box, e from bs): + ask: + | e.is-valid and prev.is-valid then: + default-bounding-box.{ + x-min: G.num-min(e.x-min, prev.x-min), + x-max: G.num-max(e.x-max, prev.x-max), + y-min: G.num-min(e.y-min, prev.y-min), + y-max: G.num-max(e.y-max, prev.y-max), + is-valid: true, + } + | e.is-valid then: e + | prev.is-valid then: prev + | otherwise: default-bounding-box + end + end +end + ################################################################################ # DEFAULT VALUES ################################################################################ From df0533aa64db28ab2256abe7bc0f43c768695cb9 Mon Sep 17 00:00:00 2001 From: thao13039 Date: Sun, 1 Dec 2019 23:01:52 -0800 Subject: [PATCH 04/25] add either import --- src/runtime-arr/chart.arr | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 7a9a1a8843..9578aafef2 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -3,6 +3,7 @@ provide-types * import global as G import chart-lib as CL +import either as E import image as IM import list as L import option as O From 8ed8dd629977798deaad12f1c1222bfae6cca877 Mon Sep 17 00:00:00 2001 From: thao13039 Date: Sun, 1 Dec 2019 23:05:37 -0800 Subject: [PATCH 05/25] add ScatterPlotSeries type and default --- src/runtime-arr/chart.arr | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 9578aafef2..17f83733dc 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -131,6 +131,19 @@ type BarChartSeries = { default-bar-chart-series = {} +type ScatterPlotSeries = { + ps :: L.List, + color :: Option, + legend :: String, + point-size :: Number, +} + +default-scatter-plot-series = { + color: none, + legend: '', + point-size: 7, +} + ########### type ChartWindowObject = { From 650afbb0f5762dcc20089d2221ad4199945c759c Mon Sep 17 00:00:00 2001 From: thao13039 Date: Sun, 1 Dec 2019 23:06:14 -0800 Subject: [PATCH 06/25] add PlotChartWindowObject type and default --- src/runtime-arr/chart.arr | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 17f83733dc..f2525effe2 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -187,6 +187,30 @@ default-bar-chart-window-object :: BarChartWindowObject = default-chart-window-o y-max: O.none, } +type PlotChartWindowObject = { + title :: String, + width :: Number, + height :: Number, + render :: ( -> IM.Image), + x-axis :: String, + y-axis :: String, + x-min :: Option, + x-max :: Option, + x-max :: Option, + y-max :: Option, + num-samples :: Number, +} + +default-plot-chart-window-object :: PlotChartWindowObject = default-chart-window-object.{ + x-axis: '', + y-axis: '', + x-min: none, + x-max: none, + y-min: none, + y-max: none, + num-samples: 1000, +} + ################################################################################ # DATA DEFINITIONS ################################################################################ From 6c5fcfd3966a4767798ac1bb1dc974181ecbd99b Mon Sep 17 00:00:00 2001 From: thao13039 Date: Sun, 1 Dec 2019 23:07:08 -0800 Subject: [PATCH 07/25] add scatter-plot-series to DataSeries data definition --- src/runtime-arr/chart.arr | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index f2525effe2..1fac43e806 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -216,6 +216,17 @@ default-plot-chart-window-object :: PlotChartWindowObject = default-chart-window ################################################################################ data DataSeries: + | scatter-plot-series(obj :: ScatterPlotSeries) with: + is-single: false, + color: method(self, color :: I.Color): + scatter-plot-series(self.obj.{color: some(color)}) + end, + legend: method(self, legend :: String): + scatter-plot-series(self.obj.{legend: legend}) + end, + point-size: method(self, point-size :: Number): + scatter-plot-series(self.obj.{point-size: point-size}) + end, | pie-chart-series(obj :: PieChartSeries) with: is-single: true, | bar-chart-series(obj :: BarChartSeries) with: From 0aada8ffc804f339698b11c64639811f0709943b Mon Sep 17 00:00:00 2001 From: thao13039 Date: Sun, 1 Dec 2019 23:08:35 -0800 Subject: [PATCH 08/25] remove constr comment from pie- + bar-chart-window --- src/runtime-arr/chart.arr | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 1fac43e806..b7f894d734 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -244,7 +244,6 @@ end data ChartWindow: | pie-chart-window(obj :: PieChartWindowObject) with: - #constr: {(): pie-chart-window}, title: method(self, title :: String): pie-chart-window(self.obj.{title: title}) end, width: method(self, width :: Number): pie-chart-window(self.obj.{width: width}) end, height: method(self, height :: Number): pie-chart-window(self.obj.{height: height}) end, @@ -257,7 +256,6 @@ data ChartWindow: self.obj.{interact: false}.render() end, | bar-chart-window(obj :: BarChartWindowObject) with: - #constr: {(): bar-chart-window}, x-axis: method(self, x-axis :: String): bar-chart-window(self.obj.{x-axis: x-axis}) end, y-axis: method(self, y-axis :: String): bar-chart-window(self.obj.{y-axis: y-axis}) end, y-min: method(self, y-min :: Number): bar-chart-window(self.obj.{y-min: O.some(y-min)}) end, From 71513263adc96ebd4db76874283d290a4ac0ff53 Mon Sep 17 00:00:00 2001 From: thao13039 Date: Sun, 1 Dec 2019 23:10:16 -0800 Subject: [PATCH 09/25] add plot-chart-window to ChartWindow data def --- src/runtime-arr/chart.arr | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index b7f894d734..c04ff1c205 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -271,6 +271,30 @@ data ChartWindow: _ = check-chart-window(self.obj) self.obj.{interact: false}.render() end, + | plot-chart-window(obj :: PlotChartWindowObject) with: + x-axis: x-axis-method, + y-axis: y-axis-method, + x-min: x-min-method, + x-max: x-max-method, + y-min: y-min-method, + y-max: y-max-method, + num-samples: method(self, num-samples :: Number) block: + when (num-samples <= 0) or (num-samples > 100000) or not(num-is-integer(num-samples)): + G.raise('num-samples: value must be an ineger between 1 and 100000') + end + plot-chart-window(self.obj.{num-samples: num-samples}) + end, + title: method(self, title :: String): plot-chart-window(self.obj.{title: title}) end, + width: method(self, width :: Number): plot-chart-window(self.obj.{width: width}) end, + height: method(self, height :: Number): plot-chart-window(self.obj.{height: height}) end, + display: method(self): + _ = check-chart-window(self.obj) + self.obj.{interact: true}.render() + end, + get-image: method(self): + _ = check-chart-window(self.obj) + self.obj.{interact: false}.render() + end, #sharing: # TODO(tiffany): add the following 3 methods to every ChartWindow From 67f8f620e090869ea785bfd1cbd0e5b7a9d9c49c Mon Sep 17 00:00:00 2001 From: thao13039 Date: Sun, 1 Dec 2019 23:11:00 -0800 Subject: [PATCH 10/25] add scatter-plot-from-list function --- src/runtime-arr/chart.arr | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index c04ff1c205..5f06edd26f 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -317,6 +317,18 @@ end # FUNCTIONS ################################################################################ +fun scatter-plot-from-list(xs :: L.List, ys :: L.List) -> DataSeries block: + when xs.length() <> ys.length(): + G.raise('scatter-plot: xs and ys should have the same length') + end + # TODO(tiffany): uncomment after implementing each + #xs.each(check-num) + #ys.each(check-num) + scatter-plot-series(default-scatter-plot-series.{ + ps: L.map3({(x, y, z): [G.raw-array: x, y, z]}, xs, ys, L.map({(_): ''}, xs)) + }) +end + fun pie-chart-from-list(labels :: L.List, values :: L.List) -> DataSeries block: doc: ``` Consume labels, a list of string, and values, a list of numbers From f87ef1db6c4b6b68be305b00325ea7ff5b34730a Mon Sep 17 00:00:00 2001 From: thao13039 Date: Tue, 3 Dec 2019 18:03:17 -0800 Subject: [PATCH 11/25] scatter-plot not done, place to start histogram --- src/runtime-arr/chart.arr | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 5f06edd26f..042db0b7fc 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -139,7 +139,7 @@ type ScatterPlotSeries = { } default-scatter-plot-series = { - color: none, + color: O.none, legend: '', point-size: 7, } @@ -204,10 +204,10 @@ type PlotChartWindowObject = { default-plot-chart-window-object :: PlotChartWindowObject = default-chart-window-object.{ x-axis: '', y-axis: '', - x-min: none, - x-max: none, - y-min: none, - y-max: none, + x-min: O.none, + x-max: O.none, + y-min: O.none, + y-max: O.none, num-samples: 1000, } @@ -218,8 +218,8 @@ default-plot-chart-window-object :: PlotChartWindowObject = default-chart-window data DataSeries: | scatter-plot-series(obj :: ScatterPlotSeries) with: is-single: false, - color: method(self, color :: I.Color): - scatter-plot-series(self.obj.{color: some(color)}) + color: method(self, color :: IM.Color): + scatter-plot-series(self.obj.{color: O.some(color)}) end, legend: method(self, legend :: String): scatter-plot-series(self.obj.{legend: legend}) @@ -272,14 +272,14 @@ data ChartWindow: self.obj.{interact: false}.render() end, | plot-chart-window(obj :: PlotChartWindowObject) with: - x-axis: x-axis-method, - y-axis: y-axis-method, - x-min: x-min-method, - x-max: x-max-method, - y-min: y-min-method, - y-max: y-max-method, + x-axis: method(self, x-axis :: String): plot-chart-window(self.obj.{x-axis: x-axis}) end, + y-axis: method(self, y-axis :: String): plot-chart-window(self.obj.{y-axis: y-axis}) end, + x-min: method(self, x-min :: Number): plot-chart-window(self.obj.{x-min: O.some(x-min)}) end, + x-max: method(self, x-max :: Number): plot-chart-window(self.obj.{x-max: O.some(x-max)}) end, + y-min: method(self, y-min :: Number): plot-chart-window(self.obj.{y-min: O.some(y-min)}) end, + y-max: method(self, y-max :: Number): plot-chart-window(self.obj.{y-max: O.some(y-max)}) end, num-samples: method(self, num-samples :: Number) block: - when (num-samples <= 0) or (num-samples > 100000) or not(num-is-integer(num-samples)): + when (num-samples <= 0) or (num-samples > 100000) or G.not(G.num-is-integer(num-samples)): G.raise('num-samples: value must be an ineger between 1 and 100000') end plot-chart-window(self.obj.{num-samples: num-samples}) @@ -318,14 +318,14 @@ end ################################################################################ fun scatter-plot-from-list(xs :: L.List, ys :: L.List) -> DataSeries block: - when xs.length() <> ys.length(): + when L.length(xs) <> L.length(ys): G.raise('scatter-plot: xs and ys should have the same length') end # TODO(tiffany): uncomment after implementing each #xs.each(check-num) #ys.each(check-num) scatter-plot-series(default-scatter-plot-series.{ - ps: L.map3({(x, y, z): [G.raw-array: x, y, z]}, xs, ys, L.map({(_): ''}, xs)) + ps: L.map2({(x, y): [G.raw-array: x, y]}, xs, ys) }) end @@ -377,6 +377,8 @@ end fun render-chart(s :: DataSeries) -> ChartWindow: doc: 'Render it!' cases (DataSeries) s: + # TODO(tiffany): fix scatter-plot-series + | scatter-plot-series(_) => plot-chart-window(default-plot-chart-window-object) | pie-chart-series(obj) => pie-chart-window(default-pie-chart-window-object.{ render: method(self): CL.pie-chart(obj.tab) end From 4d5e96813e52b303d96d021aa0091712464dfc35 Mon Sep 17 00:00:00 2001 From: thao13039 Date: Tue, 3 Dec 2019 18:42:41 -0800 Subject: [PATCH 12/25] implement histogram --- src/runtime-arr/chart.arr | 101 +++++++++++++++++++++++++++++++++ src/runtime/chart-lib.arr.js | 13 +++++ src/runtime/chart-lib.arr.json | 1 + 3 files changed, 115 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 042db0b7fc..ce19fa518d 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -131,6 +131,19 @@ type BarChartSeries = { default-bar-chart-series = {} +type HistogramSeries = { + tab :: TableIntern, + bin-width :: Option, + max-num-bins :: Option, + min-num-bins :: Option, +} + +default-histogram-series = { + bin-width: O.none, + max-num-bins: O.none, + min-num-bins: O.none, +} + type ScatterPlotSeries = { ps :: L.List, color :: Option, @@ -187,6 +200,27 @@ default-bar-chart-window-object :: BarChartWindowObject = default-chart-window-o y-max: O.none, } +type HistogramChartWindowObject = { + title :: String, + width :: Number, + height :: Number, + render :: ( -> IM.Image), + x-axis :: String, + y-axis :: String, + x-min :: Option, + x-max :: Option, + y-max :: Option, +} + +default-histogram-chart-window-object :: HistogramChartWindowObject = + default-chart-window-object.{ + x-axis: '', + y-axis: '', + x-min: O.none, + x-max: O.none, + y-max: O.none, + } + type PlotChartWindowObject = { title :: String, width :: Number, @@ -231,6 +265,23 @@ data DataSeries: is-single: true, | bar-chart-series(obj :: BarChartSeries) with: is-single: true, + | histogram-series(obj :: HistogramSeries) with: + is-single: true, + method bin-width(self, bin-width :: Number): + histogram-series(self.obj.{bin-width: O.some(bin-width)}) + end, + method max-num-bins(self, max-num-bins :: Number): + histogram-series(self.obj.{max-num-bins: O.some(max-num-bins)}) + end, + method min-num-bins(self, min-num-bins :: Number): + histogram-series(self.obj.{min-num-bins: O.some(min-num-bins)}) + end, + method num-bins(self, num-bins :: Number): + histogram-series(self.obj.{ + min-num-bins: O.some(num-bins), + max-num-bins: O.some(num-bins) + }) + end, # TODO(tiffany): add _output and test get-vs-from-img after VS is implemented end @@ -271,6 +322,12 @@ data ChartWindow: _ = check-chart-window(self.obj) self.obj.{interact: false}.render() end, + | histogram-chart-window(obj :: HistogramChartWindowObject) with: + x-axis: method(self, x-axis :: String): histogram-chart-window(self.obj.{x-axis: x-axis}) end, + y-axis: method(self, y-axis :: String): histogram-chart-window(self.obj.{y-axis: y-axis}) end, + x-min: method(self, x-min :: Number): histogram-chart-window(self.obj.{x-min: O.some(x-min)}) end, + x-max: method(self, x-max :: Number): histogram-chart-window(self.obj.{x-max: O.some(x-max)}) end, + y-max: method(self, y-max :: Number): histogram-chart-window(self.obj.{y-max: O.some(y-max)}) end, | plot-chart-window(obj :: PlotChartWindowObject) with: x-axis: method(self, x-axis :: String): plot-chart-window(self.obj.{x-axis: x-axis}) end, y-axis: method(self, y-axis :: String): plot-chart-window(self.obj.{y-axis: y-axis}) end, @@ -370,6 +427,17 @@ fun bar-chart-from-list(labels :: L.List, values :: L.List) -> D }) end +fun histogram-from-list(values :: L.List) -> DataSeries block: + doc: ``` + Consume a list of numbers and construct a histogram + ``` + # TODO(tiffany): uncomment after implementing each + #values.each(check-num) + histogram-series(default-histogram-series.{ + tab: to-table2(L.map({(_): ''}, values), values), + }) +end + ################################################################################ # PLOTS ################################################################################ @@ -402,6 +470,39 @@ fun render-chart(s :: DataSeries) -> ChartWindow: CL.bar-chart(obj.tab) end }) + | histogram-series(obj) => + histogram-chart-window(default-histogram-chart-window-object.{ + render: method(self): + shadow self = self.{y-min: O.none} + _ = cases (Option) self.x-min: + | some(x-min) => + cases (Option) self.x-max: + | some(x-max) => + if x-min >= x-max: + G.raise("render: x-min must be strictly less than x-max") + else: + G.nothing + end + | else => G.nothing + end + | else => G.nothing + end + _ = cases (Option) self.y-min: + | some(y-min) => + cases (Option) self.y-max: + | some(y-max) => + if y-min >= y-max: + G.raise("render: y-min must be strictly less than y-max") + else: + G.nothing + end + | else => G.nothing + end + | else => G.nothing + end + CL.histogram(obj.tab) + end + }) end #where: # render-now = {(x): render-chart(x).get-image()} diff --git a/src/runtime/chart-lib.arr.js b/src/runtime/chart-lib.arr.js index ee592a25bd..6ff0800a46 100644 --- a/src/runtime/chart-lib.arr.js +++ b/src/runtime/chart-lib.arr.js @@ -58,6 +58,16 @@ function pieChartFromTable(table) { }; } +/* @stopify flat */ +function histogram(tableFromRawArray) { + return { + "$brand": "chart", + "chartType": "Histogram", + "_headers": ["",""], + "_rows": tableFromRawArray + }; +} + /* @stopify flat */ function histogramFromTable(table) { return { @@ -104,6 +114,9 @@ return module.exports = { "pie-chart-from-table": /* @stopify flat */ function (table) { return pieChartFromTable(table); }, + "histogram": /* @stopify flat */ function (tableFromRawArray) { + return histogram(tableFromRawArray); + }, "histogram-from-table": /* @stopify flat */ function (table) { return histogramFromTable(table); }, diff --git a/src/runtime/chart-lib.arr.json b/src/runtime/chart-lib.arr.json index 1dd3e38a39..123f8ef891 100644 --- a/src/runtime/chart-lib.arr.json +++ b/src/runtime/chart-lib.arr.json @@ -21,6 +21,7 @@ "bar-chart-from-table": ["arrow", ["Table"], "Chart"], "pie-chart": ["arrow", ["rOfR"], "Chart"], "pie-chart-from-table": ["arrow", ["Table"], "Chart"], + "histogram": ["arrow", ["rOfR"], "Chart"], "histogram-from-table": ["arrow", ["Table"], "Chart"], "scatter-chart-from-table": ["arrow", ["Table"], "Chart"], "line-chart-from-table": ["arrow", ["Table"], "Chart"] From 44664d1980d3dee37f1bae950106d26cbf0d434a Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 11:48:20 -0800 Subject: [PATCH 13/25] remove unnecessary comments --- src/runtime-arr/chart.arr | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index ce19fa518d..82c75ac1d2 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -10,11 +10,6 @@ import option as O include from O: type Option end -################################################################################ -# CONSTANTS -################################################################################ - - ################################################################################ # TYPE SYNONYMS ################################################################################ @@ -46,11 +41,6 @@ end # TODO(tiffany): add in get-vs-from-img after VS is implemented -################################################################################ -# METHODS -################################################################################ - - ################################################################################ # BOUNDING BOX ################################################################################ @@ -352,21 +342,6 @@ data ChartWindow: _ = check-chart-window(self.obj) self.obj.{interact: false}.render() end, -#sharing: - - # TODO(tiffany): add the following 3 methods to every ChartWindow - # title: method(self, title :: String): self.constr()(self.obj.{title: title}) end, - # width: method(self, width :: Number): self.constr()(self.obj.{width: width}) end, - # height: method(self, height :: Number): self.constr()(self.obj.{height: height}) end, - # display: method(self): - # _ = check-chart-window(self.obj) - # self.obj.{interact: true}.render() - # end, - # get-image: method(self): - # _ = check-chart-window(self.obj) - # self.obj.{interact: false}.render() - # end, - # TODO(tiffany): add _output and test get-vs-from-img after VS is implemented end From a93d78dca511a10db861440d8fe0d408b79adc60 Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 11:50:20 -0800 Subject: [PATCH 14/25] add BoxChartSeries and BoxChartWindowObject type --- src/runtime-arr/chart.arr | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 82c75ac1d2..607a178d03 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -107,6 +107,16 @@ end # DEFAULT VALUES ################################################################################ +type BoxChartSeries = { + tab :: TableIntern, + height :: Number, + horizontal :: Boolean +} + +default-box-plot-series = { + horizontal: false +} + type PieChartSeries = { tab :: TableIntern, } @@ -163,6 +173,20 @@ default-chart-window-object :: ChartWindowObject = { render: method(self): G.raise('unimplemented') end, } +type BoxChartWindowObject = { + title :: String, + width :: Number, + height :: Number, + x-axis :: String, + y-axis :: String, + render :: ( -> IM.Image), +} + +default-box-plot-chart-window-object :: BoxChartWindowObject = default-chart-window-object.{ + x-axis: '', + y-axis: '', +} + type PieChartWindowObject = { title :: String, width :: Number, From 351336c9569209bc865f388b57efda05fbf66bae Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 11:51:32 -0800 Subject: [PATCH 15/25] add box-plot TODOs --- src/runtime-arr/chart.arr | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 607a178d03..de67b4a5cc 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -279,6 +279,12 @@ data DataSeries: is-single: true, | bar-chart-series(obj :: BarChartSeries) with: is-single: true, + # TODO(tiffany): add box-plot-series in by adding a | + # box-plot-series(obj :: BoxChartSeries) with: + # is-single: true, + # horizontal: method(self, h): + # box-plot-series(self.obj.{horizontal: h}) + # end | histogram-series(obj :: HistogramSeries) with: is-single: true, method bin-width(self, bin-width :: Number): @@ -320,6 +326,21 @@ data ChartWindow: _ = check-chart-window(self.obj) self.obj.{interact: false}.render() end, + # TODO(tiffany): add box-plot-chart-window in with a | + # box-plot-chart-window(obj :: BoxChartWindowObject) with: + # x-axis: method(self, x-axis :: String): box-plot-chart-window(self.obj.{x-axis: x-axis}) end, + # y-axis: method(self, y-axis :: String): box-plot-chart-window(self.obj.{y-axis: y-axis}) end, + # title: method(self, title :: String): box-plot-chart-window(self.obj.{title: title}) end, + # width: method(self, width :: Number): box-plot-chart-window(self.obj.{width: width}) end, + # height: method(self, height :: Number): box-plot-chart-window(self.obj.{height: height}) end, + # display: method(self): + # _ = check-chart-window(self.obj) + # self.obj.{interact: true}.render() + # end, + # get-image: method(self): + # _ = check-chart-window(self.obj) + # self.obj.{interact: false}.render() + # end, | bar-chart-window(obj :: BarChartWindowObject) with: x-axis: method(self, x-axis :: String): bar-chart-window(self.obj.{x-axis: x-axis}) end, y-axis: method(self, y-axis :: String): bar-chart-window(self.obj.{y-axis: y-axis}) end, @@ -469,6 +490,13 @@ fun render-chart(s :: DataSeries) -> ChartWindow: CL.bar-chart(obj.tab) end }) + # TODO(tiffany): implement CL.box-plot + # box-plot-series(obj) => + # box-plot-chart-window(default-box-plot-chart-window-object.{ + # render: method(self): + # CL.box-plot(self, obj) + # end + # }) | histogram-series(obj) => histogram-chart-window(default-histogram-chart-window-object.{ render: method(self): From 20a7bddae5007e1a198a35ac3c242df178732841 Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 11:53:50 -0800 Subject: [PATCH 16/25] add LinePlotSeries and FunctionPlotSeries types --- src/runtime-arr/chart.arr | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index de67b4a5cc..51ad0f0f04 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -144,6 +144,17 @@ default-histogram-series = { min-num-bins: O.none, } +type LinePlotSeries = { + ps :: L.List, + color :: Option, + legend :: String, +} + +default-line-plot-series = { + color: O.none, + legend: '', +} + type ScatterPlotSeries = { ps :: L.List, color :: Option, @@ -157,6 +168,17 @@ default-scatter-plot-series = { point-size: 7, } +type FunctionPlotSeries = { + f :: PlottableFunction, + color :: Option, + legend :: String, +} + +default-function-plot-series = { + color: none, + legend: '', +} + ########### type ChartWindowObject = { From 1a42162e320eceefda949ec5f81325002af7ac0e Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 11:54:24 -0800 Subject: [PATCH 17/25] add PlottableFunction type --- src/runtime-arr/chart.arr | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 51ad0f0f04..937c174599 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -14,6 +14,7 @@ include from O: type Option end # TYPE SYNONYMS ################################################################################ +type PlottableFunction = (Number -> Number) type Posn = RawArray type TableIntern = RawArray> From aab7f9a7507eda58e38236f508ff560a0c63535e Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 11:55:19 -0800 Subject: [PATCH 18/25] add unsafe-equal helper function --- src/runtime-arr/chart.arr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 937c174599..ac3cf8a718 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -24,6 +24,8 @@ type TableIntern = RawArray> posn = {(x :: Number, y :: Number): [G.raw-array: x, y]} +unsafe-equal = {(x :: Number, y :: Number): (x <= y) and (y <= x)} + fun map2(xs :: L.List, ys :: L.List): L.map2({(x, y): [G.raw-array: x, y]}, xs, ys) end From 15e264fc7a7287b1321d91e1c631563692d365b1 Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 11:58:11 -0800 Subject: [PATCH 19/25] add line- and function-plot-series to DataSeries --- src/runtime-arr/chart.arr | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index ac3cf8a718..939d79a4b2 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -289,6 +289,14 @@ default-plot-chart-window-object :: PlotChartWindowObject = default-chart-window ################################################################################ data DataSeries: + | line-plot-series(obj :: LinePlotSeries) with: + is-single: false, + color: method(self, color :: IM.Color): + scatter-plot-series(self.obj.{color: O.some(color)}) + end, + legend: method(self, legend :: String): + scatter-plot-series(self.obj.{legend: legend}) + end, | scatter-plot-series(obj :: ScatterPlotSeries) with: is-single: false, color: method(self, color :: IM.Color): @@ -300,6 +308,14 @@ data DataSeries: point-size: method(self, point-size :: Number): scatter-plot-series(self.obj.{point-size: point-size}) end, + | function-plot-series(obj :: FunctionPlotSeries) with: + is-single: false, + color: method(self, color :: IM.Color): + scatter-plot-series(self.obj.{color: O.some(color)}) + end, + legend: method(self, legend :: String): + scatter-plot-series(self.obj.{legend: legend}) + end, | pie-chart-series(obj :: PieChartSeries) with: is-single: true, | bar-chart-series(obj :: BarChartSeries) with: @@ -491,6 +507,8 @@ fun render-chart(s :: DataSeries) -> ChartWindow: doc: 'Render it!' cases (DataSeries) s: # TODO(tiffany): fix scatter-plot-series + | line-plot-series(_) => plot-chart-window(default-plot-chart-window-object) + | function-plot-series(_) => plot-chart-window(default-plot-chart-window-object) | scatter-plot-series(_) => plot-chart-window(default-plot-chart-window-object) | pie-chart-series(obj) => pie-chart-window(default-pie-chart-window-object.{ From 1c13fb692a618dab74d245666862cb8ed88f02dc Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 12:00:40 -0800 Subject: [PATCH 20/25] add lots of TODOs... --- src/runtime-arr/chart.arr | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 939d79a4b2..9f1ef34f2d 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -447,6 +447,10 @@ fun scatter-plot-from-list(xs :: L.List, ys :: L.List) -> DataSe }) end +# TODO(tiffany): implement labeled-scatter-plot-from-list + +# TODO(tiffany): implement exploding-pie-chart-from-list + fun pie-chart-from-list(labels :: L.List, values :: L.List) -> DataSeries block: doc: ``` Consume labels, a list of string, and values, a list of numbers @@ -488,6 +492,14 @@ fun bar-chart-from-list(labels :: L.List, values :: L.List) -> D }) end +# TODO(tiffany): implement grouped-bar-chart-from-list + +# TODO(tiffany): implement box-plot-from-list + +# TODO(tiffany): implement labeled-box-plot-from-list + +# TODO(tiffany): implement freq-bar-chart-from-list + fun histogram-from-list(values :: L.List) -> DataSeries block: doc: ``` Consume a list of numbers and construct a histogram @@ -499,6 +511,8 @@ fun histogram-from-list(values :: L.List) -> DataSeries block: }) end +# TODO(tiffany): implement labeled-histogram-from-list + ################################################################################ # PLOTS ################################################################################ @@ -578,3 +592,17 @@ fun render-chart(s :: DataSeries) -> ChartWindow: # render-now = {(x): render-chart(x).get-image()} end + +# TODO(tiffany): implement inbound-x + +# TODO(tiffany): implement inbound-y + +# TODO(tiffany): implement inbound-xy + +# TODO(tiffany): implement dist + +# TODO(tiffany): implement nearest + +# TODO(tiffany): implement find-pt-on-edge + +# TODO(tiffany): implement line-plot-edge-cut From 208c1e7b7f4970d1586fe575ee888326ae728803 Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 12:01:28 -0800 Subject: [PATCH 21/25] add function- and line-plot-from-list functions --- src/runtime-arr/chart.arr | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 9f1ef34f2d..9656cb5723 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -435,6 +435,24 @@ end # FUNCTIONS ################################################################################ +fun function-plot-from-list(f :: PlottableFunction) -> DataSeries: + function-plot-series(default-function-plot-series.{ + f: f, + }) +end + +fun line-plot-from-list(xs :: L.List, ys :: L.List) -> DataSeries block: + when L.length(xs) <> L.length(ys): + G.raise('line-plot: xs and ys should have the same length') + end + # TODO(tiffany): uncomment after implementing each + #xs.each(check-num) + #ys.each(check-num) + line-plot-series(default-line-plot-series.{ + ps: map2({(x, y): [G.raw-array: x, y]}, xs, ys) + }) +end + fun scatter-plot-from-list(xs :: L.List, ys :: L.List) -> DataSeries block: when L.length(xs) <> L.length(ys): G.raise('scatter-plot: xs and ys should have the same length') From b2b13906ba1b6db5622977cf0da72f5dcaea42ca Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 12:11:42 -0800 Subject: [PATCH 22/25] add missing O. to none --- src/runtime-arr/chart.arr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 9656cb5723..9e33fad33a 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -178,7 +178,7 @@ type FunctionPlotSeries = { } default-function-plot-series = { - color: none, + color: O.none, legend: '', } From fdca918d95cfd652cf19e315ca112d48ed69c1b5 Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 12:17:01 -0800 Subject: [PATCH 23/25] add minor fixes to get to working state --- src/runtime-arr/chart.arr | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 9e33fad33a..4e284807c1 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -292,10 +292,10 @@ data DataSeries: | line-plot-series(obj :: LinePlotSeries) with: is-single: false, color: method(self, color :: IM.Color): - scatter-plot-series(self.obj.{color: O.some(color)}) + line-plot-series(self.obj.{color: O.some(color)}) end, legend: method(self, legend :: String): - scatter-plot-series(self.obj.{legend: legend}) + line-plot-series(self.obj.{legend: legend}) end, | scatter-plot-series(obj :: ScatterPlotSeries) with: is-single: false, @@ -311,10 +311,10 @@ data DataSeries: | function-plot-series(obj :: FunctionPlotSeries) with: is-single: false, color: method(self, color :: IM.Color): - scatter-plot-series(self.obj.{color: O.some(color)}) + function-plot-series(self.obj.{color: O.some(color)}) end, legend: method(self, legend :: String): - scatter-plot-series(self.obj.{legend: legend}) + function-plot-series(self.obj.{legend: legend}) end, | pie-chart-series(obj :: PieChartSeries) with: is-single: true, @@ -449,7 +449,7 @@ fun line-plot-from-list(xs :: L.List, ys :: L.List) -> DataSerie #xs.each(check-num) #ys.each(check-num) line-plot-series(default-line-plot-series.{ - ps: map2({(x, y): [G.raw-array: x, y]}, xs, ys) + ps: L.map2({(x, y): [G.raw-array: x, y]}, xs, ys) }) end From 6c3e63615b50dcb6b42beaf4cdc80d6e512ad9e0 Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 13:52:35 -0800 Subject: [PATCH 24/25] implement list.each(...) --- src/runtime-arr/chart.arr | 26 ++++++++++++-------------- src/runtime/list.arr.js | 5 +++++ src/runtime/list.arr.json | 1 + 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 4e284807c1..5f47d3f58c 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -22,6 +22,9 @@ type TableIntern = RawArray> # HELPERS ################################################################################ +fun check-num(v :: Number) -> Nothing: nothing end +fun check-string(v :: String) -> Nothing: nothing end + posn = {(x :: Number, y :: Number): [G.raw-array: x, y]} unsafe-equal = {(x :: Number, y :: Number): (x <= y) and (y <= x)} @@ -445,9 +448,8 @@ fun line-plot-from-list(xs :: L.List, ys :: L.List) -> DataSerie when L.length(xs) <> L.length(ys): G.raise('line-plot: xs and ys should have the same length') end - # TODO(tiffany): uncomment after implementing each - #xs.each(check-num) - #ys.each(check-num) + xs.each(check-num) + ys.each(check-num) line-plot-series(default-line-plot-series.{ ps: L.map2({(x, y): [G.raw-array: x, y]}, xs, ys) }) @@ -457,9 +459,8 @@ fun scatter-plot-from-list(xs :: L.List, ys :: L.List) -> DataSe when L.length(xs) <> L.length(ys): G.raise('scatter-plot: xs and ys should have the same length') end - # TODO(tiffany): uncomment after implementing each - #xs.each(check-num) - #ys.each(check-num) + xs.each(check-num) + ys.each(check-num) scatter-plot-series(default-scatter-plot-series.{ ps: L.map2({(x, y): [G.raw-array: x, y]}, xs, ys) }) @@ -482,9 +483,8 @@ fun pie-chart-from-list(labels :: L.List, values :: L.List) -> D when label-length == 0: G.raise('pie-chart: need at least one data') end - # TODO(tiffany): uncomment after implementing each - #values.each(check-num) - #labels.each(check-string) + values.each(check-num) + labels.each(check-string) pie-chart-series(default-pie-chart-series.{ tab: to-table2(labels, values) }) @@ -500,9 +500,8 @@ fun bar-chart-from-list(labels :: L.List, values :: L.List) -> D when label-length <> value-length: G.raise('bar-chart: labels and values should have the same length') end - # TODO(tiffany): uncomment after implementing each - #values.each(check-num) - #labels.each(check-string) + values.each(check-num) + labels.each(check-string) bar-chart-series(default-bar-chart-series.{ tab: to-table2(labels, values), legends: [G.raw-array: ''], @@ -522,8 +521,7 @@ fun histogram-from-list(values :: L.List) -> DataSeries block: doc: ``` Consume a list of numbers and construct a histogram ``` - # TODO(tiffany): uncomment after implementing each - #values.each(check-num) + values.each(check-num) histogram-series(default-histogram-series.{ tab: to-table2(L.map({(_): ''}, values), values), }) diff --git a/src/runtime/list.arr.js b/src/runtime/list.arr.js index 13a6c7271b..61a63a8348 100644 --- a/src/runtime/list.arr.js +++ b/src/runtime/list.arr.js @@ -20,6 +20,11 @@ module.exports = { } return arr; }, + 'each': function( fun, lst ) { + for (let i = 0; i < lst.length; i++) { + lst[i] = fun(lst[i]); + } + }, 'map': function( fun, list ) { return list.map( fun ); }, diff --git a/src/runtime/list.arr.json b/src/runtime/list.arr.json index 2eea1cc2be..2dbb99e5a7 100644 --- a/src/runtime/list.arr.json +++ b/src/runtime/list.arr.json @@ -21,6 +21,7 @@ "length": ["forall", ["a"], ["arrow", ["lOfA"], "Number"]], "contains": ["forall", ["a"], ["arrow", ["lOfA", "tva"], "Boolean"]], "to-raw-array": ["forall", ["a"], ["arrow", ["lOfA"], "rOfA"]], + "each": ["forall", ["a"], ["arrow", [["arrow", ["tva"], "Nothing"], "lOfA"], "Nothing"]], "map": ["forall", ["a", "b"], ["arrow", [["arrow", ["tva"], "tvb"], "lOfA"], "lOfB"]], "map2": ["forall", ["a", "b", "c"], ["arrow", [["arrow", ["tva", "tvb"], "tvc"], "lOfA", "lOfB"], "lOfC"]], "map3": ["forall", ["a", "b", "c", "d"], ["arrow", [["arrow", ["tva", "tvb", "tvc"], "tvd"], "lOfA", "lOfB", "lOfC"], "lOfD"]], From 2fae8e6c2d29380ac2a31e1c6654800fbdf88ca7 Mon Sep 17 00:00:00 2001 From: thao13039 Date: Wed, 4 Dec 2019 14:01:59 -0800 Subject: [PATCH 25/25] fix calls to each --- src/runtime-arr/chart.arr | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/runtime-arr/chart.arr b/src/runtime-arr/chart.arr index 5f47d3f58c..5362b14336 100644 --- a/src/runtime-arr/chart.arr +++ b/src/runtime-arr/chart.arr @@ -448,8 +448,8 @@ fun line-plot-from-list(xs :: L.List, ys :: L.List) -> DataSerie when L.length(xs) <> L.length(ys): G.raise('line-plot: xs and ys should have the same length') end - xs.each(check-num) - ys.each(check-num) + L.each(check-num, xs) + L.each(check-num, ys) line-plot-series(default-line-plot-series.{ ps: L.map2({(x, y): [G.raw-array: x, y]}, xs, ys) }) @@ -459,8 +459,8 @@ fun scatter-plot-from-list(xs :: L.List, ys :: L.List) -> DataSe when L.length(xs) <> L.length(ys): G.raise('scatter-plot: xs and ys should have the same length') end - xs.each(check-num) - ys.each(check-num) + L.each(check-num, xs) + L.each(check-num, ys) scatter-plot-series(default-scatter-plot-series.{ ps: L.map2({(x, y): [G.raw-array: x, y]}, xs, ys) }) @@ -483,8 +483,8 @@ fun pie-chart-from-list(labels :: L.List, values :: L.List) -> D when label-length == 0: G.raise('pie-chart: need at least one data') end - values.each(check-num) - labels.each(check-string) + L.each(check-num, values) + L.each(check-string, labels) pie-chart-series(default-pie-chart-series.{ tab: to-table2(labels, values) }) @@ -500,8 +500,8 @@ fun bar-chart-from-list(labels :: L.List, values :: L.List) -> D when label-length <> value-length: G.raise('bar-chart: labels and values should have the same length') end - values.each(check-num) - labels.each(check-string) + L.each(check-num, values) + L.each(check-string, labels) bar-chart-series(default-bar-chart-series.{ tab: to-table2(labels, values), legends: [G.raw-array: ''], @@ -521,7 +521,7 @@ fun histogram-from-list(values :: L.List) -> DataSeries block: doc: ``` Consume a list of numbers and construct a histogram ``` - values.each(check-num) + L.each(check-num, values) histogram-series(default-histogram-series.{ tab: to-table2(L.map({(_): ''}, values), values), })