google_image_chart 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'awesome_print', '~> 1.0.2'
7
+ gem 'pry', '~> 0.9.10'
8
+ gem 'rake', '~> 0.9.2.2'
9
+ end
10
+
11
+ group :test do
12
+ gem 'multi_json', '~> 1.3.6'
13
+ gem 'rspec', '~> 2.9.0'
14
+ gem 'vcr', '~> 2.2.5'
15
+ gem 'webmock', '~> 1.8.10'
16
+ end
@@ -0,0 +1,36 @@
1
+ # GoogleImageChart
2
+
3
+ Simple wrapper to Google Image Chart. As the service will be switched
4
+ off in on or before 20 April 2015, this has been mostly put together for
5
+ legacy reasons. It's easier to drop a gem from a service rather than
6
+ delete code (and specs)
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'google_image_chart'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install google_image_chart
21
+
22
+ ## Usage
23
+
24
+ Check the examples directory. To run a specific example:
25
+
26
+ $ ruby examples/google_image_chart.rb
27
+
28
+ NB: you will need to have all gems in the `development` group installed.
29
+
30
+ ## Contributing
31
+
32
+ 1. Fork it
33
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
34
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
35
+ 4. Push to the branch (`git push origin my-new-feature`)
36
+ 5. Create new Pull Request
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'awesome_print'
5
+ require 'pry'
6
+
7
+ def exemplify(description, object)
8
+ puts "\n::: #{description} ".ljust(70, ":::")
9
+ ap(object, indent: -2)
10
+ end
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative 'example'
4
+ require_relative '../lib/google_image_chart'
5
+
6
+ line_chart_png = GoogleImageChart.new(
7
+ type: "lc:nda",
8
+ axes: %w[x y],
9
+ axes_range: %w[1 0 100 10],
10
+ margins: [%w[10 10 10 10]],
11
+ colours: %w[000000 FF0000],
12
+ line_styles: %w[5 2,5],
13
+ labels: [
14
+ %w[8:00 8:05 8:10 8:15 8:20 8:25 8:30 8:35 8:40 8:45 8:50 8:55 9:00]
15
+ ],
16
+ data: [
17
+ %w[30 20 40 10 30 20 40 50 60 70 90 50 90],
18
+ %w[70 70 70 70 70 70 70 70 70 70 70 70]
19
+ ],
20
+ markers: [
21
+ "N,FF0000,0,9,15",
22
+ "N,FF0000,0,10,15",
23
+ "N,FF0000,0,12,15",
24
+ "v,DDDDDD,0,::1,1,-1"
25
+ ]
26
+ )
27
+
28
+ exemplify("Google Image Chart API url", line_chart.url)
29
+
30
+ puts "\nOpening generated PNG...\n"
31
+
32
+ `open "#{line_chart_png.url}"`
@@ -0,0 +1,109 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'base64'
4
+
5
+ require 'hashie/dash'
6
+
7
+ class GoogleImageChart < Hashie::Dash
8
+ property :type, default: "lc"; alias :cht :type
9
+ property :width, default: 600
10
+ property :height, default: 200
11
+ property :margins, default: [%w[0 0 0 0]]
12
+ property :colours
13
+ property :axes, default: %w[x]
14
+ property :axes_range
15
+ property :line_styles
16
+ property :labels
17
+ property :label_styles
18
+ property :legend_labels
19
+ property :legend_position, default: "b"; alias :chdlp :legend_position
20
+ property :data
21
+ property :markers
22
+
23
+ def url
24
+ URI.escape("#{baseurl}#{properties}")
25
+ end
26
+
27
+ def image_data
28
+ Net::HTTP.get(
29
+ URI.parse(url)
30
+ )
31
+ end
32
+
33
+ def base64
34
+ Base64.encode64(image_data)
35
+ end
36
+
37
+ def properties
38
+ %w[
39
+ cht chs chma chco chxt chxr chls chxl chxs chdl chdlp chd chm
40
+ ].inject([]) { |result, property|
41
+ if value = self.send(property)
42
+ result << "#{property}=#{value}"
43
+ end
44
+ result
45
+ }.join("&")
46
+ end
47
+
48
+ def chs
49
+ "#{width}x#{height}"
50
+ end
51
+
52
+ def chxt
53
+ axes && axes.join(',')
54
+ end
55
+
56
+ def chxr
57
+ axes_range && axes_range.join(',')
58
+ end
59
+
60
+ def chd
61
+ result = ''
62
+
63
+ first_data_group = data.slice(0,1).flatten
64
+ result << 't:' << first_data_group.join(',')
65
+
66
+ all_other_data_groups = data.slice(1,data.size)
67
+ all_other_data_groups && all_other_data_groups.map { |values| result << '|' << values.join(',') }
68
+
69
+ result
70
+ end
71
+
72
+ def chls
73
+ line_styles && line_styles.join('|')
74
+ end
75
+
76
+ def chma
77
+ margins && margins.map { |group| group.join(',') }.join('|')
78
+ end
79
+
80
+ def chco
81
+ colours && colours.join(',')
82
+ end
83
+
84
+ def chm
85
+ markers && markers.join('|')
86
+ end
87
+
88
+ def chxl
89
+ labels && labels.each_with_index.inject([]) { |result, (labels, index)|
90
+ result << "#{index}:|#{labels.join('|')}"
91
+ }.join(',')
92
+ end
93
+
94
+ def chdl
95
+ legend_labels && legend_labels.join('|')
96
+ end
97
+
98
+ def chxs
99
+ label_styles && label_styles.join(',')
100
+ end
101
+
102
+
103
+
104
+ private
105
+
106
+ def baseurl
107
+ "http://chart.apis.google.com/chart?"
108
+ end
109
+ end
@@ -0,0 +1 @@
1
+ {"http_interactions":[{"request":{"method":"get","uri":"http://chart.apis.google.com/chart?chco=000000,FF0000&chd=t:30,20,40,10,30,20,40,50,60,70,90,50,90%7C70,70,70,70,70,70,70,70,70,70,70,70&chdlp=b&chls=5%7C2,5&chm=N,FF0000,0,9,15%7CN,FF0000,0,10,15%7CN,FF0000,0,12,15%7Cv,DDDDDD,0,::1,1,-1&chma=10,10,10,10&chs=600x200&cht=lc:nda&chxl=0:%7C8:00%7C8:05%7C8:10%7C8:15%7C8:20%7C8:25%7C8:30%7C8:35%7C8:40%7C8:45%7C8:50%7C8:55%7C9:00&chxr=1,0,100,10&chxt=x,y","body":{"encoding":"US-ASCII","base64_string":""},"headers":{"Accept":["*/*"],"User-Agent":["Ruby"]}},"response":{"status":{"code":200,"message":"OK"},"headers":{"Date":["Fri, 14 Sep 2012 22:31:11 GMT"],"Expires":["Sat, 15 Sep 2012 22:31:11 GMT"],"Cache-Control":["public, max-age=86400"],"Last-Modified":["Mon, 20-Aug-2012 09:57:21 GMT"],"X-Frame-Options":["ALLOWALL"],"Access-Control-Allow-Origin":["*"],"Content-Type":["image/png"],"X-Content-Type-Options":["nosniff"],"Server":["GoogleChartAPI/1.0"],"Content-Length":["14744"],"X-Xss-Protection":["1; mode=block"]},"body":{"encoding":"ASCII-8BIT","base64_string":"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\nWYiPSVIHKzd46tQpoZcb5AgSIQBgOHj37l1ERAQ3twClpKQcHBxG5i1A7nl5\ned28efPy5cu0lvv37//2229ffvmlsHZx+vRphnKDq1evXrt2rbC2zz24NAoA\nGMK6u7uvXLnC5S1AY2Njb29vDw8PhllU+DOML41impubCQRCQ0MDrUVZWfnF\nixdmZmaCb5y53KCurm5hYaGWlpbgG6cHl0YBAMMTlUp98OBBVFTUzZs3Ga6t\nMePvFiAYM2ZMRESEm5sb7Xypu7vbz88vMzOTYSI0Xg0MDHz++ecM5QYjIiKE\nngW5xC4R9vf33759u6qqyt7e3s7ODiEEhXkBAPgqKSkJDw+PjY19+/Yt+zXl\n5eWXLl3q4+Mzf/58BQUF8YQ3zCxYsGDDhg3nz5+nteTk5ISEhPzwww+CbDY4\nODgnJ4e+5Ysvvpg/f74g2xQIm3lIDx48mJOTU15evmPHjvLyciqVGhQUlJiY\n+OLFi++++66rq0uQiVABAIB7HR0d4eHhTk5O3JzSEQiEw4cPY/XjREfAea6F\nS3TBtLe3T5gwgb57FRQUCgsL+d5gYWEhw98lEydObG9vF2LM9LiZdJvlGWFn\nZ6eamhp2Ivjjjz/KyclVVFT09/e7u7sjhIqKikpKSv5VmBcAAISNj1uAnp6e\n5ubm4glvJFBXV4+Li5szZw6t/3t7e9esWfP8+XM+HrXt6elZs2ZNb28vrUVG\nRiY2NvafIlY4Yfm3VXl5uZaWVlJS0pkzZ9ra2tTV1VtaWnR1/6kYrKurW1xc\njBCqra198uTJkydPOE5WBAAAXKJSqffv3/f19dXX1/fz87t//z6bLDhmzBh/\nf/9nz56VlpYGBgZCFhQ6R0fHnTt30rf8/fff+/fv52NT+/btY3isd9euXY6O\njgLFJzCWZ4QNDQ25ubmrV692cHD4+eef/fz8Bi3Mq6GhgVXuUFFREU/EAIBh\nDG4BSqb//ve/9+7dKywspLX88ssvixYtmjNnDvcbefjwYWhoKH2LpaXlgQMH\nhBYlv1gmwvHjx1tZWWElMObOnVtUVGRqakorYdze3q6jo4MQGjVqFC07AgAA\nfxobG+Pi4qKjo58/f85+TdoowFWrVnF8LB4Ii4KCQlRUlJ2dXV9fH9ZCoVDW\nrVuXn5+vqqrKzRbev3+/bt06+kJX8vLykZGRkvBHDMtLo0ZGRq9evcKCbmxs\nJBAIUJgXACBcZDL5zp07a9euNTAw2LFjB/ssqKent3Hjxry8vMzMzE2bNkEW\nFDNra+uAgAD6loqKCu4fH/3+++8rKiroW/bs2WNtbS20+ATAbkB9SkrK33//\n3dXVNXr06G3btiGE0tPT09LSsMK8fn5+YowTADB8UP8/CvDWrVvt7e3sVx4z\nZszatWt9fX1tbW2H/Rh2voknGDKZPGvWrMePH9M3JiYmYg9RssFcbtDe3l7w\n8YjcEMKk2319fd3d3RoaGrQWKMwLAODbmzdvwsLC+L4FOAJzD5fEFkxZWZm1\ntTV9wUKOM8Jg1xQbGxtpLSoqKnl5ecbGxqKNFSEklJll5OXl5eXl6VsUFBRo\nz44CAAA3mpqaYmNj4RbgMGBsbHzw4EF/f39aS319/caNGxMSEli9ZfPmzfRZ\nECF06NAh8WRBLsEUawAAUcFGAcbHxycnJ9MesmDFxMTkiy++8PDwmDRpknjC\nA/z56quv7ty5c/fuXVrLtWvX4uLiPD09mVeOjY29fv06fYubm5sQZ+4WCph0\nGwAgZHzfAuS45ZF5NZIbYg6mtraWQCC0tbXRWjQ0NAoKChjmoHn79q2lpSX9\nMaCpqVlQUKCvry+2UGHSbQCAWGG3AOPi4qqrq9mvCaMAhzR9ff0TJ074+vrS\nWtrb2zds2HDv3j3a4yNUKnX9+vUMfwmdOHFCnFmQS5AIAQCCgluAI5CPj8+t\nW7fi4+NpLSkpKWfPnt26dSv28syZM/fv36d/y+rVq+mL/UoOuDQKAOATiUSK\nj4/n8hagsbHxxo0bBbwFOJKvRrKHSzBsChZik1HTF1oaN25cYWGh+MsWwaVR\nAIDwie4WIBhaxowZ8/vvvy9ZsoTW0t3d/fnnn6elpQ1ablBii/dBIgQAcKum\npga7BPry5Uv2a8rIyDg7O3t7ey9fvhwmIh7GPv30U29v75iYGFpLdnb23Llz\ns7Oz6Vfz9vZesGCB2KPjFrtEeO7cudbWVuxnbBp4KMwLwAgEtwABG2fPns3J\nySktLaW1MGRBExOTM2fOiD0uHrBLhOXl5bt27cJ+1tTURAiFhoba2toaGRkd\nOXJk3759MN02AMNYX1/fjRs3oqKiUlJS6AvIDQpqAY5Yo0aNioiIoC9YSE9G\nRiYiIkLCkwXLRNje3q6hoTF27FgymSwnJ4cQgsK8AIwQeXl5UVFRly5dqq+v\nZ7/mqFGjPvvsM29vbxcXFzHMGwkkk6Oj49atW3/99VfmRdu2bcO93CBHLBNh\nU1NTa2trcHCwtLQ0gUBwdXVlLsxrY2PT0tLS0tKCENLS0mIz1xwAQPLV1tZe\nvHiRm1uA0tLSzs7OPj4+cAsQYEJCQpKTk0tKSugbzc3Ng4OD8QqJeywToZqa\n2po1a2xtbSkUyr59+8aOHTtoYV4AwFAHtwCB4JSVlS9dumRvb08bSCMvLx8X\nF6esrIxvYNxgmQh1dHSw0rsyMjJz586trq42MTFhLswLJ4IADFEDAwMpKSkx\nMTHXr18nEonsV9bV1fX09PTx8ZGQAnJAAtnY2Bw8ePDbb79FCElJSR06dGio\n3D5jmQgzMzPr6+tXrVrV399fUVHh5uamra19+fLl7u5uZWXl/Px8JycnMcYJ\nABCavLy86OjouLg4jrcAlZWVXV1dt2zZ4urqCrcAAUfffPPNrFmzbt++7e7u\nbmdnh3c43GKZCG1sbF6+fHnixImmpiZjY2OsHr2Li0tISAhWmNfKykqMcQIA\nBFVaWnr+/HluJgKVk5NbtmwZNhFobW2t5MyfAiSfnZ2dtrb20DpmWCbCUaNG\nbdmy5f379wghVVVVrNHJyWnmzJlYYV4xBQgAEAzcAgSAPQ4zy9BSIA0U5gVg\nSOBjFKCHh4eFhYV4wgNAcsAUawAMKzxNBKqlpeXl5bVq1SoHBwdpaWnxRAiA\npIFECMAwgd0CvHTpUlVVFfs16W8BQi1AACARAjC0NTc3Y6Pgub8FuHLlSmzS\nRAAAgkQIwBDF0y1AIyMjHx8fuAUIwKAgEQIwlFCp1KysrOjo6Pj4+La2NvYr\nwy1AALgBiRCAoYGPW4Curq6KioriCQ+AoQsSIQASjftbgAghR0dHuAUIAK84\nJ8KnT592dnbOmzcPIQSFeQEQD7gFCIDYcEiETU1NcXFxM2fOxF5CYV5etba2\nZmdn29jY6Onp4R0LGBqKiorCwsJiY2Pr6urYr6msrLxs2TJvb29XV1dZWbi6\nAwCf2P3yUCiU6Ohoe3t77CUU5uUJmUwODAwMCQkhk8mysrJnz57dsGED3kEB\niYYdM8HBwYNW+qaRlpZ2cnLy8fFZsWIF89xPAABesUuEN2/enDZtmpSUVEND\nA0Jo0MK8RCKxq6sLIaSiogIniDQlJSWenp65ubnYSzKZvHHjRhkZmc8//xzX\nuIDkYjhmBgW3AAEQBZZPVBcXFzc0NMyePZvWwlCYt7u7GyHU3t5eVVVVVVXF\ncTKnkSM+Pt7Ozo7hG41KpW7ZsuXBgwd4RQUk2aDHDI2Ojs6OHTueP3+emZm5\nadMmyIIACBfLM8L09PTW1tYTJ060tbX19fXJyckZGRkxF+bV19fX19cXU7AS\nr7u7e/v27efPnx90aW9v7yG7r1AAABlBSURBVGeffZaamjpt2jQxBwYkFptj\nRklJCbsFOH/+fLgFCIDosPztWrt2bX9/P0Lo8ePHTU1N8+bNk5eXh8K8bBQU\nFHh4eLx+/ZrNOu/fv1+0aFFGRoa5ubnYAgMSi9UxIy8vf+DAgS1btqipqeES\nGAAjCstESLsJr6Ki0tXVhb2EwryDolKpp0+f3r17d09PD8MiMzMzDQ2NJ0+e\n0FqampoWLFiQlZUFZ9IjGftj5pdffvn0009xCQyAkYjKo56enrq6OgqFwusb\nh6va2lpskCUzf39/Eon06tWrWbNmMSwyMTFpaGjAO3aAD47HTFlZGd4xfgDB\nsALBsCJRwbS2tnJch+fpB7HCvFJSUry+cVi6ffu2tbU18yMwmpqa165dO3Hi\nhKKioqKiYmJiorW1Nf0KpaWlCxYsgCeMRiBujhlcAgNgxIJ5ePnU19e3ffv2\nTz/9tKmpiWHR7Nmz8/Lyli1bRmtRV1e/ffu2gYEB/Wr5+fnLly9nvjIGhiue\njhkAgNhAIuTHmzdvHBwcTp48SaVS6dvl5OSCg4NTU1MnTJjA8BY9Pb2UlBTs\nUVuatLQ0Dw8PMpks8ogB3vg4ZgAA4gGJkGdRUVG2trbMMyAbGhr+9ddfAQEB\nMjIyg77RxMTk3r17Ghoa9I03btz48ssvRRUrkAx8HzMAADGARMiD9vb21atX\n+/n5vX//nmHRmjVrXrx4QZuOjhUrK6uEhASGm0C///773r17hRwrkAyCHzMA\nAFGDRMgtbO7s+Ph4hnZlZeXIyMhLly6pq6tzs525c+deunSJYXz0zz//fPTo\nUaHFCiSDsI4ZAIBIQSLkjEKhBAYGzp49u7KykmGRpaXls2fPfH19edrg0qVL\nT58+zdD47bffRkRECBAmkCBCP2YAAKIDiZCD+vr6+fPnBwUFMT/S4u/v//jx\n48mTJ/Ox2U2bNv3000/0LVQqddOmTXfu3OE/ViAZRHTMAABEhN0EhsXFxQ8e\nPJCWlnZ0dCQQCGjkFea9c+fO559/zvywu6amZlhYmIAPu//nP/9pa2s7duwY\nraW/v3/lypXJycnMA/DBUCHSYwYAIAoszwjb2tpiY2OdnZ3nzp177ty51tZW\nhFBoaKiCggKBQDhy5AiRSGR4C3PL0EUmk/ft27dkyRLmb7Tp06c/efJEKN9o\nR44cWbFiBX0LiURavnx5cXGx4BuXcD09PZmZmbW1tXgHIjTiOWYAAELHMhE2\nNDTMnz/fwsLC3NzcwMCgubmZVpjX2traxsampKSEfn0KhTJ16tS5c+eGh4d3\ndnaKPnIRqq6udnJyOnDgAEN9VCkpqd27d2dlZRkbGwtlRzIyMhcvXnR2dqZv\nxCYjrampEcouJBCVSg0NDdXW1v7kk08mTpwIxwwAAGfsZ2ArKioKDw8/duxY\nX1/f06dPT58+jbWnp6fHxcVRqdT+/n4SiUQike7du0fbpoyMjIuLS2RkJJFI\nFGyWOBxERUUNWvXb0NAwOzubjw1ynHaPSCQ6Ojoy7G64TkZaU1MzaN0SOGbo\nSdRUjRAMKxAMKxIVjBDmGpWVlR01apSCggKFQhm0MG91dXVGRkZGRkZSUhLt\nXQMDA/fv3/fz8zMyMtq5cyf7otuSg0Qibd682dfXl3nI18KFC7Ozs0U05EtZ\nWTkhIcHU1JS+sbS0dNmyZcPpajNCKDk5edq0aenp6cyL4JgBAOCGVYasr6/v\n6OjAfo6Pj79582Z+fn5ISAjWkpaWlpiYSL9+QEAAm71MmDAhICCgpKREgLwu\nWo8ePWKYCxSDDfkSZMtc/nFUU1PDHICTkxOJRBJk7xKCSCT6+PjwdGTCMSMh\nIBhWIBhWJCoYgc4I//7777t37yKE+vv7W1tb1dTUzM3NOzs7sRPB/Pz88ePH\n06/Pfo6ot2/fhoSEWFhYzJs3LzIykvnPZ3z99ttvzs7OzEO+TE1NHz58KJ4h\nX/r6+jdv3hw9ejR9Y3p6+oYNGygUihgCEJ2ysjInJ6fo6Gie3gXHDABATFhl\nyP7+/kOHDp08efL7778/evRoT08PlUpNS0vbt29faGhoREQEc9Z9+fJlQEAA\nw7zSg1JQUFi8ePHly5d7e3sFzPYCqqurc3FxGTRIrDKc4Lvg6Y+jJ0+eqKio\nMETi5+c3dAtAHj9+XElJibl79fT0oqOj4ZgZlET9QQ3BsALBsCJRwXBzRsjh\n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\n6Y0fPz44OJi5sh0AAAAw5PBwRvjy5UttbW0nJyeEUF5eXmVlpaGhoajiAgAA\nAMSChzPC5uZm2uRqenp6UJgXAADAMMDDGWFvby99YV6sAGFJSUlJSQlCyNzc\nfPTo0aIIkQ+SEwmCYFiDYFiBYFiBYFiBYFhRVFTkuA4PiVBVVRXLeQihtrY2\nhsK8EkWi/hsgGFYgGFYgGFYgGFYgGFaUlJQ4rsPDpVFLS8va2tq+vj6EUEFB\nARTmBQAAMAxI8fTw561bt/Ly8mRlZT/66KOlS5eKLiwAAABAPHhLhAghIpFI\nJBLHjh0rooAAAAAAceJtQH1ZWdnDhw8VFRWdnZ0ZitT39PSkpKQ0Nze7ublh\ni8hkclpaWkVFxfz58w0MDIQYNB/BpKSkPHv2DFvq6Og4e/ZssQWDCQsL27Bh\nA/Yzjj3DHAyOPdPQ0JCUlNTX1zd79uzJkycjXHuGORgce6a2tjY5Obmrq8va\n2vqTTz5BuPYMczC4/zZVVlbm5OR4eHggCfhtog8Gx55JSEigPcnv5uZmbW2N\nY88wByPqnikpKXn06JGampqrq6uqqir9Im5yEw/3CAcGBuLj4y0tLe3s7H7+\n+WfsqVGaEydO9Pf3T58+/eTJky0tLQih8PDwuro6JyeniIiIsrIywT+qIMGU\nlpYuXLhw/fr169evt7W1FWcwpaWlUVFRz58/p7Xg2DPMweDYM6dOnTI0NFy+\nfPnt27dv3LiBcO0Z5mDw6hkqlXru3DkCgbB69epr1669evUK4dczgwaD4zGD\nEOrt7Q0PD3/37h32EsdjhjkYHHumqKho1apV2K7Nzc0Rrj3DHIxIe6anp+fP\nP/+0tbW1srIKCgrq7++nX8pNbuLhjLCsrIxMJtva2kpJSZmamjY1NY0ePfrG\njRu6urqTJk1qamoKCAhACNnZ2RUVFdna2hYUFBw7dkxOTs7Z2fn169fGxsZC\n/OQ8BePo6NjU1GRmZiYrK6ugoCDEMDgGM2PGjO7u7vHjx0tL//M3R09PD149\nwxwMQgivnjEwMNDT08PmZ3B1dX348CGOPcMcDMKvZwwNDadNmzZt2jSE0LRp\n05qamnDsGeZgEH49M2PGDIRQbGzsxx9/XFVVhfD+bWIIBuHaMx0dHcbGxn19\nfdiu8e0ZhmCQiHsmJyfHzs6OQCAghKytrSsrK01NTXnKTTwkQjMzMz09vfPn\nz5NIJDKZjI2asLCwUFVVZRhrX1hYaGhoqKGhIScnh7XQToqFhadgHB0dW1pa\nfv31V6zF3d1dU1NTPMEghCwtLRFC165dw1ZubW3Fq2eYg0EI4dUzY8eO/fLL\nLxFCFArl6dOnkydPxrFnmINB+PWMtrb2kiVL6urq0tLSampq3NzccOwZ5mAQ\nfj2DEHry5ImSkhKBQMByD76/TQzBIPx6hkgkkkik4OBgGRkZAwMDNze39+/f\n49UzzMGoqqqKtGcUFRUfP348f/58KpXa1dVVVlZmamrKU27i4dJoW1tbTU2N\niorK1KlTOzs7sb8Nzc3N9fT0GMbak0gkhpbu7m4hfmxegyGTycuWLduxY0dA\nQACVSr1165bYgmFeGceeYV4Z956pqqo6fPiwpqami4sL7j1DHwzuPSMtLa2i\noiIvL48k4JihDwbHnmlpaUlPT1+xYgVtZRx7hjkYfI+Z1atX7969+7vvvquv\nr09NTcX3mGEIRtQ9Y21traGh8ccff4SGhnZ1dWFPgPKUm3hIhNnZ2ba2tp6e\nns7OzgQCISsri7ZIVVW1oaEB+7mtrW3s2LGqqqq06+a00fdCxFMwsrKyc+fO\nxU7JXV1dq6urxRYMMxx7hhm+PfPo0aOoqCgvL6/ly5dLSUnh2zMMweDYM62t\nrc3NzePGjVu6dKmdnd3ly5dx7BnmYHDsmUePHnV3d//222/x8fHV1dVhYWE4\n9gxzMDj2zKhRo2bNmiUrK4vt+u3btzj2DHMwou4ZRUXFzZs3L1269OuvvzY1\nNaW/CMxlbuIhEWppaWEzy1Cp1L6+Puxhm87OThKJZGRkRCaTOzs70f/H2o8Z\nM0ZbW7u2thYhlJ+fL/TR9zwF09zcHBwcTKFQEELFxcXYxX3xBMO8Mo49w7wy\njj3T19f34MGDXbt2TZgwAVsZx55hDgbHnmlsbLx48SK2qLGxUU1NDceeYQ4G\nx55xcXHx9/f38fFZsGCBrq7uihUrcOwZ5mBw7JnS0lLswiOVSn3z5s2MGTNw\n7BnmYETdM+Xl5efPn9fU1JSTk8vNzZ00aRLiMTfJBAYGcrkzbW3t6urqjIyM\nO3fuUCiUZcuWIYQuXLjQ2dlpamqqrKwcERFRWFgoIyOzdOlSKSkpLS2tCxcu\nvH79urm52cvLi/4BDcHxFMyoUaMaGxsTExMzMzPLy8s9PDywizxiCMbExARb\nJykpadGiRdjPePUMczDKysp49Uxvb+/Dhw/T0tLu3r179+7dioqK6dOn49Uz\nzMHMmTMHr56xt7cvLCxMTU1NS0urq6vz8vJSUlLCq2eYg9HS0sKrZywsLJSU\nlJSUlLq7u8vKyrCHm/DqGeZgcPxtmj59enFxcUpKSmpqakdHx4oVK6SlpfHq\nGeZgVFRURNozqqqqDx8+zM7OzszMnDdvHlYWiafcxPOAeuwaq4aGBvOi/v7+\npqYmXV1dKSkprIVCodTX148bN05GRkbwTytgMGQyua2tTVtbWxSRsA+GGY49\nwwx6hhUce6arq4tEItHvGseeYQ4GjhlWcOyZ3t5eIpFI/xwKjj3DHIxIe4ZK\npdbX16uqqjIMIsRwzE08J0IAAABgOBHmyTIAAAAw5EAiBAAAMKJBIgQAADCi\nQSIEAAAwov0PLg9T4bubCpoAAAAASUVORK5CYII=\n"},"http_version":null},"recorded_at":"Fri, 14 Sep 2012 22:31:11 GMT"}],"recorded_with":"VCR 2.2.5"}
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+ require 'google_image_chart'
3
+
4
+ describe GoogleImageChart do
5
+ describe "by default" do
6
+ subject { GoogleImageChart.new }
7
+
8
+ its(:type) { should eql "lc" }
9
+ its(:cht) { should eql "lc" }
10
+
11
+ its(:width) { should eql 600 }
12
+ its(:height) { should eql 200 }
13
+ its(:chs) { should eql "600x200" }
14
+
15
+ its(:margins) { should eql [%w[0 0 0 0]] }
16
+ its(:chma) { should eql "0,0,0,0" }
17
+
18
+ its(:axes) { should eql %w[x] }
19
+
20
+ its(:legend_position) { should eql "b" }
21
+ its(:chdlp) { should eql "b" }
22
+ end
23
+
24
+ describe "line chart" do
25
+ subject do
26
+ GoogleImageChart.new(
27
+ type: "lc:nda",
28
+ axes: %w[x y],
29
+ axes_range: %w[1 0 100 10],
30
+ margins: [%w[10 10 10 10]],
31
+ colours: %w[000000 FF0000],
32
+ line_styles: %w[5 2,5],
33
+ labels: [
34
+ %w[8:00 8:05 8:10 8:15 8:20 8:25 8:30 8:35 8:40 8:45 8:50 8:55 9:00]
35
+ ],
36
+ data: [
37
+ %w[30 20 40 10 30 20 40 50 60 70 90 50 90],
38
+ %w[70 70 70 70 70 70 70 70 70 70 70 70]
39
+ ],
40
+ markers: [
41
+ "N,FF0000,0,9,15",
42
+ "N,FF0000,0,10,15",
43
+ "N,FF0000,0,12,15",
44
+ "v,DDDDDD,0,::1,1,-1"
45
+ ]
46
+ )
47
+ end
48
+
49
+ its(:chd) { should eql "t:30,20,40,10,30,20,40,50,60,70,90,50,90|70,70,70,70,70,70,70,70,70,70,70,70" }
50
+ its(:chxl) { should eql "0:|8:00|8:05|8:10|8:15|8:20|8:25|8:30|8:35|8:40|8:45|8:50|8:55|9:00" }
51
+ its(:chxr) { should eql "1,0,100,10" }
52
+
53
+ describe "#image_data" do
54
+ it "returns the image content" do
55
+ VCR.use_cassette('google_charts') do
56
+ subject.image_data.should include("PNG")
57
+ end
58
+ end
59
+ end
60
+
61
+ describe "#url" do
62
+ it "valid url with all parameters" do
63
+ subject.url.should eql("http://chart.apis.google.com/chart?cht=lc:nda&chs=600x200&chma=10,10,10,10&chco=000000,FF0000&chxt=x,y&chxr=1,0,100,10&chls=5%7C2,5&chxl=0:%7C8:00%7C8:05%7C8:10%7C8:15%7C8:20%7C8:25%7C8:30%7C8:35%7C8:40%7C8:45%7C8:50%7C8:55%7C9:00&chdlp=b&chd=t:30,20,40,10,30,20,40,50,60,70,90,50,90%7C70,70,70,70,70,70,70,70,70,70,70,70&chm=N,FF0000,0,9,15%7CN,FF0000,0,10,15%7CN,FF0000,0,12,15%7Cv,DDDDDD,0,::1,1,-1")
64
+ end
65
+ end
66
+ end
67
+
68
+ describe "pie chart" do
69
+ subject do
70
+ GoogleImageChart.new(
71
+ type: "p",
72
+ width: 240,
73
+ height: 157,
74
+ margins: [
75
+ %w[0 0 0 0],
76
+ %w[0 30]
77
+ ],
78
+ colours: %w[308DF3 00FF00 FF0000],
79
+ legend_labels: %w[Group\ A Group\ B Group\ C],
80
+ label_styles: %w[0 67676700 11.167],
81
+ data: [%w[20 10 5]]
82
+ )
83
+ end
84
+
85
+ its(:chma) { should eql "0,0,0,0|0,30" }
86
+ its(:chxs) { should eql "0,67676700,11.167" }
87
+ its(:chdl) { should eql "Group A|Group B|Group C" }
88
+
89
+ describe "#url" do
90
+ it "valid url with all parameters" do
91
+ subject.url.should eql("http://chart.apis.google.com/chart?cht=p&chs=240x157&chma=0,0,0,0%7C0,30&chco=308DF3,00FF00,FF0000&chxt=x&chxs=0,67676700,11.167&chdl=Group%20A%7CGroup%20B%7CGroup%20C&chdlp=b&chd=t:20,10,5")
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,31 @@
1
+ require 'bundler/setup'
2
+
3
+ require 'pry'
4
+
5
+ APP_ROOT = File.expand_path('../../', __FILE__)
6
+ lib = "#{APP_ROOT}/lib"
7
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
8
+
9
+ require 'vcr'
10
+
11
+ VCR.configure do |c|
12
+ c.cassette_library_dir = "#{APP_ROOT}/spec/fixtures/cassette_library"
13
+ c.hook_into :webmock
14
+ c.ignore_localhost = true
15
+ c.default_cassette_options = {
16
+ :record => :new_episodes,
17
+ :serialize_with => :json,
18
+ :preserve_exact_body_bytes => true
19
+ }
20
+ end
21
+
22
+ require 'rspec'
23
+
24
+ RSpec.configure do |config|
25
+ config.mock_with :rspec
26
+
27
+ config.treat_symbols_as_metadata_keys_with_true_values = true
28
+ config.filter_run :focus => true
29
+ config.run_all_when_everything_filtered = true
30
+ config.extend VCR::RSpec::Macros
31
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: google_image_chart
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gerhard Lazu
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: hashie
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.2.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.2.0
30
+ description: Creates PNGs from chart data
31
+ email:
32
+ - gerhard@lazu.co.uk
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - lib/google_image_chart.rb
38
+ - examples/example.rb
39
+ - examples/google_image_chart.rb
40
+ - Gemfile
41
+ - README.md
42
+ - spec/fixtures/cassette_library/google_charts.json
43
+ - spec/google_image_chart_spec.rb
44
+ - spec/spec_helper.rb
45
+ homepage: https://github.com/gosquared/google_image_chart
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ segments:
58
+ - 0
59
+ hash: -1656476349801950249
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ segments:
67
+ - 0
68
+ hash: -1656476349801950249
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 1.8.23
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Simple wrapper to the Google Image Chart API - yes, the deprecated one
75
+ test_files:
76
+ - spec/fixtures/cassette_library/google_charts.json
77
+ - spec/google_image_chart_spec.rb
78
+ - spec/spec_helper.rb