From 6dd129cec0d6b96c9ff166302d7f91d7df9d1e8f Mon Sep 17 00:00:00 2001 From: Benjamin Scott Date: Tue, 15 Oct 2024 17:29:10 -0600 Subject: [PATCH] feat: add brand score parser --- Gemfile.lock | 2 +- lib/glare/ux-metrics/ux_metrics.rb | 79 +++++++++++++++++++++++++++++ lib/glare/ux-metrics/version.rb | 2 +- sig/glare/ux_metrics/ux_metrics.rbs | 18 +++++++ spec/glare/ux-metrics/ux_metrics.rb | 37 ++++++++++++++ 5 files changed, 136 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 902d014..6fceea8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - glare-ux-metrics-rb (0.2.0) + glare-ux-metrics-rb (0.2.1) GEM remote: https://rubygems.org/ diff --git a/lib/glare/ux-metrics/ux_metrics.rb b/lib/glare/ux-metrics/ux_metrics.rb index 44f46f8..ea7e033 100644 --- a/lib/glare/ux-metrics/ux_metrics.rb +++ b/lib/glare/ux-metrics/ux_metrics.rb @@ -366,6 +366,85 @@ def correct_data end end + module BrandScore + class Parser + CHOICE_KEYS = %w[ + helpful + clear + engaging + motivating + skeptical + confusing + uninteresting + overwhelming + ].freeze + + def initialize(questions:) + @questions = questions + end + + attr_reader :questions + + def valid? + return false unless questions.is_a?(Array) + + choices = questions.first + return false unless choices.is_a?(Hash) && choices.size + + missing_attributes = CHOICE_KEYS - choices.keys.map(&:to_s) + return false unless missing_attributes.empty? + + true + end + + def parse + choices = questions.first + result = choices[:helpful].to_f + + choices[:clear].to_f + + choices[:engaging].to_f + + choices[:motivating].to_f - + choices[:skeptical].to_f - + choices[:confusing].to_f - + choices[:uninteresting].to_f - + choices[:overwhelming].to_f + + sentiment_status = if result > 1.5 + "positive" + elsif result > 1 + "neutral" + else + "negative" + end + + sentiment_label = if sentiment_status == "positive" + "High Sentiment" + elsif sentiment_status == "neutral" + "Average Sentiment" + else + "Low Sentiment" + end + + Result.new(result: result, threshold: sentiment_status, label: sentiment_label) + end + + class InvalidDataError < Error + def initialize(msg = "Data not valid. Correct data format is: \n\n#{correct_data}") + super(msg) + end + + def correct_data + { + very_satisfied: "string|integer|float", + somewhat_satisfied: "string|integer|float", + neutral: "string|integer|float", + somewhat_dissatisfied: "string|integer|float", + very_dissatisfied: "string|integer|float", + }.to_json + end + end + end + end + class Result def initialize(result:, threshold:, label:) @result = result diff --git a/lib/glare/ux-metrics/version.rb b/lib/glare/ux-metrics/version.rb index 7bb9e9c..767d85b 100644 --- a/lib/glare/ux-metrics/version.rb +++ b/lib/glare/ux-metrics/version.rb @@ -2,6 +2,6 @@ module Glare module UxMetrics - VERSION = "0.2.0" + VERSION = "0.2.1" end end \ No newline at end of file diff --git a/sig/glare/ux_metrics/ux_metrics.rbs b/sig/glare/ux_metrics/ux_metrics.rbs index a6710e9..4b77387 100644 --- a/sig/glare/ux_metrics/ux_metrics.rbs +++ b/sig/glare/ux_metrics/ux_metrics.rbs @@ -100,6 +100,24 @@ module Glare end end + module BrandScore + class Parser + CHOICE_KEYS: Array[String] + attr_reader questions: Array[Hash[::Symbol | ::String, ::String | ::Float | ::Integer] | Array[::String | ::Float | ::Integer]] + + def initialize: ( + questions: Array[Hash[::Symbol | ::String, ::String | ::Float | ::Integer] | Array[::String | ::Float | ::Integer]], + ) -> void + + def valid?: -> bool + + def parse: -> Result + + class InvalidDataError < Error + def correct_data: -> String + end + end + end class Result attr_reader result: Float diff --git a/spec/glare/ux-metrics/ux_metrics.rb b/spec/glare/ux-metrics/ux_metrics.rb index 7e76cc7..c0def38 100644 --- a/spec/glare/ux-metrics/ux_metrics.rb +++ b/spec/glare/ux-metrics/ux_metrics.rb @@ -169,4 +169,41 @@ expect(data.result.is_a?(Float) && data.label.is_a?(String) && data.threshold.is_a?(String)).to eq(true) end end + + describe Glare::UxMetrics::BrandScore do + let(:brand_score_data) do + [ + { + helpful: 0.1, + clear: 0.1, + engaging: 0.1, + motivating: 0.1, + skeptical: 0.1, + confusing: 0.1, + uninteresting: 0.1, + overwhelming: 0.1 + }, + [0.2, 0.3, 0.4, 0.4, 0.2, 0.2, 0.2, 0.2, 0.0], + ] + end + + it "validates valid brand score data" do + data = Glare::UxMetrics::BrandScore::Parser.new( + questions: brand_score_data, + ) + expect(data.valid?).to eq(true) + end + + it "invalidates invalid brand score data" do + data = Glare::UxMetrics::BrandScore::Parser.new(questions: [{ hi: "yooo" }]) + expect(data.valid?).to eq(false) + end + + it "returns valid data" do + data = Glare::UxMetrics::BrandScore::Parser.new( + questions: brand_score_data, + ).parse + expect(data.result.is_a?(Float) && data.label.is_a?(String) && data.threshold.is_a?(String)).to eq(true) + end + end end