text_chart 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/text_chart/designer.rb +47 -34
- data/lib/text_chart/size_calculator.rb +40 -10
- data/lib/text_chart/version.rb +1 -1
- data/lib/text_chart.rb +36 -32
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 3151e15fd8d9c6ad4d4850b2d7200585644b19212bbac4bc6e8c1cf22b01fd51
         | 
| 4 | 
            +
              data.tar.gz: 276efc536bfc80c1e1df0b9378e5d1645fa284bbdf5b7652ff1798f3a3a76edd
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 9f452855f7b707e3bb44735bf75016ebed13665e267c458c17f2ff7f0f0828f94ebb57eafed7f8a88c507d1e4a864ebefc3764ee608e16f26d6a3bfb56c1cfbb
         | 
| 7 | 
            +
              data.tar.gz: ce3e6d56b4844b95f843954a39acf4e62344b02d6fbb752e396958085cd255240a0fad8a04cc2189f79f3eaf456dcecdd3af41312f5377ea8b04fcf10337428b
         | 
    
        data/lib/text_chart/designer.rb
    CHANGED
    
    | @@ -1,5 +1,3 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 1 | 
             
            class TextChart::Designer
         | 
| 4 2 | 
             
              # @param [TextChart] text_chart
         | 
| 5 3 | 
             
              # @param [TextChart::SizeCalculator] size_calc
         | 
| @@ -14,7 +12,7 @@ class TextChart::Designer | |
| 14 12 | 
             
              def draw_header
         | 
| 15 13 | 
             
                header = []
         | 
| 16 14 | 
             
                header << "#{@text_chart.title}\n"
         | 
| 17 | 
            -
                header << " | 
| 15 | 
            +
                header << "#{@text_chart.subtitle}\n"
         | 
| 18 16 | 
             
                header << "\n"
         | 
| 19 17 |  | 
| 20 18 | 
             
                @chart_canvas.prepend(*header)
         | 
| @@ -36,40 +34,46 @@ class TextChart::Designer | |
| 36 34 | 
             
                chart_line = 0
         | 
| 37 35 | 
             
                ref_width = @size_calc.calculate_reference_width
         | 
| 38 36 | 
             
                y_axis_width = @text_chart.size_config(:y_axis_width)
         | 
| 39 | 
            -
                 | 
| 40 | 
            -
                middle_bar_margin = @text_chart.size_config(:bar_spacing)
         | 
| 37 | 
            +
                bar_margin = @text_chart.size_config(:bar_margin)
         | 
| 41 38 | 
             
                bar_row = "###"
         | 
| 42 39 | 
             
                bar_width = @text_chart.size_config(:bar_width)
         | 
| 43 | 
            -
                 | 
| 44 | 
            -
             | 
| 45 | 
            -
                @text_chart.data.each do |d|
         | 
| 46 | 
            -
                  # + 1 to guarantee that the bar will always be rendered
         | 
| 47 | 
            -
                  bar_height = d + 1
         | 
| 40 | 
            +
                bar_start = bar_end = bar_top = 0
         | 
| 41 | 
            +
                height_of_bars = define_height_of_bars
         | 
| 48 42 |  | 
| 43 | 
            +
                height_of_bars.each do |height|
         | 
| 49 44 | 
             
                  bar_start = if bar_start == 0
         | 
| 50 | 
            -
                    ref_width +  | 
| 45 | 
            +
                    ref_width + bar_margin + y_axis_width
         | 
| 51 46 | 
             
                  else
         | 
| 52 47 | 
             
                    # + 1 because bar_end put us on the bar last column
         | 
| 53 | 
            -
                    bar_end + 1 +  | 
| 48 | 
            +
                    bar_end + 1 + bar_margin
         | 
| 54 49 | 
             
                  end
         | 
| 55 50 |  | 
| 56 51 | 
             
                  # - 1 because bar_start already put us on the bar first column
         | 
| 57 52 | 
             
                  bar_end = bar_start + bar_width - 1
         | 
| 58 53 |  | 
| 59 54 | 
             
                  chart_line = zero_line
         | 
| 60 | 
            -
                  bar_top =  | 
