diff --git a/app/models/simple_smart_answer_edition.rb b/app/models/simple_smart_answer_edition.rb index d4e89cf13..45da683fe 100644 --- a/app/models/simple_smart_answer_edition.rb +++ b/app/models/simple_smart_answer_edition.rb @@ -80,6 +80,26 @@ def destroy_in_attrs?(attrs) attrs.delete("_destroy") == "1" end + def generate_mermaid + parts = ["%%{ init: {\n'theme': 'base',\n'themeVariables': {\n " \ + "'background': '#FFFFFF',\n 'primaryTextColor': '#0B0C0C',\n " \ + "'lineColor': '#0b0c0c',\n 'fontSize': '23.75px' } } }%%\nflowchart TD"] + parts << "accTitle: #{title}\naccDescr: A flowchart for the #{title} smart answer\nAA[Start]:::start" + if nodes.present? + parts << "AA---Q#{nodes.first.slug.split('-')[1]}" + nodes.each do |node| + parts << if node.kind == "question" + mermaid_question(node) + elsif node.kind == "outcome" + mermaid_outcome(node) + end + end + end + parts << "classDef answer fill: #F3F2F1, stroke:#505A5F;\nclassDef outcome fill: #6FA4D2" \ + "\nclassDef question fill: #B1B4B6, stroke:#505A5F;\nclassDef start fill:#00703c,color: #ffffff" + parts.join("\n") + end + private def question(node) @@ -99,4 +119,22 @@ def outcome(node) body = node.body == "" ? "" : "\n#{node.body}" "#{node.slug.titleize}\n#{node.title}#{body}" end + + def mermaid_question(node) + question_node_id = node.slug.split("-")[1] + part = ["Q#{question_node_id}[\"`Q#{question_node_id}. #{node.title}`\"]:::question"] + node.options.each.with_index(1) do |option, index| + answer_node_id = "Q#{question_node_id}A#{index}" + next_node_title, next_node_number = option.next_node.split("-") + part << "Q#{question_node_id}---#{answer_node_id}\n" \ + "#{answer_node_id}([\"`A#{index}. #{option.label}`\"]):::answer\n" \ + "#{answer_node_id}-->#{next_node_title[0].upcase}#{next_node_number}\n" + end + part.join("\n") + end + + def mermaid_outcome(node) + outcome_node_id = node.slug.split("-")[1] + "O#{outcome_node_id}{{\"`O#{outcome_node_id}. #{node.title}`\"}}:::outcome" + end end diff --git a/app/views/editions/show.html.erb b/app/views/editions/show.html.erb index 70aa077bf..41d868f67 100644 --- a/app/views/editions/show.html.erb +++ b/app/views/editions/show.html.erb @@ -60,3 +60,4 @@ <% content_for :page_title, "Editing #{@resource.title}" %> + diff --git a/test/models/simple_smart_answer_edition_test.rb b/test/models/simple_smart_answer_edition_test.rb index 927d3bd20..5416e9dec 100644 --- a/test/models/simple_smart_answer_edition_test.rb +++ b/test/models/simple_smart_answer_edition_test.rb @@ -92,7 +92,10 @@ class SimpleSmartAnswerEditionTest < ActiveSupport::TestCase edition.nodes.build(slug: "outcome-1", title: "The first outcome", order: 3, kind: "outcome", body: "Outcome body") edition.nodes.build(slug: "outcome-2", title: "The second outcome", order: 4, kind: "outcome") - assert_equal "Introduction to the smart answer\n\n\nQuestion 1\nThe first question\n\nBody\n\nAnswer 1\noption one\nNext question for user: Outcome 1 (The first outcome)\n\nAnswer 2\noption two\nNext question for user: Outcome 2 (The second outcome)\n\n\n\nOutcome 1\nThe first outcome\nOutcome body\n\n\nOutcome 2\nThe second outcome\n", edition.whole_body + assert_equal "Introduction to the smart answer\n\n\nQuestion 1\nThe first question\n\nBody\n\nAnswer 1\noption one" \ + "\nNext question for user: Outcome 1 (The first outcome)\n\nAnswer 2\noption two\nNext question for" \ + " user: Outcome 2 (The second outcome)\n\n\n\nOutcome 1\nThe first outcome\nOutcome body\n\n\nOutcome" \ + " 2\nThe second outcome\n", edition.whole_body end should "create nodes with nested attributes" do @@ -237,5 +240,53 @@ class SimpleSmartAnswerEditionTest < ActiveSupport::TestCase assert_equal 2, @edition.nodes.size end end + + context "generating mermaid.js syntax" do + should "generate correct syntax from a simple smart answer with no nodes" do + edition = FactoryBot.build(:simple_smart_answer_edition, panopticon_id: @artefact.id) + edition.update(title: "Smarter than the average answer") + edition.save! + + assert_equal "%%{ init: {\n'theme': 'base',\n'themeVariables': {\n 'background': '#FFFFFF',\n" \ + " 'primaryTextColor': '#0B0C0C',\n 'lineColor': '#0b0c0c',\n 'fontSize': '23.75px'" \ + " } } }%%\nflowchart TD\naccTitle: Smarter than the average answer\naccDescr: A flowchart for the Smarter " \ + "than the average answer smart answer\nAA[Start]:::start\nclassDef answer fill: #F3F2F1, stroke:#505A5F;\nclassDef " \ + "outcome fill: #6FA4D2\nclassDef question fill: #B1B4B6, stroke:#505A5F;\nclassDef start fill:#00703c,color: " \ + "#ffffff", edition.generate_mermaid + end + + should "generate correct syntax from a simple smart answer with one node" do + edition = FactoryBot.build(:simple_smart_answer_edition, panopticon_id: @artefact.id) + edition.update(title: "Smarter than the average answer") + edition.nodes.build(slug: "question-1", title: "You approach two locked doors. Which do you choose?", kind: "question") + + edition.save! + + assert_equal "%%{ init: {\n'theme': 'base',\n'themeVariables': {\n 'background': '#FFFFFF',\n" \ + " 'primaryTextColor': '#0B0C0C',\n 'lineColor': '#0b0c0c',\n 'fontSize': '23.75px'" \ + " } } }%%\nflowchart TD\naccTitle: Smarter than the average answer\naccDescr: A flowchart for the Smarter " \ + "than the average answer smart answer\nAA[Start]:::start\nAA---Q1\nQ1[\"`Q1. You approach two locked doors. " \ + "Which do you choose?`\"]:::question\nclassDef answer fill: #F3F2F1, stroke:#505A5F;\nclassDef " \ + "outcome fill: #6FA4D2\nclassDef question fill: #B1B4B6, stroke:#505A5F;\nclassDef start fill:#00703c,color: " \ + "#ffffff", edition.generate_mermaid + end + + should "generate mermaid.js syntax from a simple smart answer with multiple nodes" do + edition = FactoryBot.build(:simple_smart_answer_edition, panopticon_id: @artefact.id) + + edition.nodes.build(slug: "question-1", title: "You approach two locked doors. Which do you choose?", kind: "question", options: [{ label: "A tiger fights you", next_node: "outcome-1" }]) + edition.nodes.build(slug: "outcome-1", title: "Tiger wins", kind: "outcome") + edition.save! + + assert_equal "%%{ init: {\n'theme': 'base',\n'themeVariables': {\n 'background': '#FFFFFF',\n" \ + " 'primaryTextColor': '#0B0C0C',\n 'lineColor': '#0b0c0c',\n 'fontSize': '23.75px'" \ + " } } }%%\nflowchart TD\naccTitle: Simple smart answer\naccDescr: A flowchart for the Simple " \ + "smart answer smart answer\nAA[Start]:::start\nAA---Q1\nQ1[\"`Q1. You approach two locked doors. " \ + "Which do you choose?`\"]:::question\nQ1---Q1A1\nQ1A1([\"`A1. A tiger fights you`\"]):::answer\n" \ + "Q1A1-->O1\n\nO1{{\"`O1. Tiger wins`\"}}:::outcome\nclassDef answer fill: #F3F2F1, stroke:#505A5F;\nclassDef " \ + "outcome fill: #6FA4D2\nclassDef question fill: #B1B4B6, stroke:#505A5F;\nclassDef start fill:#00703c,color: " \ + "#ffffff", edition.generate_mermaid + end + end # rubocop:enable Rails/SaveBang end