chartd 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.
@@ -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