From 7d28678b65c8bd6f0ac7af6bf5a28a09be421158 Mon Sep 17 00:00:00 2001
From: Jorn van de Beek <jornvandebeek@roqua.nl>
Date: Tue, 19 Jan 2021 15:39:14 +0100
Subject: [PATCH 1/6] Add dsl for outcome schemas (tables) for roqua

---
 lib/quby/compiler/entities/subscore_schema.rb |  4 ++
 lib/quby/compiler/outputs/roqua_serializer.rb | 25 +++++++++++
 .../compiler/outputs/roqua_serializer_spec.rb | 43 +++++++++++++++++++
 3 files changed, 72 insertions(+)
 create mode 100644 spec/quby/compiler/outputs/roqua_serializer_spec.rb

diff --git a/lib/quby/compiler/entities/subscore_schema.rb b/lib/quby/compiler/entities/subscore_schema.rb
index 8091d9d..4c39f93 100644
--- a/lib/quby/compiler/entities/subscore_schema.rb
+++ b/lib/quby/compiler/entities/subscore_schema.rb
@@ -14,6 +14,10 @@ module Quby
         attribute :only_for_export?, Types::Bool
         # [Optional] The key of the variable definition used to calculate the subscore result.
         attribute :calculation_key?, Types::Symbol
+        # [Optional] The name of the outcome table where this subscore should be shown. Used for cases where scores
+        # differ in subscores too much to be shown as one table. Any name can be used, as long as they match between
+        # subscores that should be shown in the same table.
+        attribute :outcome_table?, Types::Symbol
       end
     end
   end
diff --git a/lib/quby/compiler/outputs/roqua_serializer.rb b/lib/quby/compiler/outputs/roqua_serializer.rb
index 9238afb..85dca6e 100644
--- a/lib/quby/compiler/outputs/roqua_serializer.rb
+++ b/lib/quby/compiler/outputs/roqua_serializer.rb
@@ -21,6 +21,7 @@ module Quby
             respondent_types: questionnaire.respondent_types,
             tags: questionnaire.tags.to_h.keys,
             charts: charts,
+            outcome_schema: outcome_schema,
           }
         end
 
@@ -73,6 +74,30 @@ module Quby
             end
           }
         end
+
+        def outcome_schema
+          # hash of tables, with the score keys (rows) and subscore keys (columns) used for each
+          tables = Hash.new{ |hash, key| hash[key] = {score_keys: [], subscore_keys: []} }
+          # hash of `subscore_key: subscore_label` pairs used in tables
+          headers = {}
+          
+          questionnaire.score_schemas.values.each do |schema|
+            schema.subscore_schemas.each do |subschema|
+              next unless subschema.outcome_table
+              tables[subschema.outcome_table][:subscore_keys] << subschema.key
+              tables[subschema.outcome_table][:score_keys] << schema.key
+              headers[subschema.key] = subschema.label
+            end
+          end
+          
+          tables.values.each { |table| table[:score_keys].uniq! }
+          tables.values.each { |table| table[:subscore_keys].uniq! }
+          
+          {
+            headers: headers,
+            tables: tables.values,
+          }
+        end
       end
     end
   end
diff --git a/spec/quby/compiler/outputs/roqua_serializer_spec.rb b/spec/quby/compiler/outputs/roqua_serializer_spec.rb
new file mode 100644
index 0000000..3cccaee
--- /dev/null
+++ b/spec/quby/compiler/outputs/roqua_serializer_spec.rb
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+describe Quby::Compiler::Outputs::RoquaSerializer do
+  it 'generates outcome schemas' do
+    questionnaire = dsl("test") do
+      title "Test Quest"
+
+      score_schema :score1, 'Score 1' do
+        subscore :value, 'Waarde', export_key: :score1, outcome_table: :values do
+          1
+        end
+        subscore :int, 'Interpretatie', export_key: :score1_i do
+          'Wah'
+        end
+      end
+
+      score_schema :score2, 'Score 2' do
+        subscore :value, 'Waarde', export_key: :score2, outcome_table: :values do
+          2
+        end
+      end
+
+      score_schema :score3, 'Score 3' do
+        subscore :mean, 'Gemiddelde', export_key: :score3, outcome_table: :means do
+          1
+        end
+      end
+    end
+    serializer = described_class.new(questionnaire)
+    expect(serializer.as_json).to \
+      include({
+                outcome_schema: {
+                  tables: [{:score_keys => [:score1, :score2], :subscore_keys => [:value]},
+                           {:score_keys => [:score3], :subscore_keys => [:mean]}],
+                  headers: {mean: "Gemiddelde", value: "Waarde"}
+                }
+              })
+  end
+
+  def dsl(key, &block)
+    Quby::Compiler::DSL.build(key, nil, &block)
+  end
+end
\ No newline at end of file
-- 
GitLab


