diff --git a/lib/squid/axis.rb b/lib/squid/axis.rb index 5f63c74..3c20a69 100644 --- a/lib/squid/axis.rb +++ b/lib/squid/axis.rb @@ -7,8 +7,8 @@ class Axis include Format attr_reader :data - def initialize(data, steps:, stack:, format:, &block) - @data, @steps, @stack, @format = data, steps, stack, format + def initialize(data, min:, max:, steps:, stack:, format:, &block) + @data, @min, @max, @steps, @stack, @format = data, min, max, steps, stack, format @width_proc = block if block_given? end @@ -39,12 +39,14 @@ def label_width(label) end def min + return @min if @min if @data.any? && values.first && values.first.any? [values.first.min, 0].min end end def max + return @max if @max if @data.any? && values.last && values.last.any? closest_step_to values.last.max end diff --git a/lib/squid/configuration.rb b/lib/squid/configuration.rb index 431af18..69ab622 100644 --- a/lib/squid/configuration.rb +++ b/lib/squid/configuration.rb @@ -33,7 +33,7 @@ def self.boolean end def self.integer - -> (value) { value.to_i } + -> (value) { value.to_i if value.present? } end def self.symbol @@ -59,6 +59,8 @@ def self.array(proc = nil) labels: {as: array(boolean)}, legend: {as: boolean, default: 'true'}, line_widths: {as: array(float)}, + min: {as: integer}, + max: {as: integer}, steps: {as: integer, default: '4'}, ticks: {as: boolean, default: 'true'}, type: {as: symbol, default: 'column'}, diff --git a/lib/squid/graph.rb b/lib/squid/graph.rb index cf0bb7e..971d3bb 100644 --- a/lib/squid/graph.rb +++ b/lib/squid/graph.rb @@ -13,7 +13,7 @@ module Squid class Graph extend Settings has_settings :baseline, :border, :chart, :colors, :every, :formats, :height - has_settings :legend, :line_widths, :steps, :ticks, :type, :labels + has_settings :legend, :line_widths, :min, :max, :steps, :ticks, :type, :labels def initialize(document, data = {}, settings = {}) @data, @settings = data, settings @@ -65,7 +65,7 @@ def draw_charts end def draw_chart(axis, second_axis: false) - args = {minmax: axis.minmax, height: grid_height, stack: stack?} + args = {minmax: axis.minmax, height: grid_height, stack: stack?, type: type} args[:labels] = items_of labels, skip_first_if: second_axis args[:formats] = items_of formats, skip_first_if: second_axis points = Point.for axis.data, args @@ -96,7 +96,7 @@ def right def axis(first:, last:) series = @data.values[first, last].map(&:values) - options = {steps: steps, stack: stack?, format: formats[first]} + options = {min: min, max: max, steps: steps, stack: stack?, format: formats[first]} Axis.new(series, options) {|label| @plot.width_of label} end diff --git a/lib/squid/point.rb b/lib/squid/point.rb index 1a34131..4b4d6eb 100644 --- a/lib/squid/point.rb +++ b/lib/squid/point.rb @@ -4,16 +4,52 @@ module Squid class Point extend Format - def self.for(series, minmax:, height:, labels:, stack:, formats:) + def self.for(series, minmax:, height:, labels:, stack:, formats:, type:) @min = Hash.new 0 @max = Hash.new 0 min, max = minmax + + case type + when :point + adjusted_series = series.map{|array| array.map{ |n| (minmax[0]..minmax[1]).include?(n) ? n : nil } } + when :line, :two_axis + adjusted_series = series + when :column + adjusted_series = series.map do |array| + array.map do |n| + if (minmax[0]..minmax[1]).include?(n) + n - minmax[0] + elsif n > max + max - min + else + nil + end + end + end + when :stack + adjusted_series = series + end + offset = -> (value) { value * height.to_f / (max-min) } - series.map.with_index do |values, series_i| + + case type + when :point + offset = -> (value) { value * height.to_f / (max-min) } + when :line, :two_axis + offset = -> (value) { value * height.to_f / (max-min) } + when :column + offset = -> (value) { value * height.to_f / (max-min) } + when :stack + offset = -> (value) { value * height.to_f / (max-min) } + end + + adjusted_series.map.with_index do |values, series_i| values.map.with_index do |value, i| h = y_for value, index: i, stack: false, &offset if value y = y_for value, index: i, stack: stack, &offset if value - y = y - offset.call([min, 0].min) if value + unless type == :column + y = y - offset.call(min) if value + end label = format_for value, formats[series_i] if labels[series_i] new y: y, height: h, index: i, label: label, negative: value.to_f < 0 end @@ -27,7 +63,6 @@ def initialize(y:, height:, index:, label:, negative:) end private - def self.y_for(value, index:, stack:, &block) if stack hash = (value > 0) ? @max : @min