| 61 | 
            -
                   | 
| 55 | 
            +
                  bar_top = height - 1
         | 
| 56 | 
            +
                  height.times do |t|
         | 
| 62 57 | 
             
                    @chart_canvas[chart_line][bar_start..bar_end] = bar_row
         | 
| 63 58 |  | 
| 64 59 | 
             
                    chart_line -= 1 unless t == bar_top
         | 
| 65 60 | 
             
                  end
         | 
| 66 | 
            -
             | 
| 67 | 
            -
                  draw_reference_line(chart_line, ref_width + y_axis_width, bar_start)
         | 
| 68 61 | 
             
                end
         | 
| 69 62 |  | 
| 70 63 | 
             
                @chart_canvas
         | 
| 71 64 | 
             
              end
         | 
| 72 65 |  | 
| 66 | 
            +
              # @return [Array<String>]
         | 
| 67 | 
            +
              def paint
         | 
| 68 | 
            +
                @chart_canvas.map do |row|
         | 
| 69 | 
            +
                  next if row.gsub!(@text_chart.title, colorize(@text_chart.title, :bold))
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  row.gsub!(/-?\d/) { colorize($&, :cyan) }
         | 
| 72 | 
            +
                  row.gsub!(/#+/) { colorize($&, :blue) }
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
                @chart_canvas
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
             | 
| 73 77 | 
             
              private
         | 
| 74 78 |  | 
| 75 79 | 
             
              def build_empty_chart
         | 
| @@ -107,34 +111,43 @@ class TextChart::Designer | |
| 107 111 | 
             
              end
         | 
| 108 112 |  | 
| 109 113 | 
             
              def draw_references
         | 
| 110 | 
            -
                references = @text_chart. | 
| 114 | 
            +
                references = @text_chart.data
         | 
| 111 115 | 
             
                width = @size_calc.calculate_reference_width
         | 
| 112 | 
            -
                 | 
| 113 | 
            -
                ref_size = ref_start = ref_end = nil
         | 
| 114 | 
            -
                margin_size = @text_chart.size_config(:reference_and_y_axis_margin)
         | 
| 116 | 
            +
                y_axis_size = @size_calc.calculate_y_axis_size
         | 
| 117 | 
            +
                ref_size = ref_start = ref_end = ref_str = nil
         | 
| 115 118 |  | 
| 116 | 
            -
                 | 
| 117 | 
            -
                   | 
| 119 | 
            +
                references.each do |r|
         | 
| 120 | 
            +
                  row = y_axis_size - @size_calc.calculate_bar_height(r)
         | 
| 121 | 
            +
                  ref_str = r.to_s
         | 
| 122 | 
            +
                  ref_size = ref_str.size
         | 
| 118 123 |  | 
| 119 | 
            -
                  if ref_size ==  | 
| 124 | 
            +
                  if ref_size == width
         | 
| 120 125 | 
             
                    ref_start = 0
         | 
| 121 126 | 
             
                    ref_end = ref_size - 1
         | 
| 122 | 
            -
                    @chart_canvas[i][ref_start..ref_end] = references[i].to_s
         | 
| 123 127 | 
             
                  else
         | 
| 124 | 
            -
                    ref_start = ref_size
         | 
| 125 | 
            -
                     | 
| 128 | 
            +
                    ref_start = width - ref_size
         | 
| 129 | 
            +
                    ref_end = [ref_start, ref_size].max
         | 
| 126 130 | 
             
                  end
         | 
| 131 | 
            +
                  @chart_canvas[row][ref_start..ref_end] = ref_str
         | 
| 127 132 | 
             
                end
         | 
| 128 133 | 
             
              end
         | 
| 129 134 |  | 
| 130 | 
            -
               | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 135 | 
            +
              # @param string to be colorized [String]
         | 
| 136 | 
            +
              # @param desired color/formatting [Symbol]
         | 
| 137 | 
            +
              # @return colorized string [String]
         | 
| 138 | 
            +
              def colorize(str, format)
         | 
| 139 | 
            +
                case format
         | 
| 140 | 
            +
                when :bold
         | 
| 141 | 
            +
                  "\e[1m#{str}\e[22m"
         | 
| 142 | 
            +
                when :cyan
         | 
| 143 | 
            +
                  "\e[36m#{str}\e[0m"
         | 
| 144 | 
            +
                when :blue
         | 
| 145 | 
            +
                  "\e[34m#{str}\e[0m"
         | 
| 138 146 | 
             
                end
         | 
| 139 147 | 
             
              end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
              # @return height of each sample item [Array<Integer>]
         | 
| 150 | 
            +
              def define_height_of_bars
         | 
| 151 | 
            +
                @text_chart.data.map { |i| @size_calc.calculate_bar_height(i) }
         | 
| 152 | 
            +
              end
         | 
| 140 153 | 
             
            end
         | 
| @@ -17,14 +17,14 @@ class TextChart::SizeCalculator | |
| 17 17 | 
             
                    y_axis_width = @text_chart.size_config(:y_axis_width)
         | 
| 18 18 | 
             
                    result += y_axis_width
         | 
| 19 19 |  | 
| 20 | 
            -
                    left_margin = @text_chart.size_config(: | 
| 21 | 
            -
                    right_margin = @text_chart.size_config(: | 
| 20 | 
            +
                    left_margin = @text_chart.size_config(:bar_margin)
         | 
| 21 | 
            +
                    right_margin = @text_chart.size_config(:bar_margin)
         | 
| 22 22 | 
             
                    result += left_margin + right_margin
         | 
| 23 23 |  | 
| 24 24 | 
             
                    bar_width = @text_chart.size_config(:bar_width)
         | 
| 25 25 | 
             
                    result += @text_chart.data.size * bar_width
         | 
| 26 26 |  | 
| 27 | 
            -
                    bar_spacing = @text_chart.size_config(: | 
| 27 | 
            +
                    bar_spacing = @text_chart.size_config(:bar_margin)
         | 
| 28 28 | 
             
                    # -1 to avoid adding spacing after the last bar.
         | 
| 29 29 | 
             
                    result += (@text_chart.data.size - 1) * bar_spacing
         | 
| 30 30 |  | 
| @@ -36,10 +36,8 @@ class TextChart::SizeCalculator | |
| 36 36 | 
             
              def calculate_reference_width
         | 
| 37 37 | 
             
                @reference_width ||=
         | 
| 38 38 | 
             
                  begin
         | 
| 39 | 
            -
                     | 
| 40 | 
            -
                     | 
| 41 | 
            -
                    reference_margin = @text_chart.size_config(:reference_and_y_axis_margin)
         | 
| 42 | 
            -
                    biggest_item_width + reference_margin
         | 
| 39 | 
            +
                    biggest_number_size = @text_chart.data.map(&:to_s).map(&:size).max
         | 
| 40 | 
            +
                    biggest_number_size
         | 
| 43 41 | 
             
                  end
         | 
| 44 42 | 
             
              end
         | 
| 45 43 |  | 
| @@ -52,14 +50,23 @@ class TextChart::SizeCalculator | |
| 52 50 | 
             
                    x_axis_row = @text_chart.size_config(:x_axis_height)
         | 
| 53 51 | 
             
                    result += x_axis_row
         | 
| 54 52 |  | 
| 55 | 
            -
                     | 
| 56 | 
            -
             | 
| 57 | 
            -
                     | 
| 53 | 
            +
                    calculate_bar_height(@text_chart.data.max).times do
         | 
| 54 | 
            +
                      result += @text_chart.size_config(:bar_row_height)
         | 
| 55 | 
            +
                    end
         | 
| 58 56 |  | 
| 59 57 | 
             
                    result
         | 
| 60 58 | 
             
                  end
         | 
| 61 59 | 
             
              end
         | 
| 62 60 |  | 
| 61 | 
            +
              # @param bar [Integer]
         | 
| 62 | 
            +
              # @return the number of rows that we should render [Integer]
         | 
| 63 | 
            +
              def calculate_bar_height(bar)
         | 
| 64 | 
            +
                return 0 if bar.zero?
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                min_bar_height = 1
         | 
| 67 | 
            +
                (calculate_increase_percentile(@text_chart.data.min, bar) / bar_height_limiter).round + min_bar_height
         | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
             | 
| 63 70 | 
             
              # @return [Integer]
         | 
| 64 71 | 
             
              def calculate_x_axis_size
         | 
| 65 72 | 
             
                @x_axis_size ||= calculate_number_of_columns - calculate_reference_width
         | 
| @@ -73,4 +80,27 @@ class TextChart::SizeCalculator | |
| 73 80 | 
             
                    calculate_number_of_rows - x_axis_row
         | 
| 74 81 | 
             
                  end
         | 
| 75 82 | 
             
              end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
              private
         | 
| 85 | 
            +
             | 
| 86 | 
            +
              # @param initial value [Numeric]
         | 
| 87 | 
            +
              # @param final value [Numeric]
         | 
| 88 | 
            +
              # @return increase percentile [Float]
         | 
| 89 | 
            +
              def calculate_increase_percentile(initial, final)
         | 
| 90 | 
            +
                float_initial = initial.to_f
         | 
| 91 | 
            +
                float_final = final.to_f
         | 
| 92 | 
            +
                diff = float_final - float_initial
         | 
| 93 | 
            +
                (diff / float_initial) * 100.0
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
              # @return the denominator to assure the `max_rows` config [Integer]
         | 
| 97 | 
            +
              def bar_height_limiter
         | 
| 98 | 
            +
                @bar_height_limiter ||=
         | 
| 99 | 
            +
                  begin
         | 
| 100 | 
            +
                    limiter = 10.0
         | 
| 101 | 
            +
                    max_diff = calculate_increase_percentile(@text_chart.data.min, @text_chart.data.max)
         | 
| 102 | 
            +
                    limiter *= 10.0 until (max_diff / limiter).round <= @text_chart.size_config(:max_bar_height)
         | 
| 103 | 
            +
                    limiter
         | 
| 104 | 
            +
                  end
         | 
| 105 | 
            +
              end
         | 
| 76 106 | 
             
            end
         | 
    
        data/lib/text_chart/version.rb
    CHANGED
    
    
    
        data/lib/text_chart.rb
    CHANGED
    
    | @@ -8,41 +8,53 @@ require_relative "text_chart/designer" | |
| 8 8 | 
             
            # representing the chart, just like this one:
         | 
| 9 9 | 
             
            #
         | 
| 10 10 | 
             
            # text_chart demonstration
         | 
| 11 | 
            -
            #  | 
| 11 | 
            +
            # Show you how cool this is
         | 
| 12 12 | 
             
            #
         | 
| 13 | 
            -
            #  | 
| 14 | 
            -
            # | 
| 15 | 
            -
            #  | 
| 16 | 
            -
            # | 
| 17 | 
            -
            #  | 
| 18 | 
            -
            # | 
| 19 | 
            -
            #  | 
| 20 | 
            -
            #  | 
| 21 | 
            -
            #  | 
| 22 | 
            -
            #  | 
| 23 | 
            -
            # | 
| 13 | 
            +
            # 73|                                                         ###
         | 
| 14 | 
            +
            #   |                                                         ###
         | 
| 15 | 
            +
            # 67|             ###             ###                         ###         ###
         | 
| 16 | 
            +
            #   |             ###             ###                         ###         ###
         | 
| 17 | 
            +
            # 54|     ###     ###     ###     ###                         ### ###     ###
         | 
| 18 | 
            +
            #   |     ###     ###     ###     ###                         ### ###     ###
         | 
| 19 | 
            +
            # 44|     ### ### ###     ###     ###     ###                 ### ###     ### ###
         | 
| 20 | 
            +
            #   |     ### ### ###     ###     ###     ###                 ### ###     ### ###
         | 
| 21 | 
            +
            # 33|     ### ### ###     ### ### ###     ###                 ### ###     ### ###
         | 
| 22 | 
            +
            #   |     ### ### ###     ### ### ###     ###                 ### ###     ### ###
         | 
| 23 | 
            +
            # 27|     ### ### ### ### ### ### ###     ###         ### ### ### ###     ### ###
         | 
| 24 | 
            +
            # 20|     ### ### ### ### ### ### ###     ###     ### ### ### ### ### ### ### ###
         | 
| 25 | 
            +
            # 14| ### ### ### ### ### ### ### ### ### ###     ### ### ### ### ### ### ### ###
         | 
| 26 | 
            +
            # 10| ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
         | 
| 27 | 
            +
            #  5| ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
         | 
| 28 | 
            +
            #   ----------------------------------------------------------------------------------
         | 
| 24 29 | 
             
            class TextChart
         | 
| 25 30 | 
             
              class Error < StandardError; end
         | 
| 26 31 |  | 
| 27 32 | 
             
              # @param [String] title
         | 
| 28 | 
            -
              # @param [String]  | 
| 33 | 
            +
              # @param [String] subtitle
         | 
| 29 34 | 
             
              # @param [Array] data
         | 
| 30 | 
            -
               | 
| 35 | 
            +
              # @param [Boolean] colors
         | 
| 36 | 
            +
              def initialize(title, subtitle, data, colors = false)
         | 
| 37 | 
            +
                raise Error, "`data` cannot be empty" if data.empty?
         | 
| 38 | 
            +
             | 
| 31 39 | 
             
                @title = title
         | 
| 32 | 
            -
                @ | 
| 33 | 
            -
                @data = data.empty? ? [0] : data
         | 
| 34 | 
            -
                @ | 
| 40 | 
            +
                @subtitle = subtitle
         | 
| 41 | 
            +
                @data = data.empty? ? [0] : data.filter(&:positive?)
         | 
| 42 | 
            +
                @colors = colors
         | 
| 35 43 | 
             
                @size_calculator = SizeCalculator.new(self)
         | 
| 36 44 | 
             
                @designer = Designer.new(self, @size_calculator)
         | 
| 37 45 | 
             
              end
         | 
| 38 46 |  | 
| 39 | 
            -
              attr_reader :title, : | 
| 47 | 
            +
              attr_reader :title, :subtitle, :data, :size_calculator, :designer
         | 
| 40 48 |  | 
| 41 49 | 
             
              # @return [String]
         | 
| 42 50 | 
             
              def to_s
         | 
| 43 | 
            -
                @designer.draw_axis
         | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 51 | 
            +
                result = @designer.draw_axis &&
         | 
| 52 | 
            +
                  @designer.draw_bars &&
         | 
| 53 | 
            +
                  @designer.draw_header
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                result = @designer.paint if @colors
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                result.join
         | 
| 46 58 | 
             
              end
         | 
| 47 59 |  | 
| 48 60 | 
             
              # @param [Symbol] key
         | 
| @@ -55,18 +67,10 @@ class TextChart | |
| 55 67 |  | 
| 56 68 | 
             
              SIZE_CONFIG = {
         | 
| 57 69 | 
             
                y_axis_width: 1,
         | 
| 58 | 
            -
                 | 
| 59 | 
            -
                bar_area_right_margin: 3,
         | 
| 70 | 
            +
                bar_margin: 1,
         | 
| 60 71 | 
             
                bar_width: 3,
         | 
| 61 | 
            -
                bar_spacing: 7,
         | 
| 62 | 
            -
                reference_and_y_axis_margin: 1,
         | 
| 63 72 | 
             
                x_axis_height: 1,
         | 
| 64 | 
            -
                 | 
| 73 | 
            +
                bar_row_height: 1,
         | 
| 74 | 
            +
                max_bar_height: 60
         | 
| 65 75 | 
             
              }
         | 
| 66 | 
            -
             | 
| 67 | 
            -
              def define_references
         | 
| 68 | 
            -
                r = [*@data.min..@data.max].reverse
         | 
| 69 | 
            -
                r << 0 unless r.include?(0)
         | 
| 70 | 
            -
                r
         | 
| 71 | 
            -
              end
         | 
| 72 76 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: text_chart
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 1.0.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Gustavo Ribeiro
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2024-01-27 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies: []
         | 
| 13 13 | 
             
            description:
         | 
| 14 14 | 
             
            email:
         |