Class: TTY::Pie

Inherits:
Object
  • Object
show all
Defined in:
lib/tty/pie.rb,
lib/tty/pie/version.rb,
lib/tty/pie/data_item.rb

Defined Under Namespace

Classes: DataItem

Constant Summary collapse

FULL_CIRCLE_DEGREES =
360
POINT_SYMBOL =
""
LEGEND_LINE_SPACE =
1
LEGEND_LEFT_SPACE =
4
VERSION =
"0.4.0"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data: [], top: nil, left: nil, radius: 10, legend: {}, fill: POINT_SYMBOL, aspect_ratio: 2, colors: []) ⇒ Pie

Create pie chart

Examples:

data = [ { name: "BTC", value: 5977, fill: "*" } ]
pie_chart = TTY::Pie.new(data: data, radius: 2)

Parameters:

  • data (Array[Hash]) (defaults to: [])

    the data to display in each slice

  • top (Integer) (defaults to: nil)
  • left (Integer) (defaults to: nil)
  • radius (Integer) (defaults to: 10)
  • legend (Hash, Boolean) (defaults to: {})
  • fill (String) (defaults to: POINT_SYMBOL)
  • aspect_ratio (Float) (defaults to: 2)


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/tty/pie.rb', line 51

def initialize(data: [], top: nil, left: nil, radius: 10,
               legend: {}, fill: POINT_SYMBOL, aspect_ratio: 2,
               colors: [])
  @data = data.dup
  @top = top
  @left = left
  @radius = radius
  @legend = legend
  @fill = Array(fill)
  @colors = Array(colors)
  @aspect_ratio = aspect_ratio
  @center_x = (left || 0) + radius * aspect_ratio
  @center_y = (top || 0) + radius

  @pastel = Pastel.new(enabled: !!colors)
  @cursor = TTY::Cursor
end

Instance Attribute Details

#aspect_ratioObject (readonly)

Returns the value of attribute aspect_ratio.



25
26
27
# File 'lib/tty/pie.rb', line 25

def aspect_ratio
  @aspect_ratio
end

#center_xObject (readonly)

Returns the value of attribute center_x.



21
22
23
# File 'lib/tty/pie.rb', line 21

def center_x
  @center_x
end

#center_yObject (readonly)

Returns the value of attribute center_y.



21
22
23
# File 'lib/tty/pie.rb', line 21

def center_y
  @center_y
end

#colorsObject (readonly)

Returns the value of attribute colors.



31
32
33
# File 'lib/tty/pie.rb', line 31

def colors
  @colors
end

#cursorObject (readonly)

Returns the value of attribute cursor.



27
28
29
# File 'lib/tty/pie.rb', line 27

def cursor
  @cursor
end

#fillObject (readonly)

Returns the value of attribute fill.



29
30
31
# File 'lib/tty/pie.rb', line 29

def fill
  @fill
end

#leftObject (readonly)

Returns the value of attribute left.



19
20
21
# File 'lib/tty/pie.rb', line 19

def left
  @left
end

#legendObject (readonly)

Returns the value of attribute legend.



33
34
35
# File 'lib/tty/pie.rb', line 33

def legend
  @legend
end

#radiusObject (readonly)

Returns the value of attribute radius.



23
24
25
# File 'lib/tty/pie.rb', line 23

def radius
  @radius
end

#topObject (readonly)

Returns the value of attribute top.



19
20
21
# File 'lib/tty/pie.rb', line 19

def top
  @top
end

Instance Method Details

#add(item) ⇒ self Also known as: <<

Add a data item

Parameters:

  • (Hash)

Returns:

  • (self)


100
101
102
103
# File 'lib/tty/pie.rb', line 100

def add(item)
  @data << item
  self
end

#clearObject Also known as: reset

Reset data



174
175
176
177
# File 'lib/tty/pie.rb', line 174

def clear
  @data = []
  self
end

#data_itemsArray[DataItem]

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Convert data into DataItems

Returns:



83
84
85
86
87
88
89
90
91
# File 'lib/tty/pie.rb', line 83

def data_items
  total_value = total
  @data.each_with_index.map do |item, i|
    percent = (item[:value] * 100) / total_value.to_f
    color_fill = item[:fill] || fill[i % fill.size]
    color = colors && !colors.empty? ? colors[i % colors.size] : item.fetch(:color, false)
    DataItem.new(item[:name], item[:value], percent, color, color_fill)
  end
end

#renderString Also known as: to_s

Draw a pie based on the provided data

Returns:

  • (String)


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/tty/pie.rb', line 121

def render
  items = data_items
  return "" if items.empty?
  angles = data_angles(items)
  output = []

  labels = items.map { |item| item.to_label(legend) }
  label_vert_space  = legend_line
  label_horiz_space = legend_left
  label_offset  = labels.size / 2
  label_boundry = label_vert_space * label_offset
  labels_range  = (-label_boundry..label_boundry).step(label_vert_space)

  (-radius..radius).each do |y|
    width = (Math.sqrt(radius * radius - y * y) * aspect_ratio).round
    width = width.zero? ? (radius / aspect_ratio).round : width

    output << " " * (center_x - width) if top.nil?
    (-width..width).each do |x|
      angle = radian_to_degree(Math.atan2(x, y))
      item = items[select_data_item(angle, angles)]
      if !top.nil?
        output << cursor.move_to(center_x + x, center_y + y)
      end
      if item.color
        output << @pastel.decorate(item.fill, item.color)
      else
        output << item.fill
      end
    end

    if legend
      if !top.nil?
        output << cursor.move_to(center_x + aspect_ratio * radius + label_horiz_space, center_y + y)
      end
      if labels_range.include?(y)
        if top.nil?
          output << " " * ((center_x - (left.to_i + width)) + label_horiz_space)
        end
        output << labels[label_offset + y / label_vert_space]
      end
    end

    output << "\n"
  end

  output.join
end

#totalInteger

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Total for the data items

Returns:

  • (Integer)


74
75
76
# File 'lib/tty/pie.rb', line 74

def total
  @data.inject(0) { |sum, item| sum += item[:value]; sum }
end

#update(data) ⇒ Object

Replace current data with new set

Parameters:

  • (Array[Hash])


111
112
113
114
# File 'lib/tty/pie.rb', line 111

def update(data)
  @data = data
  self
end