From d47005c33667714a2cfa2bdcf6f47c5c6c5d038e Mon Sep 17 00:00:00 2001
From: Jorn van de Beek <jornvandebeek@roqua.nl>
Date: Wed, 20 Jan 2021 13:27:15 +0100
Subject: [PATCH 2/6] Use :main table by default

---
 lib/quby/compiler/entities/subscore_schema.rb  |  7 +++----
 lib/quby/compiler/outputs/roqua_serializer.rb  |  1 -
 .../compiler/outputs/roqua_serializer_spec.rb  | 18 ++++++++++++++----
 3 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/lib/quby/compiler/entities/subscore_schema.rb b/lib/quby/compiler/entities/subscore_schema.rb
index 4c39f93..b265898 100644
--- a/lib/quby/compiler/entities/subscore_schema.rb
+++ b/lib/quby/compiler/entities/subscore_schema.rb
@@ -14,10 +14,9 @@ module Quby
         attribute :only_for_export?, Types::Bool
         # [Optional] The key of the variable definition used to calculate the subscore result.
         attribute :calculation_key?, Types::Symbol
-        # [Optional] The name of the outcome table where this subscore should be shown. Used for cases where scores
-        # differ in subscores too much to be shown as one table. Any name can be used, as long as they match between
-        # subscores that should be shown in the same table.
-        attribute :outcome_table?, Types::Symbol
+        # [Optional argument] The name of the outcome table where this subscore should be shown. Used for cases where scores
+        # differ in subscores too much to be shown as one table. By default, all scores end up in the `:main` table.
+        attribute :outcome_table, Types::Symbol.default(:main).meta(omittable: true)
       end
     end
   end
diff --git a/lib/quby/compiler/outputs/roqua_serializer.rb b/lib/quby/compiler/outputs/roqua_serializer.rb
index 85dca6e..0ab71bd 100644
--- a/lib/quby/compiler/outputs/roqua_serializer.rb
+++ b/lib/quby/compiler/outputs/roqua_serializer.rb
@@ -83,7 +83,6 @@ module Quby
           
           questionnaire.score_schemas.values.each do |schema|
             schema.subscore_schemas.each do |subschema|
-              next unless subschema.outcome_table
               tables[subschema.outcome_table][:subscore_keys] << subschema.key
               tables[subschema.outcome_table][:score_keys] << schema.key
               headers[subschema.key] = subschema.label
diff --git a/spec/quby/compiler/outputs/roqua_serializer_spec.rb b/spec/quby/compiler/outputs/roqua_serializer_spec.rb
index 3cccaee..0a139bf 100644
--- a/spec/quby/compiler/outputs/roqua_serializer_spec.rb
+++ b/spec/quby/compiler/outputs/roqua_serializer_spec.rb
@@ -5,11 +5,18 @@ describe Quby::Compiler::Outputs::RoquaSerializer do
     questionnaire = dsl("test") do
       title "Test Quest"
 
+      score_schema :score0, 'Score 0' do
+        # By default, scores end up in the :main table
+        subscore :something, 'Nog iets', export_key: :score0 do
+          'Iets'
+        end
+      end
+
       score_schema :score1, 'Score 1' do
         subscore :value, 'Waarde', export_key: :score1, outcome_table: :values do
           1
         end
-        subscore :int, 'Interpretatie', export_key: :score1_i do
+        subscore :int, 'Interpretatie', export_key: :score1_i, outcome_table: :values do
           'Wah'
         end
       end
