chartd 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: eab546b1677131a3af4f675d30377798e59a526a
4
+ data.tar.gz: 4652a53ccaf3d551fd99c1176c4d0c075a9f8463
5
+ SHA512:
6
+ metadata.gz: aa4086f5cbdbac14f11107992bb9d82c4cbe8d56dd28dfe16f31e46c66c2ddba82b57c5a00477d659432ba470248eea69079fb7a160a6a77f970f3fe07754a5b
7
+ data.tar.gz: 47fb6bdd43be5690ace269f3b677c3535bb37acfe88fd2c66d92c0735a53895e8f97101c056420c4f75d007de2056061ddff572449caefb17176700e3cf981af
@@ -0,0 +1,17 @@
1
+ # EditorConfig helps developers define and maintain consistent
2
+ # coding styles between different editors and IDEs
3
+ # editorconfig.org
4
+
5
+ root = true
6
+
7
+ [*]
8
+
9
+ # Change these settings to your own preference
10
+ indent_style = space
11
+ indent_size = 2
12
+
13
+ # We recommend you to keep these unchanged
14
+ end_of_line = lf
15
+ charset = utf-8
16
+ trim_trailing_whitespace = true
17
+ insert_final_newline = true
@@ -0,0 +1,2 @@
1
+ coverage/
2
+ chartd-*.gem
@@ -0,0 +1,12 @@
1
+ sudo: false
2
+ language: ruby
3
+
4
+ rvm:
5
+ - 2.2.4
6
+ - 2.3.0
7
+ - ruby-head
8
+
9
+ cache: bundler
10
+
11
+ notifications:
12
+ email: false
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,31 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ chartd (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ docile (1.1.5)
10
+ json (2.0.2)
11
+ power_assert (0.3.0)
12
+ rake (11.2.2)
13
+ simplecov (0.12.0)
14
+ docile (~> 1.1.0)
15
+ json (>= 1.8, < 3)
16
+ simplecov-html (~> 0.10.0)
17
+ simplecov-html (0.10.0)
18
+ test-unit (3.2.1)
19
+ power_assert
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ chartd!
26
+ rake (~> 11.2)
27
+ simplecov (~> 0.12)
28
+ test-unit (~> 3.2)
29
+
30
+ BUNDLED WITH
31
+ 1.11.2
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Max Lielje & David Pfahler
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,125 @@
1
+ # `chartd-rb` – Encode data for chartd.co
2
+
3
+ [![Build Status](https://travis-ci.org/commissure/chartd-rb.svg?branch=master)](https://travis-ci.org/commissure/chartd-rb)
4
+
5
+ :chart_with_upwards_trend: `chartd-rb` is a Ruby gem for [chartd.co],
6
+ a service from [@stathat], that allows you to creat a chart by encoding
7
+ a dataset into an URL, like so:
8
+
9
+ [chartd.co]: https://chartd.co
10
+ [@stathat]: https://github.com/stathat
11
+
12
+ ```
13
+ https://chartd.co/a.png?w=580&h=180&d0=SRWfaZHLHEDABKKTUYgpqqvws0138eZfaYtwxxsxyst&ymin=94.48&ymax=103.3
14
+ ```
15
+
16
+ The URL can then be used with a simple `<img>` tag and the resulting
17
+ chart looks like this:
18
+
19
+ <img src="https://chartd.co/a.png?w=580&h=180&d0=SRWfaZHLHEDABKKTUYgpqqvws0138eZfaYtwxxsxyst&ymin=94.48&ymax=103.3">
20
+
21
+
22
+ ## Usage
23
+
24
+ ```ruby
25
+ # grab some data
26
+ data = [1, 2, 3]
27
+
28
+ # and create a chart
29
+ chart = Chartd::Chart.new(data)
30
+
31
+ chart.url # => https://chartd.co/a.png?d0=Ae9…
32
+ ```
33
+
34
+ ### Y-Axis Minimum & Maximum
35
+
36
+ By default `chartd` uses the minimum and maximum values from your
37
+ dataset. They can be set explicitly like this:
38
+
39
+ ```ruby
40
+ Chartd::Chart.new(data, min: 0, max: 100)
41
+ ```
42
+
43
+ ### Multiple Datasets
44
+
45
+ `data` can also be a multidimensional array, which will result in the
46
+ chart having multiple lines. The maximum of datasets to chart is 5.
47
+
48
+ Example:
49
+
50
+ ```ruby
51
+ # grab some more data
52
+ data = [
53
+ [1, 3, 2],
54
+ [5, 3, 4]
55
+ ]
56
+
57
+ # and create a chart
58
+ chart = Chartd::Chart.new(data)
59
+
60
+ chart.url # => https://chartd.co/a.png?d0=AeP&d1=9et…
61
+ ```
62
+
63
+ ### Width & Height
64
+
65
+ The default dimensions of a chart are `580px x 180px`. You can change
66
+ them using the `options` parameter:
67
+
68
+ ```ruby
69
+ Chartd::Chart.new(data, options: { w: 2000, h: 1000 })
70
+ ```
71
+
72
+ **:warning: Important:** chartd doubles the dimensions of the chart so
73
+ that the resulting image is `@2x`, meaning it looks great on retina
74
+ (high res) screens.
75
+
76
+ ### Disabling Y-Axis Labels
77
+
78
+ The y-axis are both labeled by default. Set `ylabel` to `false` when
79
+ creating a chart to turn that off:
80
+
81
+ ```ruby
82
+ Chartd::Chart.new(data, ylabels: false)
83
+ ```
84
+
85
+ ### Image Format
86
+
87
+ While chartd supports both `.svg` and `.png`, `chartd-rb` currently
88
+ only supports `.png`. [Issue #2][#2] explains why.
89
+
90
+ [#2]: https://github.com/commissure/chartd-rb/issues/2
91
+
92
+ ### Options
93
+
94
+ The `options` hash is written directly to the final URL, meaning
95
+ that [all parameters documented on chartd.co][chartd] can be used.
96
+ Example:
97
+
98
+ [chartd]: https://chartd.co/
99
+
100
+ ```ruby
101
+ Chartd::Chart.new(data, options: {
102
+ t: 'My Awesome Chart',
103
+ step: 1,
104
+ hl: 1,
105
+ })
106
+ ```
107
+
108
+ I would be happy to accept a PR that integrates some of them (for
109
+ example the coloring) a little bit more nicely.
110
+
111
+
112
+ ## Contributing
113
+
114
+ 1. Fork the repository
115
+ 2. Create a feature branch: `git checkout -b your-feature`
116
+ 3. Add your changes
117
+ 4. Write tests and check coverage report in `coverage/index.html`
118
+ 5. Push changes: `git push -u origin your-feature`
119
+ 6. Submit a pull request
120
+
121
+
122
+ ## License
123
+
124
+ This project is licensed under the **MIT license**. See the `LICENSE`
125
+ file for details.
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc 'Run tests'
8
+ task default: :test
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'chartd'
3
+ s.version = '1.0.0'
4
+ s.summary = 'Encode values for chartd.co'
5
+ s.description = 'Chartd helps you encode values for use with chartd.co.'
6
+ s.authors = ['Max Lielje', 'David Pfahler']
7
+ s.email = 'max@pagespeed.io'
8
+ s.files = `git ls-files`.split("\n")
9
+ s.test_files = `git ls-files -- test/*`.split("\n")
10
+
11
+ s.homepage = 'https://github.com/commissure/chartd-rb'
12
+ s.license = 'MIT'
13
+
14
+ s.add_development_dependency 'rake', '~> 11.2'
15
+ s.add_development_dependency 'test-unit', '~> 3.2'
16
+ s.add_development_dependency 'simplecov', '~> 0.12'
17
+ end
@@ -0,0 +1,10 @@
1
+ require 'chartd/chart'
2
+ require 'chartd/encoder'
3
+
4
+ class Chartd
5
+ # helper method for directly encoding data for when the user wants to
6
+ # generate the chart URL herself.
7
+ def self.encode(*args)
8
+ Encoder.encode(*args)
9
+ end
10
+ end
@@ -0,0 +1,66 @@
1
+ require 'chartd/encoder'
2
+ require 'uri'
3
+
4
+ class Chartd
5
+ BASE_URL = URI.parse('https://chartd.co/a.png')
6
+
7
+ class Chart
8
+ ERR_BAD_DATASET = 'Dataset has to be an array of Fixnums and/or Floats.'.freeze
9
+ ERR_TOO_MANY_DATASETS = 'Too many datasets supplied, the maximum is 5.'.freeze
10
+
11
+ attr_reader :dataset
12
+
13
+ # allow min and max to be changed after instantiating a Chart
14
+ attr_accessor :min, :max
15
+
16
+ def initialize(dataset = [], min: nil, max: nil, ylabels: true, options: {})
17
+ raise ERR_BAD_DATASET unless dataset.is_a?(Array)
18
+ raise ERR_TOO_MANY_DATASETS if dataset.count > 5
19
+
20
+ # Check if dataset is multidimensional and if so, use it as is.
21
+ # Otherwise make it multidimensional.
22
+ if dataset[0].is_a?(Array)
23
+ @dataset = dataset
24
+ else
25
+ @dataset = [dataset]
26
+ end
27
+
28
+ # calculate min and max across the entire dataset but only if they are
29
+ # not set explicitly.
30
+ @min = min || dataset.flatten.min
31
+ @max = max || dataset.flatten.max
32
+
33
+ @ylabels = ylabels
34
+
35
+ @options = default_options.merge(options)
36
+ end
37
+
38
+ def url
39
+ u = BASE_URL.dup
40
+
41
+ # encode each piece of data and append it to URL as params
42
+ encoded_data = @dataset.each_with_index.map do |d, i|
43
+ ["d#{i}", Encoder.encode(d, min: @min, max: @max)]
44
+ end
45
+
46
+ # set labels for y axis when they’re enabled (which they are by default)
47
+ if @ylabels
48
+ @options[:ymin] ||= @min
49
+ @options[:ymax] ||= @max
50
+ end
51
+
52
+ u.query = URI.encode_www_form(
53
+ @options.merge(encoded_data.to_h)
54
+ )
55
+ u.to_s.force_encoding('utf-8')
56
+ end
57
+
58
+ private
59
+
60
+ # Default options for a chart URL, can be overridden when instantiating a
61
+ # Chart using the options argument.
62
+ def default_options
63
+ { w: 580, h: 180 }
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,44 @@
1
+ class Chartd
2
+ module Encoder
3
+ B62 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.freeze
4
+
5
+ # encode encodes a dataset to a format that chartd.co understands.
6
+ # It optionally takes min and max values that change the resulting chart.
7
+ def self.encode(dataset = [], min: nil, max: nil)
8
+ return '' if dataset.empty?
9
+
10
+ # either use custom min & max values or take them from the dataset
11
+ min ||= dataset.min
12
+ max ||= dataset.max
13
+
14
+ range = dim(max, min)
15
+
16
+ # if the range of the data is
17
+ return B62[0] * dataset.count if range == 0
18
+
19
+ enclen = B62.length - 1
20
+ encoded = dataset.map do |v|
21
+ index = (enclen * (v - min) / range).to_i
22
+
23
+ # TODO: see if else case is even possible
24
+ if index >= 0 && index < B62.length
25
+ B62[index]
26
+ else
27
+ B62[0]
28
+ end
29
+ end
30
+
31
+ encoded.join
32
+ end
33
+
34
+ # dim returns the maximum of x-y or 0.
35
+ # It is used to calculate the range of the dataset.
36
+ def self.dim(x, y)
37
+ # TODO: maybe raise an exception if max < min (x < y)
38
+ return 0 if x < y
39
+
40
+ x - y
41
+ end
42
+ private_class_method :dim
43
+ end
44
+ end
@@ -0,0 +1,108 @@
1
+ require_relative 'test_helper'
2
+
3
+ require 'test/unit'
4
+ require 'chartd'
5
+
6
+ class ChartdTest < Test::Unit::TestCase
7
+ def test_chart
8
+ expected = 'https://chartd.co/a.png?w=580&h=180&ymin=1.2&ymax=3.1&d0=Am9'
9
+ chart = Chartd::Chart.new([1.2, 2.4, 3.1])
10
+
11
+ assert_equal expected, chart.url
12
+ end
13
+
14
+ def test_chart_multiline
15
+ testdata = {
16
+ 'https://chartd.co/a.png?w=580&h=180&ymin=0.17&ymax=3.1&d0=Vu9&d1=QAI' => [
17
+ [1.2, 2.4, 3.1],
18
+ [0.944, 0.170, 0.601],
19
+ ],
20
+ 'https://chartd.co/a.png?w=580&h=180&ymin=1&ymax=5&d0=AeP&d1=9et' => [
21
+ [1, 3, 2],
22
+ [5, 3, 4],
23
+ ],
24
+ }
25
+
26
+ testdata.each do |expected, dataset|
27
+ chart = Chartd::Chart.new(dataset)
28
+ assert_equal expected, chart.url
29
+ end
30
+ end
31
+
32
+ def test_chart_multiline_custom_min_max
33
+ testdata = {
34
+ 'https://chartd.co/a.png?w=580&h=180&ymin=0&ymax=4&d0=Skv&d1=OCJ' => {
35
+ dataset: [
36
+ [1.2, 2.4, 3.1],
37
+ [0.944, 0.170, 0.601],
38
+ ],
39
+ min: 0,
40
+ max: 4,
41
+ },
42
+ 'https://chartd.co/a.png?w=580&h=180&ymin=0&ymax=6&d0=KeU&d1=yeo' => {
43
+ dataset: [
44
+ [1, 3, 2],
45
+ [5, 3, 4],
46
+ ],
47
+ min: 0,
48
+ max: 6,
49
+ },
50
+ }
51
+
52
+ testdata.each do |expected, data|
53
+ chart = Chartd::Chart.new(
54
+ data[:dataset],
55
+ min: data[:min],
56
+ max: data[:max]
57
+ )
58
+ assert_equal expected, chart.url
59
+ end
60
+ end
61
+
62
+ def test_normalize_datasets
63
+ assert_equal [[1, 2, 3]], Chartd::Chart.new([1, 2, 3]).dataset
64
+ assert_equal [[2, 3], [3, 4]], Chartd::Chart.new([[2, 3], [3, 4]]).dataset
65
+ end
66
+
67
+ def test_min_max_accessors
68
+ dataset = [1, 2, 3]
69
+
70
+ regular = Chartd::Chart.new(dataset, min: 0, max: 5)
71
+
72
+ with_accessors = Chartd::Chart.new(dataset)
73
+ with_accessors.min = 0
74
+ with_accessors.max = 5
75
+
76
+ assert_equal regular.url, with_accessors.url
77
+ end
78
+
79
+ def test_raise_on_bad_dataset
80
+ assert_raise do
81
+ Chartd::Chart.new('foo bar')
82
+ end
83
+
84
+ assert_raise do
85
+ # a maximum of 5 datasets is supported by chartd
86
+ Chartd::Chart.new([[1], [1], [1], [1], [1], [1]])
87
+ end
88
+ end
89
+
90
+ def test_disable_y_labels
91
+ url = Chartd::Chart.new([1, 2, 3], ylabels: false).url
92
+ assert_no_match %r{ymin=}, url
93
+ assert_no_match %r{ymax=}, url
94
+ end
95
+
96
+ def test_options
97
+ options = {
98
+ t: 'Awesome Chart',
99
+ step: 1,
100
+ foo: 'bar',
101
+ }
102
+
103
+ url = Chartd::Chart.new([1, 2, 3], options: options).url
104
+ assert_match %r{t=Awesome\+Chart}, url
105
+ assert_match %r{step=1}, url
106
+ assert_match %r{foo=bar}, url
107
+ end
108
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'test_helper'
2
+
3
+ require 'test/unit'
4
+ require 'chartd'
5
+
6
+ class Chartd::EncodeTest < Test::Unit::TestCase
7
+ def test_encode
8
+ testcases = [
9
+ [[1.2, 2.4, 3.1], 'Am9'],
10
+ [[40, 50, 33.2], 'Y8A'],
11
+ [[0, 9, 9], 'A99'],
12
+ [[0.944, 0.170, 0.201, 0.839, 0.284, 0.485, 0.154, 0.431, 0.119, 0.679], '9DG1MbCXAp'],
13
+ [[0, -2, 9], 'LA9'],
14
+ [[0], 'A'],
15
+ [[], ''],
16
+ ]
17
+
18
+ testcases.each do |d, expected|
19
+ assert_equal expected, Chartd::Encoder.encode(d)
20
+ end
21
+ end
22
+
23
+ def test_encode_custom_min_max
24
+ testcases = {
25
+ 'Ueo' => [[20, 30, 40], 0, 60],
26
+ 'Ae9' => [[20, 30, 40], 20, 40],
27
+ }
28
+
29
+ testcases.each do |expected, data|
30
+ assert_equal expected, Chartd::Encoder.encode(data[0], min: data[1], max: data[2])
31
+ end
32
+ end
33
+
34
+ def test_encode_helper
35
+ assert_equal Chartd::Encoder.encode([1, 2, 3]), Chartd.encode([1, 2, 3])
36
+ end
37
+ end
@@ -0,0 +1,2 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chartd
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Max Lielje
8
+ - David Pfahler
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-07-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '11.2'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '11.2'
28
+ - !ruby/object:Gem::Dependency
29
+ name: test-unit
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '3.2'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '3.2'
42
+ - !ruby/object:Gem::Dependency
43
+ name: simplecov
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '0.12'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '0.12'
56
+ description: Chartd helps you encode values for use with chartd.co.
57
+ email: max@pagespeed.io
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".editorconfig"
63
+ - ".gitignore"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - LICENSE
68
+ - README.md
69
+ - Rakefile
70
+ - chartd.gemspec
71
+ - lib/chartd.rb
72
+ - lib/chartd/chart.rb
73
+ - lib/chartd/encoder.rb
74
+ - test/test_chartd.rb
75
+ - test/test_encode.rb
76
+ - test/test_helper.rb
77
+ homepage: https://github.com/commissure/chartd-rb
78
+ licenses:
79
+ - MIT
80
+ metadata: {}
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.5.1
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: Encode values for chartd.co
101
+ test_files:
102
+ - test/test_chartd.rb
103
+ - test/test_encode.rb
104
+ - test/test_helper.rb