@@ -30,9 +37,12 @@ describe Quby::Compiler::Outputs::RoquaSerializer do
     expect(serializer.as_json).to \
       include({
                 outcome_schema: {
-                  tables: [{:score_keys => [:score1, :score2], :subscore_keys => [:value]},
-                           {:score_keys => [:score3], :subscore_keys => [:mean]}],
-                  headers: {mean: "Gemiddelde", value: "Waarde"}
+                  headers: {int: "Interpretatie", mean: "Gemiddelde", something: "Nog iets", value: "Waarde"},
+                  tables: [
+                    {:score_keys => [:score0], :subscore_keys => [:something]},
+                    {:score_keys => [:score1, :score2], :subscore_keys => [:value, :int]},
+                    {:score_keys => [:score3], :subscore_keys => [:mean]}
+                  ]
                 }
               })
   end
-- 
GitLab


From e66fe0dfb15e8e69b5a7f37cbba0d85ad0b9dd5c Mon Sep 17 00:00:00 2001
From: Jorn van de Beek <jornvandebeek@roqua.nl>
Date: Thu, 21 Jan 2021 15:56:53 +0100
Subject: [PATCH 3/6] Rename outcome_schema to outcome_tables_schema

---
 lib/quby/compiler/outputs/roqua_serializer.rb       | 4 ++--
 spec/quby/compiler/outputs/roqua_serializer_spec.rb | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/quby/compiler/outputs/roqua_serializer.rb b/lib/quby/compiler/outputs/roqua_serializer.rb
index 0ab71bd..7e384fb 100644
--- a/lib/quby/compiler/outputs/roqua_serializer.rb
+++ b/lib/quby/compiler/outputs/roqua_serializer.rb
@@ -21,7 +21,7 @@ module Quby
             respondent_types: questionnaire.respondent_types,
             tags: questionnaire.tags.to_h.keys,
             charts: charts,
-            outcome_schema: outcome_schema,
+            outcome_tables_schema: outcome_tables_schema,
           }
         end
 
@@ -75,7 +75,7 @@ module Quby
           }
         end
 
-        def outcome_schema
+        def outcome_tables_schema
           # hash of tables, with the score keys (rows) and subscore keys (columns) used for each
           tables = Hash.new{ |hash, key| hash[key] = {score_keys: [], subscore_keys: []} }
           # hash of `subscore_key: subscore_label` pairs used in tables
diff --git a/spec/quby/compiler/outputs/roqua_serializer_spec.rb b/spec/quby/compiler/outputs/roqua_serializer_spec.rb
index 0a139bf..fb43846 100644
--- a/spec/quby/compiler/outputs/roqua_serializer_spec.rb
+++ b/spec/quby/compiler/outputs/roqua_serializer_spec.rb
@@ -36,7 +36,7 @@ describe Quby::Compiler::Outputs::RoquaSerializer do
     serializer = described_class.new(questionnaire)
     expect(serializer.as_json).to \
       include({
-                outcome_schema: {
+                outcome_tables_schema: {
                   headers: {int: "Interpretatie", mean: "Gemiddelde", something: "Nog iets", value: "Waarde"},
                   tables: [
                     {:score_keys => [:score0], :subscore_keys => [:something]},
-- 
GitLab


From d4b857d54f41b631248d6828a3cd92dea297c4ca Mon Sep 17 00:00:00 2001
From: Jorn van de Beek <jornvandebeek@roqua.nl>
Date: Thu, 21 Jan 2021 16:21:42 +0100
Subject: [PATCH 4/6] Use Set

---
 lib/quby/compiler/outputs/roqua_serializer.rb | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/lib/quby/compiler/outputs/roqua_serializer.rb b/lib/quby/compiler/outputs/roqua_serializer.rb
index 7e384fb..349918e 100644
--- a/lib/quby/compiler/outputs/roqua_serializer.rb
+++ b/lib/quby/compiler/outputs/roqua_serializer.rb
@@ -77,7 +77,7 @@ module Quby
 
         def outcome_tables_schema
           # hash of tables, with the score keys (rows) and subscore keys (columns) used for each
-          tables = Hash.new{ |hash, key| hash[key] = {score_keys: [], subscore_keys: []} }
+          tables = Hash.new{ |hash, key| hash[key] = {score_keys: Set.new, subscore_keys: Set.new } }
           # hash of `subscore_key: subscore_label` pairs used in tables
           headers = {}
           
@@ -89,9 +89,6 @@ module Quby
             end
           end
           
-          tables.values.each { |table| table[:score_keys].uniq! }
-          tables.values.each { |table| table[:subscore_keys].uniq! }
-          
           {
             headers: headers,
             tables: tables.values,
-- 
GitLab


From 74f19cbcc4245234641a9850b64d7afdf94388ab Mon Sep 17 00:00:00 2001
From: Jorn van de Beek <jorn@roqua.nl>
Date: Fri, 22 Jan 2021 12:13:32 +0000
Subject: [PATCH 5/6] Apply 1 suggestion(s) to 1 file(s)

---
 lib/quby/compiler/outputs/roqua_serializer.rb | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lib/quby/compiler/outputs/roqua_serializer.rb b/lib/quby/compiler/outputs/roqua_serializer.rb
index 349918e..374d3cd 100644
--- a/lib/quby/compiler/outputs/roqua_serializer.rb
+++ b/lib/quby/compiler/outputs/roqua_serializer.rb
@@ -75,6 +75,14 @@ module Quby
           }
         end
 
+        # configuration for outcome tables.
+        # tables:
+        #   <outcome_table:Symbol>: # each pair is a table.
+        #     score_keys: Set[<schema.key:Symbol>] # rows in the table
+        #     subscore_keys: Set[<subschema.key:Symbol>] # columns  in the table
+        # headers:
+        #   <subscore_key:Symbol>: <subscore.label:String> # headers for each subscore key for all tables.
+
         def outcome_tables_schema
           # hash of tables, with the score keys (rows) and subscore keys (columns) used for each
           tables = Hash.new{ |hash, key| hash[key] = {score_keys: Set.new, subscore_keys: Set.new } }
-- 
GitLab


From 7ac61927857718adb30588f3c5d8298e9de65408 Mon Sep 17 00:00:00 2001
From: Jorn van de Beek <jornvandebeek@roqua.nl>
Date: Fri, 22 Jan 2021 13:17:26 +0100
Subject: [PATCH 6/6] Pass table names in roqua.json

---
 lib/quby/compiler/outputs/roqua_serializer.rb       |  4 ++--
 spec/quby/compiler/outputs/roqua_serializer_spec.rb | 10 +++++-----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/lib/quby/compiler/outputs/roqua_serializer.rb b/lib/quby/compiler/outputs/roqua_serializer.rb
index 374d3cd..4fb8565 100644
--- a/lib/quby/compiler/outputs/roqua_serializer.rb
+++ b/lib/quby/compiler/outputs/roqua_serializer.rb
@@ -77,7 +77,7 @@ module Quby
 
         # configuration for outcome tables.
         # tables:
-        #   <outcome_table:Symbol>: # each pair is a table.
+        #   <outcome_table_name:Symbol>: # each entry is a table.
         #     score_keys: Set[<schema.key:Symbol>] # rows in the table
         #     subscore_keys: Set[<subschema.key:Symbol>] # columns  in the table
         # headers:
@@ -99,7 +99,7 @@ module Quby
           
           {
             headers: headers,
-            tables: tables.values,
+            tables: tables,
           }
         end
       end
diff --git a/spec/quby/compiler/outputs/roqua_serializer_spec.rb b/spec/quby/compiler/outputs/roqua_serializer_spec.rb
index fb43846..44c57b0 100644
--- a/spec/quby/compiler/outputs/roqua_serializer_spec.rb
+++ b/spec/quby/compiler/outputs/roqua_serializer_spec.rb
@@ -38,11 +38,11 @@ describe Quby::Compiler::Outputs::RoquaSerializer do
       include({
                 outcome_tables_schema: {
                   headers: {int: "Interpretatie", mean: "Gemiddelde", something: "Nog iets", value: "Waarde"},
-                  tables: [
-                    {:score_keys => [:score0], :subscore_keys => [:something]},
-                    {:score_keys => [:score1, :score2], :subscore_keys => [:value, :int]},
-                    {:score_keys => [:score3], :subscore_keys => [:mean]}
-                  ]
+                  tables: {
+                    main: {:score_keys => [:score0], :subscore_keys => [:something]},
+                    values: {:score_keys => [:score1, :score2], :subscore_keys => [:value, :int]},
+                    means: {:score_keys => [:score3], :subscore_keys => [:mean]}
+                  }
                 }
               })
   end
-- 
GitLab