diff --git a/Gemfile b/Gemfile index 7a90ebb1..8052f6bb 100644 --- a/Gemfile +++ b/Gemfile @@ -31,7 +31,6 @@ gem "will_paginate" gem "acts_as_list" gem "aasm", '~> 3.4.0' gem "htmlentities" -gem "swf_fu" gem "rails_autolink" gem 'puma', '~> 3.12' gem 'paperclip' @@ -39,6 +38,8 @@ gem 'paperclip' # To use ActiveModel has_secure_password gem 'bcrypt', '~> 3.1.7' +gem 'chartjs-ror' + # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks # gem 'turbolinks' diff --git a/Gemfile.lock b/Gemfile.lock index ffa2b45d..321710dd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -66,6 +66,8 @@ GEM activesupport (>= 3.0.0) uniform_notifier (~> 1.11) byebug (11.0.1) + chartjs-ror (3.6.4) + rails (>= 3.1) childprocess (1.0.1) rake (< 13.0) climate_control (0.2.0) @@ -238,9 +240,6 @@ GEM activesupport (>= 4.0) sprockets (>= 3.0.0) sqlite3 (1.4.1) - swf_fu (2.0.4) - coffee-script - rails (>= 3.1) terrapin (0.6.0) climate_control (>= 0.0.3, < 1.0) therubyracer (0.12.3) @@ -278,6 +277,7 @@ DEPENDENCIES bootstrap-sass (= 3.4.1) bullet byebug + chartjs-ror codeclimate-test-reporter (= 1.0.7) coffee-rails (~> 4.2.0) database_cleaner @@ -305,7 +305,6 @@ DEPENDENCIES simplecov spring sqlite3 - swf_fu therubyracer tolk (~> 3.1.0) uglifier (>= 1.3.0) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 38c7800b..375f0bdd 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -36,3 +36,6 @@ //= require jquery.truncator //= require superfish //= require supersubs + +//= require Chart.min +//= require chartjs-plugin-colorschemes.min diff --git a/app/assets/javascripts/chartjs-plugin-colorschemes.min.js b/app/assets/javascripts/chartjs-plugin-colorschemes.min.js new file mode 100644 index 00000000..82ee0703 --- /dev/null +++ b/app/assets/javascripts/chartjs-plugin-colorschemes.min.js @@ -0,0 +1,11 @@ +/* + * @license + * chartjs-plugin-colorschemes + * https://github.com/nagix/chartjs-plugin-colorschemes/ + * Version: 0.3.0 + * + * Copyright 2019 Akihiko Kusanagi + * Released under the MIT license + * https://github.com/nagix/chartjs-plugin-colorschemes/blob/master/LICENSE.md + */ +!function(f,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("chart.js")):"function"==typeof define&&define.amd?define(["chart.js"],e):f["chartjs-plugin-colorschemes"]=e(f.Chart)}(this,function(f){"use strict";f=f&&f.hasOwnProperty("default")?f.default:f;var o={brewer:{YlGn3:["#f7fcb9","#addd8e","#31a354"],YlGn4:["#ffffcc","#c2e699","#78c679","#238443"],YlGn5:["#ffffcc","#c2e699","#78c679","#31a354","#006837"],YlGn6:["#ffffcc","#d9f0a3","#addd8e","#78c679","#31a354","#006837"],YlGn7:["#ffffcc","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#005a32"],YlGn8:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#005a32"],YlGn9:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"],YlGnBu3:["#edf8b1","#7fcdbb","#2c7fb8"],YlGnBu4:["#ffffcc","#a1dab4","#41b6c4","#225ea8"],YlGnBu5:["#ffffcc","#a1dab4","#41b6c4","#2c7fb8","#253494"],YlGnBu6:["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#2c7fb8","#253494"],YlGnBu7:["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"],YlGnBu8:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"],YlGnBu9:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"],GnBu3:["#e0f3db","#a8ddb5","#43a2ca"],GnBu4:["#f0f9e8","#bae4bc","#7bccc4","#2b8cbe"],GnBu5:["#f0f9e8","#bae4bc","#7bccc4","#43a2ca","#0868ac"],GnBu6:["#f0f9e8","#ccebc5","#a8ddb5","#7bccc4","#43a2ca","#0868ac"],GnBu7:["#f0f9e8","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#08589e"],GnBu8:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#08589e"],GnBu9:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"],BuGn3:["#e5f5f9","#99d8c9","#2ca25f"],BuGn4:["#edf8fb","#b2e2e2","#66c2a4","#238b45"],BuGn5:["#edf8fb","#b2e2e2","#66c2a4","#2ca25f","#006d2c"],BuGn6:["#edf8fb","#ccece6","#99d8c9","#66c2a4","#2ca25f","#006d2c"],BuGn7:["#edf8fb","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#005824"],BuGn8:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#005824"],BuGn9:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"],PuBuGn3:["#ece2f0","#a6bddb","#1c9099"],PuBuGn4:["#f6eff7","#bdc9e1","#67a9cf","#02818a"],PuBuGn5:["#f6eff7","#bdc9e1","#67a9cf","#1c9099","#016c59"],PuBuGn6:["#f6eff7","#d0d1e6","#a6bddb","#67a9cf","#1c9099","#016c59"],PuBuGn7:["#f6eff7","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016450"],PuBuGn8:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016450"],PuBuGn9:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"],PuBu3:["#ece7f2","#a6bddb","#2b8cbe"],PuBu4:["#f1eef6","#bdc9e1","#74a9cf","#0570b0"],PuBu5:["#f1eef6","#bdc9e1","#74a9cf","#2b8cbe","#045a8d"],PuBu6:["#f1eef6","#d0d1e6","#a6bddb","#74a9cf","#2b8cbe","#045a8d"],PuBu7:["#f1eef6","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#034e7b"],PuBu8:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#034e7b"],PuBu9:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"],BuPu3:["#e0ecf4","#9ebcda","#8856a7"],BuPu4:["#edf8fb","#b3cde3","#8c96c6","#88419d"],BuPu5:["#edf8fb","#b3cde3","#8c96c6","#8856a7","#810f7c"],BuPu6:["#edf8fb","#bfd3e6","#9ebcda","#8c96c6","#8856a7","#810f7c"],BuPu7:["#edf8fb","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#6e016b"],BuPu8:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#6e016b"],BuPu9:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"],RdPu3:["#fde0dd","#fa9fb5","#c51b8a"],RdPu4:["#feebe2","#fbb4b9","#f768a1","#ae017e"],RdPu5:["#feebe2","#fbb4b9","#f768a1","#c51b8a","#7a0177"],RdPu6:["#feebe2","#fcc5c0","#fa9fb5","#f768a1","#c51b8a","#7a0177"],RdPu7:["#feebe2","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177"],RdPu8:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177"],RdPu9:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"],PuRd3:["#e7e1ef","#c994c7","#dd1c77"],PuRd4:["#f1eef6","#d7b5d8","#df65b0","#ce1256"],PuRd5:["#f1eef6","#d7b5d8","#df65b0","#dd1c77","#980043"],PuRd6:["#f1eef6","#d4b9da","#c994c7","#df65b0","#dd1c77","#980043"],PuRd7:["#f1eef6","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#91003f"],PuRd8:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#91003f"],PuRd9:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"],OrRd3:["#fee8c8","#fdbb84","#e34a33"],OrRd4:["#fef0d9","#fdcc8a","#fc8d59","#d7301f"],OrRd5:["#fef0d9","#fdcc8a","#fc8d59","#e34a33","#b30000"],OrRd6:["#fef0d9","#fdd49e","#fdbb84","#fc8d59","#e34a33","#b30000"],OrRd7:["#fef0d9","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#990000"],OrRd8:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#990000"],OrRd9:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"],YlOrRd3:["#ffeda0","#feb24c","#f03b20"],YlOrRd4:["#ffffb2","#fecc5c","#fd8d3c","#e31a1c"],YlOrRd5:["#ffffb2","#fecc5c","#fd8d3c","#f03b20","#bd0026"],YlOrRd6:["#ffffb2","#fed976","#feb24c","#fd8d3c","#f03b20","#bd0026"],YlOrRd7:["#ffffb2","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#b10026"],YlOrRd8:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#b10026"],YlOrRd9:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"],YlOrBr3:["#fff7bc","#fec44f","#d95f0e"],YlOrBr4:["#ffffd4","#fed98e","#fe9929","#cc4c02"],YlOrBr5:["#ffffd4","#fed98e","#fe9929","#d95f0e","#993404"],YlOrBr6:["#ffffd4","#fee391","#fec44f","#fe9929","#d95f0e","#993404"],YlOrBr7:["#ffffd4","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#8c2d04"],YlOrBr8:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#8c2d04"],YlOrBr9:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"],Purples3:["#efedf5","#bcbddc","#756bb1"],Purples4:["#f2f0f7","#cbc9e2","#9e9ac8","#6a51a3"],Purples5:["#f2f0f7","#cbc9e2","#9e9ac8","#756bb1","#54278f"],Purples6:["#f2f0f7","#dadaeb","#bcbddc","#9e9ac8","#756bb1","#54278f"],Purples7:["#f2f0f7","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#4a1486"],Purples8:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#4a1486"],Purples9:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"],Blues3:["#deebf7","#9ecae1","#3182bd"],Blues4:["#eff3ff","#bdd7e7","#6baed6","#2171b5"],Blues5:["#eff3ff","#bdd7e7","#6baed6","#3182bd","#08519c"],Blues6:["#eff3ff","#c6dbef","#9ecae1","#6baed6","#3182bd","#08519c"],Blues7:["#eff3ff","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#084594"],Blues8:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#084594"],Blues9:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"],Greens3:["#e5f5e0","#a1d99b","#31a354"],Greens4:["#edf8e9","#bae4b3","#74c476","#238b45"],Greens5:["#edf8e9","#bae4b3","#74c476","#31a354","#006d2c"],Greens6:["#edf8e9","#c7e9c0","#a1d99b","#74c476","#31a354","#006d2c"],Greens7:["#edf8e9","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#005a32"],Greens8:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#005a32"],Greens9:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"],Oranges3:["#fee6ce","#fdae6b","#e6550d"],Oranges4:["#feedde","#fdbe85","#fd8d3c","#d94701"],Oranges5:["#feedde","#fdbe85","#fd8d3c","#e6550d","#a63603"],Oranges6:["#feedde","#fdd0a2","#fdae6b","#fd8d3c","#e6550d","#a63603"],Oranges7:["#feedde","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#8c2d04"],Oranges8:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#8c2d04"],Oranges9:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"],Reds3:["#fee0d2","#fc9272","#de2d26"],Reds4:["#fee5d9","#fcae91","#fb6a4a","#cb181d"],Reds5:["#fee5d9","#fcae91","#fb6a4a","#de2d26","#a50f15"],Reds6:["#fee5d9","#fcbba1","#fc9272","#fb6a4a","#de2d26","#a50f15"],Reds7:["#fee5d9","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#99000d"],Reds8:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#99000d"],Reds9:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"],Greys3:["#f0f0f0","#bdbdbd","#636363"],Greys4:["#f7f7f7","#cccccc","#969696","#525252"],Greys5:["#f7f7f7","#cccccc","#969696","#636363","#252525"],Greys6:["#f7f7f7","#d9d9d9","#bdbdbd","#969696","#636363","#252525"],Greys7:["#f7f7f7","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525"],Greys8:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525"],Greys9:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"],PuOr3:["#f1a340","#f7f7f7","#998ec3"],PuOr4:["#e66101","#fdb863","#b2abd2","#5e3c99"],PuOr5:["#e66101","#fdb863","#f7f7f7","#b2abd2","#5e3c99"],PuOr6:["#b35806","#f1a340","#fee0b6","#d8daeb","#998ec3","#542788"],PuOr7:["#b35806","#f1a340","#fee0b6","#f7f7f7","#d8daeb","#998ec3","#542788"],PuOr8:["#b35806","#e08214","#fdb863","#fee0b6","#d8daeb","#b2abd2","#8073ac","#542788"],PuOr9:["#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788"],PuOr10:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"],PuOr11:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"],BrBG3:["#d8b365","#f5f5f5","#5ab4ac"],BrBG4:["#a6611a","#dfc27d","#80cdc1","#018571"],BrBG5:["#a6611a","#dfc27d","#f5f5f5","#80cdc1","#018571"],BrBG6:["#8c510a","#d8b365","#f6e8c3","#c7eae5","#5ab4ac","#01665e"],BrBG7:["#8c510a","#d8b365","#f6e8c3","#f5f5f5","#c7eae5","#5ab4ac","#01665e"],BrBG8:["#8c510a","#bf812d","#dfc27d","#f6e8c3","#c7eae5","#80cdc1","#35978f","#01665e"],BrBG9:["#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e"],BrBG10:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"],BrBG11:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"],PRGn3:["#af8dc3","#f7f7f7","#7fbf7b"],PRGn4:["#7b3294","#c2a5cf","#a6dba0","#008837"],PRGn5:["#7b3294","#c2a5cf","#f7f7f7","#a6dba0","#008837"],PRGn6:["#762a83","#af8dc3","#e7d4e8","#d9f0d3","#7fbf7b","#1b7837"],PRGn7:["#762a83","#af8dc3","#e7d4e8","#f7f7f7","#d9f0d3","#7fbf7b","#1b7837"],PRGn8:["#762a83","#9970ab","#c2a5cf","#e7d4e8","#d9f0d3","#a6dba0","#5aae61","#1b7837"],PRGn9:["#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837"],PRGn10:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"],PRGn11:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"],PiYG3:["#e9a3c9","#f7f7f7","#a1d76a"],PiYG4:["#d01c8b","#f1b6da","#b8e186","#4dac26"],PiYG5:["#d01c8b","#f1b6da","#f7f7f7","#b8e186","#4dac26"],PiYG6:["#c51b7d","#e9a3c9","#fde0ef","#e6f5d0","#a1d76a","#4d9221"],PiYG7:["#c51b7d","#e9a3c9","#fde0ef","#f7f7f7","#e6f5d0","#a1d76a","#4d9221"],PiYG8:["#c51b7d","#de77ae","#f1b6da","#fde0ef","#e6f5d0","#b8e186","#7fbc41","#4d9221"],PiYG9:["#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221"],PiYG10:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"],PiYG11:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"],RdBu3:["#ef8a62","#f7f7f7","#67a9cf"],RdBu4:["#ca0020","#f4a582","#92c5de","#0571b0"],RdBu5:["#ca0020","#f4a582","#f7f7f7","#92c5de","#0571b0"],RdBu6:["#b2182b","#ef8a62","#fddbc7","#d1e5f0","#67a9cf","#2166ac"],RdBu7:["#b2182b","#ef8a62","#fddbc7","#f7f7f7","#d1e5f0","#67a9cf","#2166ac"],RdBu8:["#b2182b","#d6604d","#f4a582","#fddbc7","#d1e5f0","#92c5de","#4393c3","#2166ac"],RdBu9:["#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac"],RdBu10:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"],RdBu11:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"],RdGy3:["#ef8a62","#ffffff","#999999"],RdGy4:["#ca0020","#f4a582","#bababa","#404040"],RdGy5:["#ca0020","#f4a582","#ffffff","#bababa","#404040"],RdGy6:["#b2182b","#ef8a62","#fddbc7","#e0e0e0","#999999","#4d4d4d"],RdGy7:["#b2182b","#ef8a62","#fddbc7","#ffffff","#e0e0e0","#999999","#4d4d4d"],RdGy8:["#b2182b","#d6604d","#f4a582","#fddbc7","#e0e0e0","#bababa","#878787","#4d4d4d"],RdGy9:["#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d"],RdGy10:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"],RdGy11:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"],RdYlBu3:["#fc8d59","#ffffbf","#91bfdb"],RdYlBu4:["#d7191c","#fdae61","#abd9e9","#2c7bb6"],RdYlBu5:["#d7191c","#fdae61","#ffffbf","#abd9e9","#2c7bb6"],RdYlBu6:["#d73027","#fc8d59","#fee090","#e0f3f8","#91bfdb","#4575b4"],RdYlBu7:["#d73027","#fc8d59","#fee090","#ffffbf","#e0f3f8","#91bfdb","#4575b4"],RdYlBu8:["#d73027","#f46d43","#fdae61","#fee090","#e0f3f8","#abd9e9","#74add1","#4575b4"],RdYlBu9:["#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4"],RdYlBu10:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"],RdYlBu11:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"],Spectral3:["#fc8d59","#ffffbf","#99d594"],Spectral4:["#d7191c","#fdae61","#abdda4","#2b83ba"],Spectral5:["#d7191c","#fdae61","#ffffbf","#abdda4","#2b83ba"],Spectral6:["#d53e4f","#fc8d59","#fee08b","#e6f598","#99d594","#3288bd"],Spectral7:["#d53e4f","#fc8d59","#fee08b","#ffffbf","#e6f598","#99d594","#3288bd"],Spectral8:["#d53e4f","#f46d43","#fdae61","#fee08b","#e6f598","#abdda4","#66c2a5","#3288bd"],Spectral9:["#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd"],Spectral10:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"],Spectral11:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"],RdYlGn3:["#fc8d59","#ffffbf","#91cf60"],RdYlGn4:["#d7191c","#fdae61","#a6d96a","#1a9641"],RdYlGn5:["#d7191c","#fdae61","#ffffbf","#a6d96a","#1a9641"],RdYlGn6:["#d73027","#fc8d59","#fee08b","#d9ef8b","#91cf60","#1a9850"],RdYlGn7:["#d73027","#fc8d59","#fee08b","#ffffbf","#d9ef8b","#91cf60","#1a9850"],RdYlGn8:["#d73027","#f46d43","#fdae61","#fee08b","#d9ef8b","#a6d96a","#66bd63","#1a9850"],RdYlGn9:["#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850"],RdYlGn10:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"],RdYlGn11:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"],Accent3:["#7fc97f","#beaed4","#fdc086"],Accent4:["#7fc97f","#beaed4","#fdc086","#ffff99"],Accent5:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0"],Accent6:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f"],Accent7:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17"],Accent8:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17","#666666"],"Dark2-3":["#1b9e77","#d95f02","#7570b3"],"Dark2-4":["#1b9e77","#d95f02","#7570b3","#e7298a"],"Dark2-5":["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e"],"Dark2-6":["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02"],"Dark2-7":["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d"],"Dark2-8":["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"],Paired3:["#a6cee3","#1f78b4","#b2df8a"],Paired4:["#a6cee3","#1f78b4","#b2df8a","#33a02c"],Paired5:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99"],Paired6:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c"],Paired7:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f"],Paired8:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00"],Paired9:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6"],Paired10:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a"],Paired11:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99"],Paired12:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99","#b15928"],"Pastel1-3":["#fbb4ae","#b3cde3","#ccebc5"],"Pastel1-4":["#fbb4ae","#b3cde3","#ccebc5","#decbe4"],"Pastel1-5":["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6"],"Pastel1-6":["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc"],"Pastel1-7":["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd"],"Pastel1-8":["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec"],"Pastel1-9":["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"],"Pastel2-3":["#b3e2cd","#fdcdac","#cbd5e8"],"Pastel2-4":["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4"],"Pastel2-5":["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9"],"Pastel2-6":["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae"],"Pastel2-7":["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc"],"Pastel2-8":["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc","#cccccc"],"Set1-3":["#e41a1c","#377eb8","#4daf4a"],"Set1-4":["#e41a1c","#377eb8","#4daf4a","#984ea3"],"Set1-5":["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00"],"Set1-6":["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33"],"Set1-7":["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628"],"Set1-8":["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf"],"Set1-9":["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"],"Set2-3":["#66c2a5","#fc8d62","#8da0cb"],"Set2-4":["#66c2a5","#fc8d62","#8da0cb","#e78ac3"],"Set2-5":["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854"],"Set2-6":["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f"],"Set2-7":["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494"],"Set2-8":["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494","#b3b3b3"],"Set3-3":["#8dd3c7","#ffffb3","#bebada"],"Set3-4":["#8dd3c7","#ffffb3","#bebada","#fb8072"],"Set3-5":["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3"],"Set3-6":["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462"],"Set3-7":["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69"],"Set3-8":["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5"],"Set3-9":["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9"],"Set3-10":["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd"],"Set3-11":["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5"],"Set3-12":["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"]},office:{Adjacency6:["#a9a57c","#9cbebd","#d2cb6c","#95a39d","#c89f5d","#b1a089"],Advantage6:["#663366","#330f42","#666699","#999966","#f7901e","#a3a101"],Angles6:["#797b7e","#f96a1b","#08a1d9","#7c984a","#c2ad8d","#506e94"],Apex6:["#ceb966","#9cb084","#6bb1c9","#6585cf","#7e6bc9","#a379bb"],Apothecary6:["#93a299","#cf543f","#b5ae53","#848058","#e8b54d","#786c71"],Aspect6:["#f07f09","#9f2936","#1b587c","#4e8542","#604878","#c19859"],Atlas6:["#f81b02","#fc7715","#afbf41","#50c49f","#3b95c4","#b560d4"],Austin6:["#94c600","#71685a","#ff6700","#909465","#956b43","#fea022"],Badge6:["#f8b323","#656a59","#46b2b5","#8caa7e","#d36f68","#826276"],Banded6:["#ffc000","#a5d028","#08cc78","#f24099","#828288","#f56617"],Basis6:["#f09415","#c1b56b","#4baf73","#5aa6c0","#d17df9","#fa7e5c"],Berlin6:["#a6b727","#df5327","#fe9e00","#418ab3","#d7d447","#818183"],BlackTie6:["#6f6f74","#a7b789","#beae98","#92a9b9","#9c8265","#8d6974"],Blue6:["#0f6fc6","#009dd9","#0bd0d9","#10cf9b","#7cca62","#a5c249"],BlueGreen6:["#3494ba","#58b6c0","#75bda7","#7a8c8e","#84acb6","#2683c6"],BlueII6:["#1cade4","#2683c6","#27ced7","#42ba97","#3e8853","#62a39f"],BlueRed6:["#4a66ac","#629dd1","#297fd5","#7f8fa9","#5aa2ae","#9d90a0"],BlueWarm6:["#4a66ac","#629dd1","#297fd5","#7f8fa9","#5aa2ae","#9d90a0"],Breeze6:["#2c7c9f","#244a58","#e2751d","#ffb400","#7eb606","#c00000"],Capital6:["#4b5a60","#9c5238","#504539","#c1ad79","#667559","#bad6ad"],Celestial6:["#ac3ec1","#477bd1","#46b298","#90ba4c","#dd9d31","#e25247"],Circuit6:["#9acd4c","#faa93a","#d35940","#b258d3","#63a0cc","#8ac4a7"],Civic6:["#d16349","#ccb400","#8cadae","#8c7b70","#8fb08c","#d19049"],Clarity6:["#93a299","#ad8f67","#726056","#4c5a6a","#808da0","#79463d"],Codex6:["#990000","#efab16","#78ac35","#35aca2","#4083cf","#0d335e"],Composite6:["#98c723","#59b0b9","#deae00","#b77bb4","#e0773c","#a98d63"],Concourse6:["#2da2bf","#da1f28","#eb641b","#39639d","#474b78","#7d3c4a"],Couture6:["#9e8e5c","#a09781","#85776d","#aeafa9","#8d878b","#6b6149"],Crop6:["#8c8d86","#e6c069","#897b61","#8dab8e","#77a2bb","#e28394"],Damask6:["#9ec544","#50bea3","#4a9ccc","#9a66ca","#c54f71","#de9c3c"],Depth6:["#41aebd","#97e9d5","#a2cf49","#608f3d","#f4de3a","#fcb11c"],Dividend6:["#4d1434","#903163","#b2324b","#969fa7","#66b1ce","#40619d"],Droplet6:["#2fa3ee","#4bcaad","#86c157","#d99c3f","#ce6633","#a35dd1"],Elemental6:["#629dd1","#297fd5","#7f8fa9","#4a66ac","#5aa2ae","#9d90a0"],Equity6:["#d34817","#9b2d1f","#a28e6a","#956251","#918485","#855d5d"],Essential6:["#7a7a7a","#f5c201","#526db0","#989aac","#dc5924","#b4b392"],Excel16:["#9999ff","#993366","#ffffcc","#ccffff","#660066","#ff8080","#0066cc","#ccccff","#000080","#ff00ff","#ffff00","#0000ff","#800080","#800000","#008080","#0000ff"],Executive6:["#6076b4","#9c5252","#e68422","#846648","#63891f","#758085"],Exhibit6:["#3399ff","#69ffff","#ccff33","#3333ff","#9933ff","#ff33ff"],Expo6:["#fbc01e","#efe1a2","#fa8716","#be0204","#640f10","#7e13e3"],Facet6:["#90c226","#54a021","#e6b91e","#e76618","#c42f1a","#918655"],Feathered6:["#606372","#79a8a4","#b2ad8f","#ad8082","#dec18c","#92a185"],Flow6:["#0f6fc6","#009dd9","#0bd0d9","#10cf9b","#7cca62","#a5c249"],Focus6:["#ffb91d","#f97817","#6de304","#ff0000","#732bea","#c913ad"],Folio6:["#294171","#748cbc","#8e887c","#834736","#5a1705","#a0a16a"],Formal6:["#907f76","#a46645","#cd9c47","#9a92cd","#7d639b","#733678"],Forte6:["#c70f0c","#dd6b0d","#faa700","#93e50d","#17c7ba","#0a96e4"],Foundry6:["#72a376","#b0ccb0","#a8cdd7","#c0beaf","#cec597","#e8b7b7"],Frame6:["#40bad2","#fab900","#90bb23","#ee7008","#1ab39f","#d5393d"],Gallery6:["#b71e42","#de478e","#bc72f0","#795faf","#586ea6","#6892a0"],Genesis6:["#80b606","#e29f1d","#2397e2","#35aca2","#5430bb","#8d34e0"],Grayscale6:["#dddddd","#b2b2b2","#969696","#808080","#5f5f5f","#4d4d4d"],Green6:["#549e39","#8ab833","#c0cf3a","#029676","#4ab5c4","#0989b1"],GreenYellow6:["#99cb38","#63a537","#37a76f","#44c1a3","#4eb3cf","#51c3f9"],Grid6:["#c66951","#bf974d","#928b70","#87706b","#94734e","#6f777d"],Habitat6:["#f8c000","#f88600","#f83500","#8b723d","#818b3d","#586215"],Hardcover6:["#873624","#d6862d","#d0be40","#877f6c","#972109","#aeb795"],Headlines6:["#439eb7","#e28b55","#dcb64d","#4ca198","#835b82","#645135"],Horizon6:["#7e97ad","#cc8e60","#7a6a60","#b4936d","#67787b","#9d936f"],Infusion6:["#8c73d0","#c2e8c4","#c5a6e8","#b45ec7","#9fdafb","#95c5b0"],Inkwell6:["#860908","#4a0505","#7a500a","#c47810","#827752","#b5bb83"],Inspiration6:["#749805","#bacc82","#6e9ec2","#2046a5","#5039c6","#7411d0"],Integral6:["#1cade4","#2683c6","#27ced7","#42ba97","#3e8853","#62a39f"],Ion6:["#b01513","#ea6312","#e6b729","#6aac90","#5f9c9d","#9e5e9b"],IonBoardroom6:["#b31166","#e33d6f","#e45f3c","#e9943a","#9b6bf2","#d53dd0"],Kilter6:["#76c5ef","#fea022","#ff6700","#70a525","#a5d848","#20768c"],Madison6:["#a1d68b","#5ec795","#4dadcf","#cdb756","#e29c36","#8ec0c1"],MainEvent6:["#b80e0f","#a6987d","#7f9a71","#64969f","#9b75b2","#80737a"],Marquee6:["#418ab3","#a6b727","#f69200","#838383","#fec306","#df5327"],Median6:["#94b6d2","#dd8047","#a5ab81","#d8b25c","#7ba79d","#968c8c"],Mesh6:["#6f6f6f","#bfbfa5","#dcd084","#e7bf5f","#e9a039","#cf7133"],Metail6:["#6283ad","#324966","#5b9ea4","#1d5b57","#1b4430","#2f3c35"],Metro6:["#7fd13b","#ea157a","#feb80a","#00addc","#738ac8","#1ab39f"],Metropolitan6:["#50b4c8","#a8b97f","#9b9256","#657689","#7a855d","#84ac9d"],Module6:["#f0ad00","#60b5cc","#e66c7d","#6bb76d","#e88651","#c64847"],NewsPrint6:["#ad0101","#726056","#ac956e","#808da9","#424e5b","#730e00"],Office6:["#5b9bd5","#ed7d31","#a5a5a5","#ffc000","#4472c4","#70ad47"],"Office2007-2010-6":["#4f81bd","#c0504d","#9bbb59","#8064a2","#4bacc6","#f79646"],Opulent6:["#b83d68","#ac66bb","#de6c36","#f9b639","#cf6da4","#fa8d3d"],Orange6:["#e48312","#bd582c","#865640","#9b8357","#c2bc80","#94a088"],OrangeRed6:["#d34817","#9b2d1f","#a28e6a","#956251","#918485","#855d5d"],Orbit6:["#f2d908","#9de61e","#0d8be6","#c61b1b","#e26f08","#8d35d1"],Organic6:["#83992a","#3c9770","#44709d","#a23c33","#d97828","#deb340"],Oriel6:["#fe8637","#7598d9","#b32c16","#f5cd2d","#aebad5","#777c84"],Origin6:["#727ca3","#9fb8cd","#d2da7a","#fada7a","#b88472","#8e736a"],Paper6:["#a5b592","#f3a447","#e7bc29","#d092a7","#9c85c0","#809ec2"],Parallax6:["#30acec","#80c34f","#e29d3e","#d64a3b","#d64787","#a666e1"],Parcel6:["#f6a21d","#9bafb5","#c96731","#9ca383","#87795d","#a0988c"],Perception6:["#a2c816","#e07602","#e4c402","#7dc1ef","#21449b","#a2b170"],Perspective6:["#838d9b","#d2610c","#80716a","#94147c","#5d5ad2","#6f6c7d"],Pixel6:["#ff7f01","#f1b015","#fbec85","#d2c2f1","#da5af4","#9d09d1"],Plaza6:["#990000","#580101","#e94a00","#eb8f00","#a4a4a4","#666666"],Precedent6:["#993232","#9b6c34","#736c5d","#c9972b","#c95f2b","#8f7a05"],Pushpin6:["#fda023","#aa2b1e","#71685c","#64a73b","#eb5605","#b9ca1a"],Quotable6:["#00c6bb","#6feba0","#b6df5e","#efb251","#ef755f","#ed515c"],Red6:["#a5300f","#d55816","#e19825","#b19c7d","#7f5f52","#b27d49"],RedOrange6:["#e84c22","#ffbd47","#b64926","#ff8427","#cc9900","#b22600"],RedViolet6:["#e32d91","#c830cc","#4ea6dc","#4775e7","#8971e1","#d54773"],Retrospect6:["#e48312","#bd582c","#865640","#9b8357","#c2bc80","#94a088"],Revolution6:["#0c5986","#ddf53d","#508709","#bf5e00","#9c0001","#660075"],Saddle6:["#c6b178","#9c5b14","#71b2bc","#78aa5d","#867099","#4c6f75"],Savon6:["#1cade4","#2683c6","#27ced7","#42ba97","#3e8853","#62a39f"],Sketchbook6:["#a63212","#e68230","#9bb05e","#6b9bc7","#4e66b2","#8976ac"],Sky6:["#073779","#8fd9fb","#ffcc00","#eb6615","#c76402","#b523b4"],Slate6:["#bc451b","#d3ba68","#bb8640","#ad9277","#a55a43","#ad9d7b"],Slice6:["#052f61","#a50e82","#14967c","#6a9e1f","#e87d37","#c62324"],Slipstream6:["#4e67c8","#5eccf3","#a7ea52","#5dceaf","#ff8021","#f14124"],SOHO6:["#61625e","#964d2c","#66553e","#848058","#afa14b","#ad7d4d"],Solstice6:["#3891a7","#feb80a","#c32d2e","#84aa33","#964305","#475a8d"],Spectrum6:["#990000","#ff6600","#ffba00","#99cc00","#528a02","#333333"],Story6:["#1d86cd","#732e9a","#b50b1b","#e8950e","#55992b","#2c9c89"],Studio6:["#f7901e","#fec60b","#9fe62f","#4ea5d1","#1c4596","#542d90"],Summer6:["#51a6c2","#51c2a9","#7ec251","#e1dc53","#b54721","#a16bb1"],Technic6:["#6ea0b0","#ccaf0a","#8d89a4","#748560","#9e9273","#7e848d"],Thatch6:["#759aa5","#cfc60d","#99987f","#90ac97","#ffad1c","#b9ab6f"],Tradition6:["#6b4a0b","#790a14","#908342","#423e5c","#641345","#748a2f"],Travelogue6:["#b74d21","#a32323","#4576a3","#615d9a","#67924b","#bf7b1b"],Trek6:["#f0a22e","#a5644e","#b58b80","#c3986d","#a19574","#c17529"],Twilight6:["#e8bc4a","#83c1c6","#e78d35","#909ce1","#839c41","#cc5439"],Urban6:["#53548a","#438086","#a04da3","#c4652d","#8b5d3d","#5c92b5"],UrbanPop6:["#86ce24","#00a2e6","#fac810","#7d8f8c","#d06b20","#958b8b"],VaporTrail6:["#df2e28","#fe801a","#e9bf35","#81bb42","#32c7a9","#4a9bdc"],Venture6:["#9eb060","#d09a08","#f2ec86","#824f1c","#511818","#553876"],Verve6:["#ff388c","#e40059","#9c007f","#68007f","#005bd3","#00349e"],View6:["#6f6f74","#92a9b9","#a7b789","#b9a489","#8d6374","#9b7362"],Violet6:["#ad84c6","#8784c7","#5d739a","#6997af","#84acb6","#6f8183"],VioletII6:["#92278f","#9b57d3","#755dd9","#665eb8","#45a5ed","#5982db"],Waveform6:["#31b6fd","#4584d3","#5bd078","#a5d028","#f5c040","#05e0db"],Wisp6:["#a53010","#de7e18","#9f8351","#728653","#92aa4c","#6aac91"],WoodType6:["#d34817","#9b2d1f","#a28e6a","#956251","#918485","#855d5d"],Yellow6:["#ffca08","#f8931d","#ce8d3e","#ec7016","#e64823","#9c6a6a"],YellowOrange6:["#f0a22e","#a5644e","#b58b80","#c3986d","#a19574","#c17529"]},tableau:{Tableau10:["#4E79A7","#F28E2B","#E15759","#76B7B2","#59A14F","#EDC948","#B07AA1","#FF9DA7","#9C755F","#BAB0AC"],Tableau20:["#4E79A7","#A0CBE8","#F28E2B","#FFBE7D","#59A14F","#8CD17D","#B6992D","#F1CE63","#499894","#86BCB6","#E15759","#FF9D9A","#79706E","#BAB0AC","#D37295","#FABFD2","#B07AA1","#D4A6C8","#9D7660","#D7B5A6"],ColorBlind10:["#1170aa","#fc7d0b","#a3acb9","#57606c","#5fa2ce","#c85200","#7b848f","#a3cce9","#ffbc79","#c8d0d9"],SeattleGrays5:["#767f8b","#b3b7b8","#5c6068","#d3d3d3","#989ca3"],Traffic9:["#b60a1c","#e39802","#309143","#e03531","#f0bd27","#51b364","#ff684c","#ffda66","#8ace7e"],MillerStone11:["#4f6980","#849db1","#a2ceaa","#638b66","#bfbb60","#f47942","#fbb04e","#b66353","#d7ce9f","#b9aa97","#7e756d"],SuperfishelStone10:["#6388b4","#ffae34","#ef6f6a","#8cc2ca","#55ad89","#c3bc3f","#bb7693","#baa094","#a9b5ae","#767676"],NurielStone9:["#8175aa","#6fb899","#31a1b3","#ccb22b","#a39fc9","#94d0c0","#959c9e","#027b8e","#9f8f12"],JewelBright9:["#eb1e2c","#fd6f30","#f9a729","#f9d23c","#5fbb68","#64cdcc","#91dcea","#a4a4d5","#bbc9e5"],Summer8:["#bfb202","#b9ca5d","#cf3e53","#f1788d","#00a2b3","#97cfd0","#f3a546","#f7c480"],Winter10:["#90728f","#b9a0b4","#9d983d","#cecb76","#e15759","#ff9888","#6b6b6b","#bab2ae","#aa8780","#dab6af"],GreenOrangeTeal12:["#4e9f50","#87d180","#ef8a0c","#fcc66d","#3ca8bc","#98d9e4","#94a323","#c3ce3d","#a08400","#f7d42a","#26897e","#8dbfa8"],RedBlueBrown12:["#466f9d","#91b3d7","#ed444a","#feb5a2","#9d7660","#d7b5a6","#3896c4","#a0d4ee","#ba7e45","#39b87f","#c8133b","#ea8783"],PurplePinkGray12:["#8074a8","#c6c1f0","#c46487","#ffbed1","#9c9290","#c5bfbe","#9b93c9","#ddb5d5","#7c7270","#f498b6","#b173a0","#c799bc"],HueCircle19:["#1ba3c6","#2cb5c0","#30bcad","#21B087","#33a65c","#57a337","#a2b627","#d5bb21","#f8b620","#f89217","#f06719","#e03426","#f64971","#fc719e","#eb73b3","#ce69be","#a26dc2","#7873c0","#4f7cba"],OrangeBlue7:["#9e3d22","#d45b21","#f69035","#d9d5c9","#77acd3","#4f81af","#2b5c8a"],RedGreen7:["#a3123a","#e33f43","#f8816b","#ced7c3","#73ba67","#44914e","#24693d"],GreenBlue7:["#24693d","#45934d","#75bc69","#c9dad2","#77a9cf","#4e7fab","#2a5783"],RedBlue7:["#a90c38","#e03b42","#f87f69","#dfd4d1","#7eaed3","#5383af","#2e5a87"],RedBlack7:["#ae123a","#e33e43","#f8816b","#d9d9d9","#a0a7a8","#707c83","#49525e"],GoldPurple7:["#ad9024","#c1a33b","#d4b95e","#e3d8cf","#d4a3c3","#c189b0","#ac7299"],RedGreenGold7:["#be2a3e","#e25f48","#f88f4d","#f4d166","#90b960","#4b9b5f","#22763f"],SunsetSunrise7:["#33608c","#9768a5","#e7718a","#f6ba57","#ed7846","#d54c45","#b81840"],OrangeBlueWhite7:["#9e3d22","#e36621","#fcad52","#ffffff","#95c5e1","#5b8fbc","#2b5c8a"],RedGreenWhite7:["#ae123a","#ee574d","#fdac9e","#ffffff","#91d183","#539e52","#24693d"],GreenBlueWhite7:["#24693d","#529c51","#8fd180","#ffffff","#95c1dd","#598ab5","#2a5783"],RedBlueWhite7:["#a90c38","#ec534b","#feaa9a","#ffffff","#9ac4e1","#5c8db8","#2e5a87"],RedBlackWhite7:["#ae123a","#ee574d","#fdac9d","#ffffff","#bdc0bf","#7d888d","#49525e"],OrangeBlueLight7:["#ffcc9e","#f9d4b6","#f0dccd","#e5e5e5","#dae1ea","#cfdcef","#c4d8f3"],Temperature7:["#529985","#6c9e6e","#99b059","#dbcf47","#ebc24b","#e3a14f","#c26b51"],BlueGreen7:["#feffd9","#f2fabf","#dff3b2","#c4eab1","#94d6b7","#69c5be","#41b7c4"],BlueLight7:["#e5e5e5","#e0e3e8","#dbe1ea","#d5dfec","#d0dcef","#cadaf1","#c4d8f3"],OrangeLight7:["#e5e5e5","#ebe1d9","#f0ddcd","#f5d9c2","#f9d4b6","#fdd0aa","#ffcc9e"],Blue20:["#b9ddf1","#afd6ed","#a5cfe9","#9bc7e4","#92c0df","#89b8da","#80b0d5","#79aacf","#72a3c9","#6a9bc3","#6394be","#5b8cb8","#5485b2","#4e7fac","#4878a6","#437a9f","#3d6a98","#376491","#305d8a","#2a5783"],Orange20:["#ffc685","#fcbe75","#f9b665","#f7ae54","#f5a645","#f59c3c","#f49234","#f2882d","#f07e27","#ee7422","#e96b20","#e36420","#db5e20","#d25921","#ca5422","#c14f22","#b84b23","#af4623","#a64122","#9e3d22"],Green20:["#b3e0a6","#a5db96","#98d687","#8ed07f","#85ca77","#7dc370","#75bc69","#6eb663","#67af5c","#61a956","#59a253","#519c51","#49964f","#428f4d","#398949","#308344","#2b7c40","#27763d","#256f3d","#24693d"],Red20:["#ffbeb2","#feb4a6","#fdab9b","#fca290","#fb9984","#fa8f79","#f9856e","#f77b66","#f5715d","#f36754","#f05c4d","#ec5049","#e74545","#e13b42","#da323f","#d3293d","#ca223c","#c11a3b","#b8163a","#ae123a"],Purple20:["#eec9e5","#eac1df","#e6b9d9","#e0b2d2","#daabcb","#d5a4c4","#cf9dbe","#ca96b8","#c48fb2","#be89ac","#b882a6","#b27ba1","#aa759d","#a27099","#9a6a96","#926591","#8c5f86","#865986","#81537f","#7c4d79"],Brown20:["#eedbbd","#ecd2ad","#ebc994","#eac085","#e8b777","#e5ae6c","#e2a562","#de9d5a","#d99455","#d38c54","#ce8451","#c9784d","#c47247","#c16941","#bd6036","#b85636","#b34d34","#ad4433","#a63d32","#9f3632"],Gray20:["#d5d5d5","#cdcecd","#c5c7c6","#bcbfbe","#b4b7b7","#acb0b1","#a4a9ab","#9ca3a4","#939c9e","#8b9598","#848e93","#7c878d","#758087","#6e7a81","#67737c","#616c77","#5b6570","#555f6a","#4f5864","#49525e"],GrayWarm20:["#dcd4d0","#d4ccc8","#cdc4c0","#c5bdb9","#beb6b2","#b7afab","#b0a7a4","#a9a09d","#a29996","#9b938f","#948c88","#8d8481","#867e7b","#807774","#79706e","#736967","#6c6260","#665c51","#5f5654","#59504e"],BlueTeal20:["#bce4d8","#aedcd5","#a1d5d2","#95cecf","#89c8cc","#7ec1ca","#72bac6","#66b2c2","#59acbe","#4ba5ba","#419eb6","#3b96b2","#358ead","#3586a7","#347ea1","#32779b","#316f96","#2f6790","#2d608a","#2c5985"],OrangeGold20:["#f4d166","#f6c760","#f8bc58","#f8b252","#f7a84a","#f69e41","#f49538","#f38b2f","#f28026","#f0751e","#eb6c1c","#e4641e","#de5d1f","#d75521","#cf4f22","#c64a22","#bc4623","#b24223","#a83e24","#9e3a26"],GreenGold20:["#f4d166","#e3cd62","#d3c95f","#c3c55d","#b2c25b","#a3bd5a","#93b958","#84b457","#76af56","#67a956","#5aa355","#4f9e53","#479751","#40914f","#3a8a4d","#34844a","#2d7d45","#257740","#1c713b","#146c36"],RedGold21:["#f4d166","#f5c75f","#f6bc58","#f7b254","#f9a750","#fa9d4f","#fa9d4f","#fb934d","#f7894b","#f47f4a","#f0774a","#eb6349","#e66549","#e15c48","#dc5447","#d64c45","#d04344","#ca3a42","#c43141","#bd273f","#b71d3e"],Classic10:["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"],ClassicMedium10:["#729ece","#ff9e4a","#67bf5c","#ed665d","#ad8bc9","#a8786e","#ed97ca","#a2a2a2","#cdcc5d","#6dccda"],ClassicLight10:["#aec7e8","#ffbb78","#98df8a","#ff9896","#c5b0d5","#c49c94","#f7b6d2","#c7c7c7","#dbdb8d","#9edae5"],Classic20:["#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5"],ClassicGray5:["#60636a","#a5acaf","#414451","#8f8782","#cfcfcf"],ClassicColorBlind10:["#006ba4","#ff800e","#ababab","#595959","#5f9ed1","#c85200","#898989","#a2c8ec","#ffbc79","#cfcfcf"],ClassicTrafficLight9:["#b10318","#dba13a","#309343","#d82526","#ffc156","#69b764","#f26c64","#ffdd71","#9fcd99"],ClassicPurpleGray6:["#7b66d2","#dc5fbd","#94917b","#995688","#d098ee","#d7d5c5"],ClassicPurpleGray12:["#7b66d2","#a699e8","#dc5fbd","#ffc0da","#5f5a41","#b4b19b","#995688","#d898ba","#ab6ad5","#d098ee","#8b7c6e","#dbd4c5"],ClassicGreenOrange6:["#32a251","#ff7f0f","#3cb7cc","#ffd94a","#39737c","#b85a0d"],ClassicGreenOrange12:["#32a251","#acd98d","#ff7f0f","#ffb977","#3cb7cc","#98d9e4","#b85a0d","#ffd94a","#39737c","#86b4a9","#82853b","#ccc94d"],ClassicBlueRed6:["#2c69b0","#f02720","#ac613c","#6ba3d6","#ea6b73","#e9c39b"],ClassicBlueRed12:["#2c69b0","#b5c8e2","#f02720","#ffb6b0","#ac613c","#e9c39b","#6ba3d6","#b5dffd","#ac8763","#ddc9b4","#bd0a36","#f4737a"],ClassicCyclic13:["#1f83b4","#12a2a8","#2ca030","#78a641","#bcbd22","#ffbf50","#ffaa0e","#ff7f0e","#d63a3a","#c7519c","#ba43b4","#8a60b0","#6f63bb"],ClassicGreen7:["#bccfb4","#94bb83","#69a761","#339444","#27823b","#1a7232","#09622a"],ClassicGray13:["#c3c3c3","#b2b2b2","#a2a2a2","#929292","#838383","#747474","#666666","#585858","#4b4b4b","#3f3f3f","#333333","#282828","#1e1e1e"],ClassicBlue7:["#b4d4da","#7bc8e2","#67add4","#3a87b7","#1c73b1","#1c5998","#26456e"],ClassicRed9:["#eac0bd","#f89a90","#f57667","#e35745","#d8392c","#cf1719","#c21417","#b10c1d","#9c0824"],ClassicOrange7:["#f0c294","#fdab67","#fd8938","#f06511","#d74401","#a33202","#7b3014"],ClassicAreaRed11:["#f5cac7","#fbb3ab","#fd9c8f","#fe8b7a","#fd7864","#f46b55","#ea5e45","#e04e35","#d43e25","#c92b14","#bd1100"],ClassicAreaGreen11:["#dbe8b4","#c3e394","#acdc7a","#9ad26d","#8ac765","#7abc5f","#6cae59","#60a24d","#569735","#4a8c1c","#3c8200"],ClassicAreaBrown11:["#f3e0c2","#f6d29c","#f7c577","#f0b763","#e4aa63","#d89c63","#cc8f63","#c08262","#bb7359","#bb6348","#bb5137"],ClassicRedGreen11:["#9c0824","#bd1316","#d11719","#df513f","#fc8375","#cacaca","#a2c18f","#69a761","#2f8e41","#1e7735","#09622a"],ClassicRedBlue11:["#9c0824","#bd1316","#d11719","#df513f","#fc8375","#cacaca","#67add4","#3a87b7","#1c73b1","#1c5998","#26456e"],ClassicRedBlack11:["#9c0824","#bd1316","#d11719","#df513f","#fc8375","#cacaca","#9b9b9b","#777777","#565656","#383838","#1e1e1e"],ClassicAreaRedGreen21:["#bd1100","#c82912","#d23a21","#dc4930","#e6583e","#ef654d","#f7705b","#fd7e6b","#fe8e7e","#fca294","#e9dabe","#c7e298","#b1de7f","#a0d571","#90cb68","#82c162","#75b65d","#69aa56","#5ea049","#559633","#4a8c1c"],ClassicOrangeBlue13:["#7b3014","#a33202","#d74401","#f06511","#fd8938","#fdab67","#cacaca","#7bc8e2","#67add4","#3a87b7","#1c73b1","#1c5998","#26456e"],ClassicGreenBlue11:["#09622a","#1e7735","#2f8e41","#69a761","#a2c18f","#cacaca","#67add4","#3a87b7","#1c73b1","#1c5998","#26456e"],ClassicRedWhiteGreen11:["#9c0824","#b41f27","#cc312b","#e86753","#fcb4a5","#ffffff","#b9d7b7","#74af72","#428f49","#297839","#09622a"],ClassicRedWhiteBlack11:["#9c0824","#b41f27","#cc312b","#e86753","#fcb4a5","#ffffff","#bfbfbf","#838383","#575757","#393939","#1e1e1e"],ClassicOrangeWhiteBlue11:["#7b3014","#a84415","#d85a13","#fb8547","#ffc2a1","#ffffff","#b7cde2","#6a9ec5","#3679a8","#2e5f8a","#26456e"],ClassicRedWhiteBlackLight10:["#ffc2c5","#ffd1d3","#ffe0e1","#fff0f0","#ffffff","#f3f3f3","#e8e8e8","#dddddd","#d1d1d1","#c6c6c6"],ClassicOrangeWhiteBlueLight11:["#ffcc9e","#ffd6b1","#ffe0c5","#ffead8","#fff5eb","#ffffff","#f3f7fd","#e8effa","#dce8f8","#d0e0f6","#c4d8f3"],ClassicRedWhiteGreenLight11:["#ffb2b6","#ffc2c5","#ffd1d3","#ffe0e1","#fff0f0","#ffffff","#f1faed","#e3f5db","#d5f0ca","#c6ebb8","#b7e6a7"],ClassicRedGreenLight11:["#ffb2b6","#fcbdc0","#f8c7c9","#f2d1d2","#ecdbdc","#e5e5e5","#dde6d9","#d4e6cc","#cae6c0","#c1e6b4","#b7e6a7"]}},n=f.helpers,c=2===f.DatasetController.prototype.removeHoverStyle.length;f.defaults.global.plugins.colorschemes={scheme:"brewer.Paired12",fillAlpha:.5,reverse:!1};var e={id:"colorschemes",beforeUpdate:function(d,c){var a,b,r,l,f=c.scheme.split("."),e=o[f[0]];return e&&(a=e[f[1]],b=a.length,a&&d.config.data.datasets.forEach(function(f,e){switch(r=e%b,l=a[c.reverse?b-r-1:r],f.colorschemes={},f.type||d.config.type){case"line":case"radar":case"scatter":void 0===f.backgroundColor&&(f.backgroundColor=n.color(l).alpha(c.fillAlpha).rgbString(),f.colorschemes.backgroundColor=!0),void 0===f.borderColor&&(f.borderColor=l,f.colorschemes.borderColor=!0),void 0===f.pointBackgroundColor&&(f.pointBackgroundColor=n.color(l).alpha(c.fillAlpha).rgbString(),f.colorschemes.pointBackgroundColor=!0),void 0===f.pointBorderColor&&(f.pointBorderColor=l,f.colorschemes.pointBorderColor=!0);break;case"doughnut":case"pie":void 0===f.backgroundColor&&(f.backgroundColor=f.data.map(function(f,e){return r=e%b,a[c.reverse?b-r-1:r]}),f.colorschemes.backgroundColor=!0);break;default:void 0===f.backgroundColor&&(f.backgroundColor=l,f.colorschemes.backgroundColor=!0)}})),!0},afterUpdate:function(f){f.config.data.datasets.forEach(function(f){f.colorschemes&&(f.colorschemes.backgroundColor&&delete f.backgroundColor,f.colorschemes.borderColor&&delete f.borderColor,f.colorschemes.pointBackgroundColor&&delete f.pointBackgroundColor,f.colorschemes.pointBorderColor&&delete f.pointBorderColor,delete f.colorschemes)})},beforeEvent:function(f,e,d){return c&&this.beforeUpdate(f,d),!0},afterEvent:function(f){c&&this.afterUpdate(f)}};return f.colorschemes=o,f.plugins.register(e),e}); \ No newline at end of file diff --git a/app/assets/stylesheets/legacy.scss b/app/assets/stylesheets/legacy.scss index dd9519eb..3031810f 100644 --- a/app/assets/stylesheets/legacy.scss +++ b/app/assets/stylesheets/legacy.scss @@ -1266,7 +1266,7 @@ button.positive, .widgets a.positive{ background-color:black; } -.stats_content .open-flash-chart, .stats_content .stats_module { +.stats_content .chart, .stats_content .stats_module { float: left; width: 450px; margin-right:20px; diff --git a/app/assets/swfs/expressInstall.swf b/app/assets/swfs/expressInstall.swf deleted file mode 100644 index 0fbf8fca..00000000 Binary files a/app/assets/swfs/expressInstall.swf and /dev/null differ diff --git a/app/assets/swfs/open-flash-chart.swf b/app/assets/swfs/open-flash-chart.swf deleted file mode 100644 index 85b590a2..00000000 Binary files a/app/assets/swfs/open-flash-chart.swf and /dev/null differ diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index f217a18f..39b1c908 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -11,42 +11,6 @@ class StatsController < ApplicationController @stats = Stats::UserStats.new(current_user) end - def actions_done_last12months_data - # get actions created and completed in the past 12+3 months. +3 for running - # - outermost set of entries needed for these calculations - actions_last12months = current_user.todos.created_or_completed_after(@cut_off_year_plus3).select("completed_at,created_at") - - # convert to array and fill in non-existing months - @actions_done_last12months_array = put_events_into_month_buckets(actions_last12months, 13, :completed_at) - @actions_created_last12months_array = put_events_into_month_buckets(actions_last12months, 13, :created_at) - - # find max for graph in both arrays - @max = (@actions_done_last12months_array + @actions_created_last12months_array).max - - # find running avg - done_in_last_15_months = put_events_into_month_buckets(actions_last12months, 16, :completed_at) - created_in_last_15_months = put_events_into_month_buckets(actions_last12months, 16, :created_at) - - @actions_done_avg_last12months_array = compute_running_avg_array(done_in_last_15_months, 13) - @actions_created_avg_last12months_array = compute_running_avg_array(created_in_last_15_months, 13) - - # interpolate avg for current month. - @interpolated_actions_created_this_month = interpolate_avg_for_current_month(@actions_created_last12months_array) - @interpolated_actions_done_this_month = interpolate_avg_for_current_month(@actions_done_last12months_array) - - @created_count_array = Array.new(13, actions_last12months.created_after(@cut_off_year).count(:all)/12.0) - @done_count_array = Array.new(13, actions_last12months.completed_after(@cut_off_year).count(:all)/12.0) - render :layout => false - end - - def interpolate_avg_for_current_month(set) - (set[0]*(1/percent_of_month) + set[1] + set[2]) / 3.0 - end - - def percent_of_month - Time.zone.now.day / Time.zone.now.end_of_month.day.to_f - end - def actions_done_last_years @page_title = t('stats.index_title') @chart = Stats::Chart.new('actions_done_lastyears_data', :height => 400, :width => 900) @@ -80,191 +44,6 @@ class StatsController < ApplicationController render :layout => false end - def actions_done_last30days_data - # get actions created and completed in the past 30 days. - @actions_done_last30days = current_user.todos.completed_after(@cut_off_30days).select("completed_at") - @actions_created_last30days = current_user.todos.created_after(@cut_off_30days).select("created_at") - - # convert to array. 30+1 to have 30 complete days and one current day [0] - @actions_done_last30days_array = convert_to_days_from_today_array(@actions_done_last30days, 31, :completed_at) - @actions_created_last30days_array = convert_to_days_from_today_array(@actions_created_last30days, 31, :created_at) - - # find max for graph in both hashes - @max = [@actions_done_last30days_array.max, @actions_created_last30days_array.max].max - - render :layout => false - end - - def actions_completion_time_data - @actions_completion_time = current_user.todos.completed.select("completed_at, created_at").reorder("completed_at DESC" ) - - # convert to array and fill in non-existing weeks with 0 - @max_weeks = @actions_completion_time.last ? difference_in_weeks(@today, @actions_completion_time.last.completed_at) : 1 - @actions_completed_per_week_array = convert_to_weeks_running_array(@actions_completion_time, @max_weeks+1) - - # stop the chart after 10 weeks - @count = [10, @max_weeks].min - - # convert to new array to hold max @cut_off elems + 1 for sum of actions after @cut_off - @actions_completion_time_array = cut_off_array_with_sum(@actions_completed_per_week_array, @count) - @max_actions = @actions_completion_time_array.max - - # get percentage done cumulative - @cum_percent_done = convert_to_cumulative_array(@actions_completion_time_array, @actions_completion_time.count(:all)) - - render :layout => false - end - - def actions_running_time_data - @actions_running_time = current_user.todos.not_completed.select("created_at").reorder("created_at DESC") - - # convert to array and fill in non-existing weeks with 0 - @max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at) - @actions_running_per_week_array = convert_to_weeks_from_today_array(@actions_running_time, @max_weeks+1, :created_at) - - # cut off chart at 52 weeks = one year - @count = [52, @max_weeks].min - - # convert to new array to hold max @cut_off elems + 1 for sum of actions after @cut_off - @actions_running_time_array = cut_off_array_with_sum(@actions_running_per_week_array, @count) - @max_actions = @actions_running_time_array.max - - # get percentage done cumulative - @cum_percent_done = convert_to_cumulative_array(@actions_running_time_array, @actions_running_time.count ) - - render :layout => false - end - - def actions_visible_running_time_data - # running means - # - not completed (completed_at must be null) - # visible means - # - actions not part of a hidden project - # - actions not part of a hidden context - # - actions not deferred (show_from must be null) - # - actions not pending/blocked - - @actions_running_time = current_user.todos.not_completed.not_hidden.not_deferred_or_blocked. - select("todos.created_at"). - reorder("todos.created_at DESC") - - @max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at) - @actions_running_per_week_array = convert_to_weeks_from_today_array(@actions_running_time, @max_weeks+1, :created_at) - - # cut off chart at 52 weeks = one year - @count = [52, @max_weeks].min - - # convert to new array to hold max @cut_off elems + 1 for sum of actions after @cut_off - @actions_running_time_array = cut_off_array_with_sum(@actions_running_per_week_array, @count) - @max_actions = @actions_running_time_array.max - - # get percentage done cumulative - @cum_percent_done = convert_to_cumulative_array(@actions_running_time_array, @actions_running_time.count ) - - render :layout => false - end - - def actions_open_per_week_data - @actions_started = current_user.todos.created_after(@today-53.weeks). - select("todos.created_at, todos.completed_at"). - reorder("todos.created_at DESC") - - @max_weeks = difference_in_weeks(@today, @actions_started.last.created_at) - - # cut off chart at 52 weeks = one year - @count = [52, @max_weeks].min - - @actions_open_per_week_array = convert_to_weeks_running_from_today_array(@actions_started, @max_weeks+1) - @actions_open_per_week_array = cut_off_array(@actions_open_per_week_array, @count) - @max_actions = (@actions_open_per_week_array.max or 0) - - render :layout => false - end - - def context_total_actions_data - actions = Stats::TopContextsQuery.new(current_user).result - - @data = Stats::PieChartData.new(actions, t('stats.spread_of_actions_for_all_context'), 70) - - render :pie_chart_data, :layout => false - end - - def context_running_actions_data - actions = Stats::TopContextsQuery.new(current_user, :running => true).result - @data = Stats::PieChartData.new(actions, t('stats.spread_of_running_actions_for_visible_contexts'), 60) - - render :pie_chart_data, :layout => false - end - - def actions_day_of_week_all_data - @actions_creation_day = current_user.todos.select("created_at") - @actions_completion_day = current_user.todos.completed.select("completed_at") - - # convert to array and fill in non-existing days - @actions_creation_day_array = Array.new(7) { |i| 0} - @actions_creation_day.each { |t| @actions_creation_day_array[ t.created_at.wday ] += 1 } - @max = @actions_creation_day_array.max - - # convert to array and fill in non-existing days - @actions_completion_day_array = Array.new(7) { |i| 0} - @actions_completion_day.each { |t| @actions_completion_day_array[ t.completed_at.wday ] += 1 } - @max = @actions_completion_day_array.max - - render :layout => false - end - - def actions_day_of_week_30days_data - @actions_creation_day = current_user.todos.created_after(@cut_off_month).select("created_at") - @actions_completion_day = current_user.todos.completed_after(@cut_off_month).select("completed_at") - - # convert to hash to be able to fill in non-existing days - @max=0 - @actions_creation_day_array = Array.new(7) { |i| 0} - @actions_creation_day.each { |r| @actions_creation_day_array[ r.created_at.wday ] += 1 } - - # convert to hash to be able to fill in non-existing days - @actions_completion_day_array = Array.new(7) { |i| 0} - @actions_completion_day.each { |r| @actions_completion_day_array[r.completed_at.wday] += 1 } - - @max = [@actions_creation_day_array.max, @actions_completion_day_array.max].max - - render :layout => false - end - - def actions_time_of_day_all_data - @actions_creation_hour = current_user.todos.select("created_at") - @actions_completion_hour = current_user.todos.completed.select("completed_at") - - # convert to hash to be able to fill in non-existing days - @actions_creation_hour_array = Array.new(24) { |i| 0} - @actions_creation_hour.each{|r| @actions_creation_hour_array[r.created_at.hour] += 1 } - - # convert to hash to be able to fill in non-existing days - @actions_completion_hour_array = Array.new(24) { |i| 0} - @actions_completion_hour.each{|r| @actions_completion_hour_array[r.completed_at.hour] += 1 } - - @max = [@actions_creation_hour_array.max, @actions_completion_hour_array.max].max - - render :layout => false - end - - def actions_time_of_day_30days_data - @actions_creation_hour = current_user.todos.created_after(@cut_off_month).select("created_at") - @actions_completion_hour = current_user.todos.completed_after(@cut_off_month).select("completed_at") - - # convert to hash to be able to fill in non-existing days - @actions_creation_hour_array = Array.new(24) { |i| 0} - @actions_creation_hour.each{|r| @actions_creation_hour_array[r.created_at.hour] += 1 } - - # convert to hash to be able to fill in non-existing days - @actions_completion_hour_array = Array.new(24) { |i| 0} - @actions_completion_hour.each{|r| @actions_completion_hour_array[r.completed_at.hour] += 1 } - - @max = [@actions_creation_hour_array.max, @max = @actions_completion_hour_array.max].max - - render :layout => false - end - def show_selected_actions_from_chart @page_title = t('stats.action_selection_title') @count = 99 @@ -385,58 +164,6 @@ class StatsController < ApplicationController convert_to_array(records.select { |x| x.send(date_method_on_todo) }, array_size) { |r| [difference_in_months(@today, r.send(date_method_on_todo))]} end - def convert_to_days_from_today_array(records, array_size, date_method_on_todo) - return convert_to_array(records, array_size){ |r| [difference_in_days(@today, r.send(date_method_on_todo))]} - end - - def convert_to_weeks_from_today_array(records, array_size, date_method_on_todo) - return convert_to_array(records, array_size) { |r| [difference_in_weeks(@today, r.send(date_method_on_todo))]} - end - - def convert_to_weeks_running_array(records, array_size) - return convert_to_array(records, array_size) { |r| [difference_in_weeks(r.completed_at, r.created_at)]} - end - - def convert_to_weeks_running_from_today_array(records, array_size) - return convert_to_array(records, array_size) { |r| week_indexes_of(r) } - end - - def week_indexes_of(record) - a = [] - start_week = difference_in_weeks(@today, record.created_at) - end_week = record.completed_at ? difference_in_weeks(@today, record.completed_at) : 0 - end_week.upto(start_week) { |i| a << i }; - return a - end - - # returns a new array containing all elems of array up to cut_off and - # adds the sum of the rest of array to the last elem - def cut_off_array_with_sum(array, cut_off) - # +1 to hold sum of rest - a = Array.new(cut_off+1){|i| array[i]||0} - # add rest of array to last elem - a[cut_off] += array.inject(:+) - a.inject(:+) - return a - end - - def cut_off_array(array, cut_off) - return Array.new(cut_off){|i| array[i]||0} - end - - def convert_to_cumulative_array(array, max) - # calculate fractions - a = Array.new(array.size){|i| array[i]*100.0/max} - # make cumulative - 1.upto(array.size-1){ |i| a[i] += a[i-1] } - return a - end - - # assumes date1 > date2 - # this results in the number of months before the month of date1, not taking days into account, so diff of 31-dec and 1-jan is 1 month! - def difference_in_months(date1, date2) - return (date1.utc.year - date2.utc.year)*12 + (date1.utc.month - date2.utc.month) - end - # assumes date1 > date2 def difference_in_days(date1, date2) return ((date1.utc.at_midnight-date2.utc.at_midnight)/SECONDS_PER_DAY).to_i @@ -446,22 +173,4 @@ class StatsController < ApplicationController def difference_in_weeks(date1, date2) return difference_in_days(date1, date2) / 7 end - - def three_month_avg(set, i) - (set.fetch(i){ 0 } + set.fetch(i+1){ 0 } + set.fetch(i+2){ 0 }) / 3.0 - end - - def set_three_month_avg(set,upper_bound) - (0..upper_bound-1).map { |i| three_month_avg(set, i) } - end - - # sets "null" on first column and - if necessary - cleans up last two columns, which may have insufficient data - def compute_running_avg_array(set, upper_bound) - result = set_three_month_avg(set, upper_bound) - result[upper_bound-1] = result[upper_bound-1] * 3 if upper_bound == set.length - result[upper_bound-2] = result[upper_bound-2] * 3 / 2 if upper_bound > 1 and upper_bound == set.length - result[0] = "null" - result - end # unsolved, not triggered, edge case for set.length == upper_bound + 1 - end diff --git a/app/models/stats/actions.rb b/app/models/stats/actions.rb index 212aa374..2d862d46 100644 --- a/app/models/stats/actions.rb +++ b/app/models/stats/actions.rb @@ -6,6 +6,12 @@ module Stats attr_reader :user def initialize(user) @user = user + + @today = Time.zone.now.utc.beginning_of_day + @cut_off_year = 12.months.ago.beginning_of_day + @cut_off_year_plus3 = 15.months.ago.beginning_of_day + @cut_off_month = 1.month.ago.beginning_of_day + @cut_off_30days = 30.days.ago.beginning_of_day end def ttc @@ -28,28 +34,281 @@ module Stats @sum_actions_created_last12months ||= new_since(one_year) end - def completion_charts - @completion_charts ||= %w{ - actions_done_last30days_data - actions_done_last12months_data - actions_completion_time_data - }.map do |action| - Stats::Chart.new(action) - end + def done_last12months_data + # get actions created and completed in the past 12+3 months. +3 for running + # - outermost set of entries needed for these calculations + actions_last12months = @user.todos.created_or_completed_after(@cut_off_year_plus3).select("completed_at,created_at") + + # convert to array and fill in non-existing months + @actions_done_last12months_array = put_events_into_month_buckets(actions_last12months, 13, :completed_at) + @actions_created_last12months_array = put_events_into_month_buckets(actions_last12months, 13, :created_at) + + # find max for graph in both arrays + @max = (@actions_done_last12months_array + @actions_created_last12months_array).max + + # find running avg + done_in_last_15_months = put_events_into_month_buckets(actions_last12months, 16, :completed_at) + created_in_last_15_months = put_events_into_month_buckets(actions_last12months, 16, :created_at) + + @actions_done_avg_last12months_array = compute_running_avg_array(done_in_last_15_months, 13) + @actions_created_avg_last12months_array = compute_running_avg_array(created_in_last_15_months, 13) + + # interpolate avg for current month. + # FIXME: These should also be used. + @interpolated_actions_created_this_month = interpolate_avg_for_current_month(@actions_created_last12months_array) + @interpolated_actions_done_this_month = interpolate_avg_for_current_month(@actions_done_last12months_array) + + @created_count_array = Array.new(13, actions_last12months.created_after(@cut_off_year).count(:all)/12.0) + @done_count_array = Array.new(13, actions_last12months.completed_after(@cut_off_year).count(:all)/12.0) + + return { + datasets: [ + {label: I18n.t('stats.labels.avg_created'), data: @created_count_array, type: "line"}, + {label: I18n.t('stats.labels.avg_completed'), data: @done_count_array, type: "line"}, + {label: I18n.t('stats.labels.month_avg_completed', :months => 3), data: @actions_done_avg_last12months_array, type: "line"}, + {label: I18n.t('stats.labels.month_avg_created', :months => 3), data: @actions_created_avg_last12months_array, type: "line"}, + {label: I18n.t('stats.labels.created'), data: @actions_created_last12months_array}, + {label: I18n.t('stats.labels.completed'), data: @actions_done_last12months_array}, + ], + labels: array_of_month_labels(@done_count_array.size), + } end - def timing_charts - @timing_charts ||= %w{ - actions_visible_running_time_data - actions_running_time_data - actions_open_per_week_data - actions_day_of_week_all_data - actions_day_of_week_30days_data - actions_time_of_day_all_data - actions_time_of_day_30days_data - }.map do |action| - Stats::Chart.new(action) - end + def done_last30days_data + # get actions created and completed in the past 30 days. + @actions_done_last30days = @user.todos.completed_after(@cut_off_30days).select("completed_at") + @actions_created_last30days = @user.todos.created_after(@cut_off_30days).select("created_at") + + # convert to array. 30+1 to have 30 complete days and one current day [0] + @actions_done_last30days_array = convert_to_days_from_today_array(@actions_done_last30days, 31, :completed_at) + @actions_created_last30days_array = convert_to_days_from_today_array(@actions_created_last30days, 31, :created_at) + + # find max for graph in both hashes + @max = [@actions_done_last30days_array.max, @actions_created_last30days_array.max].max + + created_count_array = Array.new(30){ |i| @actions_created_last30days.size/30.0 } + done_count_array = Array.new(30){ |i| @actions_done_last30days.size/30.0 } + # TODO: make the strftime i18n proof + time_labels = Array.new(30){ |i| I18n.l(Time.zone.now-i.days, :format => :stats) } + + return { + datasets: [ + {label: I18n.t('stats.labels.avg_created'), data: created_count_array, type: "line"}, + {label: I18n.t('stats.labels.avg_completed'), data: done_count_array, type: "line"}, + {label: I18n.t('stats.labels.created'), data: @actions_created_last30days_array}, + {label: I18n.t('stats.labels.completed'), data: @actions_done_last30days_array}, + ], + labels: time_labels, + } + end + + def completion_time_data + @actions_completion_time = @user.todos.completed.select("completed_at, created_at").reorder("completed_at DESC" ) + + # convert to array and fill in non-existing weeks with 0 + @max_weeks = @actions_completion_time.last ? difference_in_weeks(@today, @actions_completion_time.last.completed_at) : 1 + @actions_completed_per_week_array = convert_to_weeks_running_array(@actions_completion_time, @max_weeks+1) + + # stop the chart after 10 weeks + @count = [10, @max_weeks].min + + # convert to new array to hold max @cut_off elems + 1 for sum of actions after @cut_off + @actions_completion_time_array = cut_off_array_with_sum(@actions_completed_per_week_array, @count) + @max_actions = @actions_completion_time_array.max + + # get percentage done cumulative + @cum_percent_done = convert_to_cumulative_array(@actions_completion_time_array, @actions_completion_time.count(:all)) + + time_labels = Array.new(@count){ |i| "#{i}-#{i+1}" } + time_labels[0] = I18n.t('stats.within_one') + time_labels[@count] = "> #{@count}" + + return { + datasets: [ + {label: I18n.t('stats.legend.percentage'), data: @cum_percent_done, type: "line"}, + {label: I18n.t('stats.legend.actions'), data: @actions_completion_time_array}, + ], + labels: time_labels, + } + end + + def running_time_data + @actions_running_time = @user.todos.not_completed.select("created_at").reorder("created_at DESC") + + # convert to array and fill in non-existing weeks with 0 + @max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at) + @actions_running_per_week_array = convert_to_weeks_from_today_array(@actions_running_time, @max_weeks+1, :created_at) + + # cut off chart at 52 weeks = one year + @count = [52, @max_weeks].min + + # convert to new array to hold max @cut_off elems + 1 for sum of actions after @cut_off + @actions_running_time_array = cut_off_array_with_sum(@actions_running_per_week_array, @count) + @max_actions = @actions_running_time_array.max + + # get percentage done cumulative + @cum_percent_done = convert_to_cumulative_array(@actions_running_time_array, @actions_running_time.count ) + + time_labels = Array.new(@count){ |i| "#{i}-#{i+1}" } + time_labels[0] = "< 1" + time_labels[@count] = "> #{@count}" + + return { + datasets: [ + {label: I18n.t('stats.running_time_all_legend.percentage'), data: @cum_percent_done, type: "line"}, + {label: I18n.t('stats.running_time_all_legend.actions'), data: @actions_running_time_array}, + ], + labels: time_labels, + } + end + + def visible_running_time_data + # running means + # - not completed (completed_at must be null) + # visible means + # - actions not part of a hidden project + # - actions not part of a hidden context + # - actions not deferred (show_from must be null) + # - actions not pending/blocked + + @actions_running_time = @user.todos.not_completed.not_hidden.not_deferred_or_blocked. + select("todos.created_at"). + reorder("todos.created_at DESC") + + @max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at) + @actions_running_per_week_array = convert_to_weeks_from_today_array(@actions_running_time, @max_weeks+1, :created_at) + + # cut off chart at 52 weeks = one year + @count = [52, @max_weeks].min + + # convert to new array to hold max @cut_off elems + 1 for sum of actions after @cut_off + @actions_running_time_array = cut_off_array_with_sum(@actions_running_per_week_array, @count) + @max_actions = @actions_running_time_array.max + + # get percentage done cumulative + @cum_percent_done = convert_to_cumulative_array(@actions_running_time_array, @actions_running_time.count ) + + time_labels = Array.new(@count){ |i| "#{i}-#{i+1}" } + time_labels[0] = "< 1" + time_labels[@count] = "> #{@count}" + + return { + datasets: [ + {label: I18n.t('stats.running_time_legend.percentage'), data: @cum_percent_done, type: "line"}, + {label: I18n.t('stats.running_time_legend.actions'), data: @actions_running_time_array}, + ], + labels: time_labels, + } + end + + def open_per_week_data + @actions_started = @user.todos.created_after(@today-53.weeks). + select("todos.created_at, todos.completed_at"). + reorder("todos.created_at DESC") + + @max_weeks = difference_in_weeks(@today, @actions_started.last.created_at) + + # cut off chart at 52 weeks = one year + @count = [52, @max_weeks].min + + @actions_open_per_week_array = convert_to_weeks_running_from_today_array(@actions_started, @max_weeks+1) + @actions_open_per_week_array = cut_off_array(@actions_open_per_week_array, @count) + + time_labels = Array.new(@count+1){ |i| "#{i}-#{i+1}" } + time_labels[0] = "< 1" + + return { + datasets: [ + {label: I18n.t('stats.open_per_week_legend.actions'), data: @actions_open_per_week_array}, + ], + labels: time_labels, + } + end + + def day_of_week_all_data + @actions_creation_day = @user.todos.select("created_at") + @actions_completion_day = @user.todos.completed.select("completed_at") + + # convert to array and fill in non-existing days + @actions_creation_day_array = Array.new(7) { |i| 0} + @actions_creation_day.each { |t| @actions_creation_day_array[ t.created_at.wday ] += 1 } + @max = @actions_creation_day_array.max + + # convert to array and fill in non-existing days + @actions_completion_day_array = Array.new(7) { |i| 0} + @actions_completion_day.each { |t| @actions_completion_day_array[ t.completed_at.wday ] += 1 } + + return { + datasets: [ + {label: I18n.t('stats.labels.created'), data: @actions_creation_day_array}, + {label: I18n.t('stats.labels.completed'), data: @actions_completion_day_array}, + ], + labels: I18n.t('date.day_names'), + } + end + + def day_of_week_30days_data + @actions_creation_day = @user.todos.created_after(@cut_off_month).select("created_at") + @actions_completion_day = @user.todos.completed_after(@cut_off_month).select("completed_at") + + # convert to hash to be able to fill in non-existing days + @max=0 + @actions_creation_day_array = Array.new(7) { |i| 0} + @actions_creation_day.each { |r| @actions_creation_day_array[ r.created_at.wday ] += 1 } + + # convert to hash to be able to fill in non-existing days + @actions_completion_day_array = Array.new(7) { |i| 0} + @actions_completion_day.each { |r| @actions_completion_day_array[r.completed_at.wday] += 1 } + + return { + datasets: [ + {label: I18n.t('stats.labels.created'), data: @actions_creation_day_array}, + {label: I18n.t('stats.labels.completed'), data: @actions_completion_day_array}, + ], + labels: I18n.t('date.day_names'), + } + end + + def time_of_day_all_data + @actions_creation_hour = @user.todos.select("created_at") + @actions_completion_hour = @user.todos.completed.select("completed_at") + + # convert to hash to be able to fill in non-existing days + @actions_creation_hour_array = Array.new(24) { |i| 0} + @actions_creation_hour.each{|r| @actions_creation_hour_array[r.created_at.hour] += 1 } + + # convert to hash to be able to fill in non-existing days + @actions_completion_hour_array = Array.new(24) { |i| 0} + @actions_completion_hour.each{|r| @actions_completion_hour_array[r.completed_at.hour] += 1 } + + return { + datasets: [ + {label: I18n.t('stats.labels.created'), data: @actions_creation_hour_array}, + {label: I18n.t('stats.labels.completed'), data: @actions_completion_hour_array}, + ], + labels: @actions_creation_hour_array.each_with_index.map { |total, hour| [hour] }, + } + end + + def time_of_day_30days_data + @actions_creation_hour = @user.todos.created_after(@cut_off_month).select("created_at") + @actions_completion_hour = @user.todos.completed_after(@cut_off_month).select("completed_at") + + # convert to hash to be able to fill in non-existing days + @actions_creation_hour_array = Array.new(24) { |i| 0} + @actions_creation_hour.each{|r| @actions_creation_hour_array[r.created_at.hour] += 1 } + + # convert to hash to be able to fill in non-existing days + @actions_completion_hour_array = Array.new(24) { |i| 0} + @actions_completion_hour.each{|r| @actions_completion_hour_array[r.completed_at.hour] += 1 } + + return { + datasets: [ + {label: I18n.t('stats.labels.created'), data: @actions_creation_hour_array}, + {label: I18n.t('stats.labels.completed'), data: @actions_completion_hour_array}, + ], + labels: @actions_creation_hour_array.each_with_index.map { |total, hour| [hour] }, + } end private @@ -73,5 +332,107 @@ module Stats def completed @completed ||= user.todos.completed.select("completed_at, created_at") end + + def interpolate_avg_for_current_month(set) + (set[0]*(1/percent_of_month) + set[1] + set[2]) / 3.0 + end + + def percent_of_month + Time.zone.now.day / Time.zone.now.end_of_month.day.to_f + end + + # uses the supplied block to determine array of indexes in hash + # the block should return an array of indexes each is added to the hash and summed + def convert_to_array(records, upper_bound) + a = Array.new(upper_bound, 0) + records.each { |r| (yield r).each { |i| a[i] += 1 if a[i] } } + a + end + + def put_events_into_month_buckets(records, array_size, date_method_on_todo) + convert_to_array(records.select { |x| x.send(date_method_on_todo) }, array_size) { |r| [difference_in_months(@today, r.send(date_method_on_todo))]} + end + + def convert_to_days_from_today_array(records, array_size, date_method_on_todo) + return convert_to_array(records, array_size){ |r| [difference_in_days(@today, r.send(date_method_on_todo))]} + end + + def convert_to_weeks_from_today_array(records, array_size, date_method_on_todo) + return convert_to_array(records, array_size) { |r| [difference_in_weeks(@today, r.send(date_method_on_todo))]} + end + + def convert_to_weeks_running_array(records, array_size) + return convert_to_array(records, array_size) { |r| [difference_in_weeks(r.completed_at, r.created_at)]} + end + + def convert_to_weeks_running_from_today_array(records, array_size) + return convert_to_array(records, array_size) { |r| week_indexes_of(r) } + end + + def week_indexes_of(record) + a = [] + start_week = difference_in_weeks(@today, record.created_at) + end_week = record.completed_at ? difference_in_weeks(@today, record.completed_at) : 0 + end_week.upto(start_week) { |i| a << i }; + return a + end + + def cut_off_array_with_sum(array, cut_off) + # +1 to hold sum of rest + a = Array.new(cut_off+1){|i| array[i]||0} + # add rest of array to last elem + a[cut_off] += array.inject(:+) - a.inject(:+) + return a + end + + def cut_off_array(array, cut_off) + return Array.new(cut_off){|i| array[i]||0} + end + + def convert_to_cumulative_array(array, max) + # calculate fractions + a = Array.new(array.size){|i| array[i]*100.0/max} + # make cumulative + 1.upto(array.size-1){ |i| a[i] += a[i-1] } + return a + end + + def difference_in_months(date1, date2) + return (date1.utc.year - date2.utc.year)*12 + (date1.utc.month - date2.utc.month) + end + + # assumes date1 > date2 + def difference_in_days(date1, date2) + return ((date1.utc.at_midnight-date2.utc.at_midnight)/SECONDS_PER_DAY).to_i + end + + # assumes date1 > date2 + def difference_in_weeks(date1, date2) + return difference_in_days(date1, date2) / 7 + end + + def three_month_avg(set, i) + (set.fetch(i){ 0 } + set.fetch(i+1){ 0 } + set.fetch(i+2){ 0 }) / 3.0 + end + + def set_three_month_avg(set,upper_bound) + (0..upper_bound-1).map { |i| three_month_avg(set, i) } + end + + def compute_running_avg_array(set, upper_bound) + result = set_three_month_avg(set, upper_bound) + result[upper_bound-1] = result[upper_bound-1] * 3 if upper_bound == set.length + result[upper_bound-2] = result[upper_bound-2] * 3 / 2 if upper_bound > 1 and upper_bound == set.length + result[0] = "null" + result + end # unsolved, not triggered, edge case for set.length == upper_bound + 1 + + def month_label(i) + I18n.t('date.month_names')[ (Time.zone.now.mon - i -1 ) % 12 + 1 ] + end + + def array_of_month_labels(count) + Array.new(count) { |i| month_label(i) } + end end end diff --git a/app/models/stats/contexts.rb b/app/models/stats/contexts.rb index 1aa04e38..488663ca 100644 --- a/app/models/stats/contexts.rb +++ b/app/models/stats/contexts.rb @@ -13,15 +13,5 @@ module Stats def running_actions @running_actions ||= Stats::TopContextsQuery.new(user, :limit => 5, :running => true).result end - - def charts - @charts = %w{ - context_total_actions_data - context_running_actions_data - }.map do |action| - Stats::Chart.new(action, :height => 325) - end - end - end end diff --git a/app/models/stats/pie_chart_data.rb b/app/models/stats/pie_chart_data.rb deleted file mode 100644 index 9111c9b5..00000000 --- a/app/models/stats/pie_chart_data.rb +++ /dev/null @@ -1,86 +0,0 @@ -module Stats - class PieChartData - - attr_reader :all_totals, :alpha, :title - def initialize(all_totals, title, alpha) - @all_totals = all_totals - @title = title - @alpha = alpha - end - - def values - @values ||= Array.new(slices) do |i| - chart_totals[i]['total'] * 100 / sum - end - end - - def labels - @labels ||= Array.new(slices) do |i| - chart_totals[i]['name'].truncate(15, :omission => '...') - end - end - - def ids - @ids ||= Array.new(slices) do |i| - chart_totals[i]['id'] - end - end - - def sum - @sum ||= totals.inject(0) do |sum, total| - sum + total - end - end - - private - - def pie_cutoff - 10 - end - - def slices - @slices ||= [all_totals.size, pie_cutoff].min - end - - def subtotal(from, to) - totals[from..to].inject(0) do |sum, total| - sum + total - end - end - - def chart_totals - unless @chart_totals - @chart_totals = first_n_totals(10) - if all_totals.size > pie_cutoff - @chart_totals[-1] = other - end - end - @chart_totals - end - - def first_n_totals(n) - # create a duplicate so that we don't accidentally - # overwrite the original array - Array.new(slices) do |i| - { - 'name' => all_totals[i]['name'], - 'total' => all_totals[i]['total'], - 'id' => all_totals[i]['id'] - } - end - end - - def other - { - 'name' => I18n.t('stats.other_actions_label'), - 'id' => -1, - 'total' => subtotal(slices-1, all_totals.size-1) - } - end - - def totals - @totals ||= all_totals.map { |item| item['total'] } - end - - end -end diff --git a/app/views/stats/_actions.html.erb b/app/views/stats/_actions.html.erb index 7c48350b..1daf9b7f 100644 --- a/app/views/stats/_actions.html.erb +++ b/app/views/stats/_actions.html.erb @@ -1,17 +1,111 @@ <%= render :partial => 'time_to_complete', :locals => {:ttc => actions.ttc} -%> - +<% +options = { + width: "400px", + height: "400px", + maintainAspectRatio: false, + responsive: false, + plugins: { + colorschemes: { + scheme: 'brewer.Paired12', + }, + }, +} +%>

<%= t('stats.actions_actions_avg_created_30days', :count => (actions.created_last30days*10.0/30.0).round/10.0 )%> <%= t('stats.actions_avg_completed_30days', :count => (actions.done_last30days*10.0/30.0).round/10.0 )%> <%= t('stats.actions_avg_created', :count => (actions.created_last12months*10.0/12.0).round/10.0 )%> <%= t('stats.actions_avg_completed', :count => (actions.done_last12months*10.0/12.0).round/10.0 )%>

-<% actions.completion_charts.each do |chart| %><%= - render :partial => 'chart', :locals => {:chart => chart} --%><% end %> +<%= bar_chart actions.done_last30days_data, options.merge({ + scales: { + xAxes: [{ scaleLabel: { display: true, labelString: t('stats.legend.number_of_days')}}], + yAxes: [{ scaleLabel: { display: true, labelString: t('stats.legend.number_of_actions')}}], + }, + 'title': {'display': true, 'text': t('stats.actions_30days_title')}, +}) %> + +<%= bar_chart actions.done_last12months_data, options.merge({ + scales: { + xAxes: [{ scaleLabel: { display: true, labelString: t('stats.legend.months_ago')}}], + yAxes: [{ scaleLabel: { display: true, labelString: t('stats.legend.number_of_actions')}}], + }, + 'title': {'display': true, 'text': t('stats.actions_lastyear_title')}, + 'onClick': 'function() { window.location.href = "' + url_for(:controller => 'stats', :action => 'actions_done_last_years') + '"; }', + }) %> + +<% +# TODO: There should be separate scales for percentage and amount of tasks so that the max of both is in the top of the chart, ie. the left y-axis should be "Percentage". +%> +<%= bar_chart actions.completion_time_data, options.merge({ + scales: { + xAxes: [{ scaleLabel: { display: true, labelString: t('stats.legend.running_time')}}], + yAxes: [{ scaleLabel: { display: true, labelString: t('stats.legend.actions')}}], + }, + 'title': {'display': true, 'text': t('stats.action_completion_time_title')}}) %>
-<% actions.timing_charts.each do |chart| %><%= - render :partial => 'chart', :locals => {:chart => chart} --%><% end %> +<% +# TODO: There should be separate scales for percentage and amount of tasks so that the max of both is in the top of the chart, ie. the left y-axis should be "Percentage". +%> +<%= bar_chart actions.visible_running_time_data, options.merge({ + scales: { + xAxes: [{ scaleLabel: { display: true, labelString: t('stats.running_time_legend.weeks')}}], + yAxes: [{ scaleLabel: { display: true, labelString: t('stats.running_time_legend.actions')}}], + }, + 'title': {'display': true, 'text': t('stats.current_running_time_of_incomplete_visible_actions')}, + 'onClick': 'function(event, array) { window.location.href = "' + url_for(:controller => 'stats', :action => 'show_selected_actions_from_chart', :id => "avrt") + '?index=" + array[0]._index; }', +}) %> + +<% +# TODO: There should be separate scales for percentage and amount of tasks so that the max of both is in the top of the chart, ie. the left y-axis should be "Percentage". +%> +<%= bar_chart actions.running_time_data, options.merge({ + scales: { + xAxes: [{ scaleLabel: { display: true, labelString: t('stats.running_time_all_legend.running_time')}}], + yAxes: [{ scaleLabel: { display: true, labelString: t('stats.running_time_all_legend.actions')}}], + }, + 'title': {'display': true, 'text': t('stats.running_time_all')}, + 'onClick': 'function(event, array) { window.location.href = "' + url_for(:controller => 'stats', :action => 'show_selected_actions_from_chart', :id => "art") + '?index=" + array[0]._index; }', +}) %> + +
+ +<%= bar_chart actions.open_per_week_data, options.merge({ + scales: { + xAxes: [{ scaleLabel: { display: true, labelString: t('stats.open_per_week_legend.weeks')}}], + yAxes: [{ scaleLabel: { display: true, labelString: t('stats.open_per_week_legend.actions')}}], + }, + 'title': {'display': true, 'text': t('stats.open_per_week')}}) %> + +<%= bar_chart actions.day_of_week_all_data, options.merge({ + scales: { + xAxes: [{ scaleLabel: { display: true, labelString: t('stats.actions_day_of_week_legend.day_of_week')}}], + yAxes: [{ scaleLabel: { display: true, labelString: t('stats.actions_day_of_week_legend.number_of_actions')}}], + }, + 'title': {'display': true, 'text': t('stats.actions_day_of_week_title')}}) %> + +<%= bar_chart actions.day_of_week_30days_data, options.merge({ + scales: { + xAxes: [{ scaleLabel: { display: true, labelString: t('stats.actions_dow_30days_legend.day_of_week')}}], + yAxes: [{ scaleLabel: { display: true, labelString: t('stats.actions_dow_30days_legend.number_of_actions')}}], + }, + 'title': {'display': true, 'text': t('stats.actions_dow_30days_title')}}) %> + +
+ +<%= bar_chart actions.time_of_day_all_data, options.merge({ + scales: { + xAxes: [{ scaleLabel: { display: true, labelString: t('stats.time_of_day_legend.time_of_day')}}], + yAxes: [{ scaleLabel: { display: true, labelString: t('stats.time_of_day_legend.number_of_actions')}}], + }, + 'title': {'display': true, 'text': t('stats.time_of_day')}}) %> + +<%= bar_chart actions.time_of_day_30days_data, options.merge({ + scales: { + xAxes: [{ scaleLabel: { display: true, labelString: t('stats.tod30_legend.time_of_day')}}], + yAxes: [{ scaleLabel: { display: true, labelString: t('stats.tod30_legend.number_of_actions')}}], + }, + 'title': {'display': true, 'text': t('stats.tod30')}}) %> diff --git a/app/views/stats/_chart.html.erb b/app/views/stats/_chart.html.erb deleted file mode 100644 index 2281dd2e..00000000 --- a/app/views/stats/_chart.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -<% @swf_count ||= 0 -%> -
diff --git a/app/views/stats/_contexts.html.erb b/app/views/stats/_contexts.html.erb index 2f9502e1..54dfa730 100644 --- a/app/views/stats/_contexts.html.erb +++ b/app/views/stats/_contexts.html.erb @@ -1,6 +1,51 @@ -<% contexts.charts.each do |chart| %><%= - render :partial => 'chart', :locals => {:chart => chart} --%><% end %> +
+ +<% data = { + datasets: [{ + data: Array.new, + }], + labels: Array.new, + ids: Array.new, +} +Stats::TopContextsQuery.new(current_user).result.map { |context| + data[:datasets][0][:data].append(context.total) + data[:labels].append(context.name) + data[:ids].append(context.id) +} +options = { + width: "400px", + height: "400px", + maintainAspectRatio: false, + responsive: false, + plugins: { + colorschemes: { + scheme: 'brewer.Paired12', + }, + }, +} +%> +<% #TODO: Move data handling to model. Show value as percentage %> +<%= pie_chart data, options.merge({ + 'title': {'display': true, 'text': t('stats.spread_of_actions_for_all_context')}, + 'onClick': 'function(event, array) { window.location.href = "' + url_for(:controller => 'contexts', :action => 'show', :id => -1).gsub('-1', '') + '" + array[0]._chart.chart.data.ids[array[0]._index]; }' +}) %> + +<% data = { + datasets: [{ + data: Array.new, + }], + labels: Array.new, + ids: Array.new, +} +Stats::TopContextsQuery.new(current_user, :running => true).result.map { |context| + data[:datasets][0][:data].append(context.total) + data[:labels].append(context.name) + data[:ids].append(context.id) +} +%> +<%= pie_chart data, options.merge({ + 'onClick': 'function(event, array) { window.location.href = "' + url_for(:controller => 'contexts', :action => 'show', :id => -1).gsub('-1', '') + '" + array[0]._chart.chart.data.ids[array[0]._index]; }', + 'title': {'display': true, 'text': t('stats.spread_of_running_actions_for_visible_contexts')}}) %>
diff --git a/app/views/stats/actions_completion_time_data.html.erb b/app/views/stats/actions_completion_time_data.html.erb deleted file mode 100644 index c70912f0..00000000 --- a/app/views/stats/actions_completion_time_data.html.erb +++ /dev/null @@ -1,26 +0,0 @@ -<%- -time_labels = Array.new(@count){ |i| "#{i}-#{i+1}" } -time_labels[0] = t('stats.within_one') -time_labels[@count] = "> #{@count}" --%> -&title=<%= t('stats.action_completion_time_title') %>,{font-size:16},& -&y_legend=<%= t('stats.legend.actions') %>,10,0x8010A0& -&y2_legend=<%= t('stats.legend.percentage') %>,10,0xFF0000& -&x_legend=<%= t('stats.legend.running_time') %>,12,0x736AFF& -&y_ticks=5,10,5& -&filled_bar=50,0x9933CC,0x8010A0& -&values=<%= @actions_completion_time_array.join(",")%>& -&line_2=2,0xFF0000& -&values_2=<%= @cum_percent_done.join(",")%>& -&x_labels=<%= time_labels.join(",")%>& -&y_min=0& -<% -# add one to @max for people who have no actions completed yet. -# OpenFlashChart cannot handle y_max=0 --%> -&y_max=<%=1+@max_actions+@max_actions/10-%>& -&show_y2=true& -&y2_lines=2& -&y2_min=0& -&y2_max=100& -&x_label_style=9,,2,1& diff --git a/app/views/stats/actions_day_of_week_30days_data.html.erb b/app/views/stats/actions_day_of_week_30days_data.html.erb deleted file mode 100644 index 75adf7bb..00000000 --- a/app/views/stats/actions_day_of_week_30days_data.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -&title=<%= t('stats.actions_dow_30days_title') %>,{font-size:16},& -&y_legend=<%= t('stats.actions_dow_30days_legend.number_of_actions') %>,10,0x736AFF& -&x_legend=<%= t('stats.actions_dow_30days_legend.day_of_week') %>,10,0x736AFF& -&y_ticks=5,10,5& -&filled_bar=50,0x9933CC,0x8010A0,<%= t('stats.labels.created') %>,8& -&filled_bar_2=50,0x0066CC,0x0066CC,<%= t('stats.labels.completed') %>,8& -&values=<%= @actions_creation_day_array.join(",") %>& -&values_2=<%= @actions_completion_day_array.join(",") %>& -&x_labels=<%= t('date.day_names').join(",") %>& -&y_min=0& -<% - # add one to @max for people who have no actions completed yet. - # OpenFlashChart cannot handle y_max=0 --%> -&y_max=<%=@max+1 -%>& -&x_label_style=9,,2,1& \ No newline at end of file diff --git a/app/views/stats/actions_day_of_week_all_data.html.erb b/app/views/stats/actions_day_of_week_all_data.html.erb deleted file mode 100644 index 24e3ad6f..00000000 --- a/app/views/stats/actions_day_of_week_all_data.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -&title=<%= t('stats.actions_day_of_week_title') %>,{font-size:16},& -&y_legend=<%= t('stats.actions_day_of_week_legend.number_of_actions') %>,10,0x736AFF& -&x_legend=<%= t('stats.actions_day_of_week_legend.day_of_week') %>,10,0x736AFF& -&y_ticks=5,10,5& -&filled_bar=50,0x9933CC,0x8010A0,<%= t('stats.labels.created') %>,8& -&filled_bar_2=50,0x0066CC,0x0066CC,<%= t('stats.labels.completed') %>,8& -&values=<%= @actions_creation_day_array.join(",") %>& -&values_2=<%= @actions_completion_day_array.join(",") %>& -&x_labels=<%= t('date.day_names').join(",") %>& -&y_min=0& -<% - # add one to @max for people who have no actions completed yet. - # OpenFlashChart cannot handle y_max=0 --%> -&y_max=<%=@max+1 -%>& -&x_label_style=9,,2,1& \ No newline at end of file diff --git a/app/views/stats/actions_done_last12months_data.html.erb b/app/views/stats/actions_done_last12months_data.html.erb deleted file mode 100644 index c6ca9176..00000000 --- a/app/views/stats/actions_done_last12months_data.html.erb +++ /dev/null @@ -1,31 +0,0 @@ -<%- - url = url_for :controller => 'stats', :action => 'actions_done_last_years' --%> -&title=<%= t('stats.actions_lastyear_title') %>,{font-size:16},& -&y_legend=<%= t('stats.legend.number_of_actions') %>,12,0x736AFF& -&x_legend=<%= t('stats.legend.months_ago') %>,12,0x736AFF& -&y_ticks=5,10,5& -&filled_bar=50,0x9933CC,0x8010A0,<%= t('stats.labels.created')%>,9& -&filled_bar_2=50,0x0066CC,0x0066CC,<%= t('stats.labels.completed') %>,9& -&line_3=2,0x00FF00, <%= t('stats.labels.avg_created') %>, 9& -&line_4=2,0xFF0000, <%= t('stats.labels.avg_completed') %>, 9& -&line_5=2,0x007700, <%= t('stats.labels.month_avg_created', :months => 3) %>, 9& -&line_6=2,0xAA0000, <%= t('stats.labels.month_avg_completed', :months => 3) %>, 9& -&line_7=1,0xAA0000& -&line_8=1,0x007700& -&values=<%= @actions_created_last12months_array.join(",")%>& -&links=<%= Array.new(13,url).join(",") %>& -&links_2=<%= Array.new(13,url).join(",") %>& -&values_2=<%= @actions_done_last12months_array.join(",")%>& -&values_3=<%= @created_count_array.join(",")%>& -&values_4=<%= @done_count_array.join(",")%>& -&values_5=<%= @actions_created_avg_last12months_array.join(",")%>& -&values_6=<%= @actions_done_avg_last12months_array.join(",")%>& -&values_7=<%= @interpolated_actions_created_this_month%>,<%=@actions_done_avg_last12months_array[1]%>& -&values_8=<%= @interpolated_actions_done_this_month%>,<%=@actions_created_avg_last12months_array[1]%>& -&x_labels=<%= array_of_month_labels(@done_count_array.size).join(",")%>& -&y_min=0& -<% # add one to @max for people who have no actions completed yet. - # OpenFlashChart cannot handle y_max=0 -%> -&y_max=<%=@max+@max/10+1-%>& -&x_label_style=9,,2,& diff --git a/app/views/stats/actions_done_last30days_data.html.erb b/app/views/stats/actions_done_last30days_data.html.erb deleted file mode 100644 index 11991146..00000000 --- a/app/views/stats/actions_done_last30days_data.html.erb +++ /dev/null @@ -1,26 +0,0 @@ -<%- -created_count_array = Array.new(30){ |i| @actions_created_last30days.size/30.0 } -done_count_array = Array.new(30){ |i| @actions_done_last30days.size/30.0 } -# TODO: make the strftime i18n proof -time_labels = Array.new(30){ |i| l(Time.zone.now-i.days, :format => :stats) } --%> -&title=<%= t('stats.actions_30days_title') %>,{font-size:16},& -&y_legend=<%= t('stats.legend.number_of_actions') %>,12,0x736AFF& -&x_legend=<%= t('stats.legend.number_of_days') %>,12,0x736AFF& -&y_ticks=5,10,5& -&filled_bar=50,0x9933CC,0x8010A0,<%= t('stats.labels.created') %>,9& -&filled_bar_2=50,0x0066CC,0x0066CC,<%= t('stats.labels.completed') %>,9& -&line_3=3,0x00FF00, <%= t('stats.labels.avg_created') %>, 9& -&line_4=3,0xFF0000, <%= t('stats.labels.avg_completed') %>, 9& -&values=<%= @actions_created_last30days_array.join(",")%>& -&values_2=<%= @actions_done_last30days_array.join(",")%>& -&values_3=<%= created_count_array.join(",")%>& -&values_4=<%= done_count_array.join(",")%>& -&x_labels=<%= time_labels.join(",")%>& -&y_min=0& -<% # max + 10% for some extra space at the top - # add one to @max for people who have no actions completed yet. - # OpenFlashChart cannot handle y_max=0 --%> -&y_max=<%=@max+@max/10+1 -%>& -&x_label_style=9,,2,3& \ No newline at end of file diff --git a/app/views/stats/actions_open_per_week_data.html.erb b/app/views/stats/actions_open_per_week_data.html.erb deleted file mode 100644 index e9e93bed..00000000 --- a/app/views/stats/actions_open_per_week_data.html.erb +++ /dev/null @@ -1,18 +0,0 @@ -<%- -time_labels = Array.new(@count+1){ |i| "#{i}-#{i+1}" } -time_labels[0] = "< 1" --%> -&title=<%= t('stats.open_per_week') %>,{font-size:16},& -&y_legend=<%= t('stats.open_per_week_legend.actions') %>,10,0x736AFF& -&x_legend=<%= t('stats.open_per_week_legend.weeks') %>,11,0x736AFF& -&y_ticks=5,10,5& -&filled_bar=50,0x9933CC,0x8010A0& -&values=<%= @actions_open_per_week_array.join(",") -%>& -&x_labels=<%= time_labels.join(",")%>& -&y_min=0& -<% - # add one to @max for people who have no actions completed yet. - # OpenFlashChart cannot handle y_max=0 --%> -&y_max=<%=1+@max_actions+@max_actions/10-%>& -&x_label_style=9,,2,2& \ No newline at end of file diff --git a/app/views/stats/actions_running_time_data.html.erb b/app/views/stats/actions_running_time_data.html.erb deleted file mode 100644 index 6126b31a..00000000 --- a/app/views/stats/actions_running_time_data.html.erb +++ /dev/null @@ -1,30 +0,0 @@ -<%- -url_labels = Array.new(@count){ |i| url_for(:controller => 'stats', :action => 'show_selected_actions_from_chart', :index => i, :id=> "art") } -url_labels[@count]=url_for(:controller => 'stats', :action => 'show_selected_actions_from_chart', :index => @count, :id=> "art_end") - -time_labels = Array.new(@count){ |i| "#{i}-#{i+1}" } -time_labels[0] = "< 1" -time_labels[@count] = "> #{@count}" --%> -&title=<%= t('stats.running_time_all') %>,{font-size:16},& -&y_legend=<%= t('stats.running_time_all_legend.actions') %>,10,0x736AFF& -&y2_legend=<%= t('stats.running_time_all_legend.percentage') %>,10,0xFF0000& -&x_legend=<%= t('stats.running_time_all_legend.running_time') %>,11,0x736AFF& -&y_ticks=5,10,5& -&filled_bar=50,0x9933CC,0x8010A0& -&values=<%= @actions_running_time_array.join(",") -%>& -&links=<%= url_labels.join(",") %>& -&line_2=2,0xFF0000& -&values_2=<%= @cum_percent_done.join(",") %>& -&x_labels=<%= time_labels.join(",") %> & -&y_min=0& -<% - # add one to @max for people who have no actions completed yet. - # OpenFlashChart cannot handle y_max=0 --%> -&y_max=<%=1+@max_actions+@max_actions/10-%>& -&x_label_style=9,,2,2& -&show_y2=true& -&y2_lines=2& -&y2_min=0& -&y2_max=100& diff --git a/app/views/stats/actions_time_of_day_30days_data.html.erb b/app/views/stats/actions_time_of_day_30days_data.html.erb deleted file mode 100644 index 49f6fa48..00000000 --- a/app/views/stats/actions_time_of_day_30days_data.html.erb +++ /dev/null @@ -1,23 +0,0 @@ -&title=<%= t('stats.tod30') %>,{font-size:16},& -&y_legend=<%= t('stats.tod30_legend.number_of_actions') %>,12,0x736AFF& -&x_legend=<%= t('stats.tod30_legend.time_of_day') %>,12,0x736AFF& -&y_ticks=5,10,5& -&filled_bar=50,0x9933CC,0x8010A0,<%= t('stats.labels.created') %>,8& -&filled_bar_2=50,0x0066CC,0x0066CC,<%= t('stats.labels.completed') %>,8& -&values=<% -0.upto 22 do |i| -%> - <%=@actions_creation_hour_array[i] -%>, -<% end -%><%=@actions_creation_hour_array[23]%>& -&values_2=<% -0.upto 22 do |i| -%> - <%=@actions_completion_hour_array[i] -%>, -<% end -%><%=@actions_completion_hour_array[23]%>& -&x_labels= <% -0.upto 22 do |i| -%> - <%=i-%>, -<% end -%>23& -&y_min=0& -<% # add one to @max for people who have no actions completed yet. - # OpenFlashChart cannot handle y_max=0 -%> -&y_max=<%=@max+1 -%>& -&x_label_style=9,,1,1& diff --git a/app/views/stats/actions_time_of_day_all_data.html.erb b/app/views/stats/actions_time_of_day_all_data.html.erb deleted file mode 100644 index 4abb52e9..00000000 --- a/app/views/stats/actions_time_of_day_all_data.html.erb +++ /dev/null @@ -1,23 +0,0 @@ -&title=<%= t('stats.time_of_day') %>,{font-size:16},& -&y_legend=<%= t('stats.time_of_day_legend.number_of_actions') %>,12,0x736AFF& -&x_legend=<%= t('stats.time_of_day_legend.time_of_day') %>,12,0x736AFF& -&y_ticks=5,10,5& -&filled_bar=50,0x9933CC,0x8010A0,<%= t('stats.labels.created') %>,8& -&filled_bar_2=50,0x0066CC,0x0066CC,<%= t('stats.labels.completed') %>,8& -&values=<% -0.upto 22 do |i| -%> - <%=@actions_creation_hour_array[i] -%>, -<% end -%><%=@actions_creation_hour_array[23]%>& -&values_2=<% -0.upto 22 do |i| -%> - <%=@actions_completion_hour_array[i] -%>, -<% end -%><%=@actions_completion_hour_array[23]%>& -&x_labels= <% -0.upto 22 do |i| -%> - <%=i-%>, -<% end -%>23& -&y_min=0& -<% # add one to @max for people who have no actions completed yet. - # OpenFlashChart cannot handle y_max=0 -%> -&y_max=<%=@max+1 -%>& -&x_label_style=9,,1,1& diff --git a/app/views/stats/actions_visible_running_time_data.html.erb b/app/views/stats/actions_visible_running_time_data.html.erb deleted file mode 100644 index c68969ec..00000000 --- a/app/views/stats/actions_visible_running_time_data.html.erb +++ /dev/null @@ -1,30 +0,0 @@ -<%- -url_labels = Array.new(@count){ |i| url_for(:controller => 'stats', :action => 'show_selected_actions_from_chart', :index => i, :id=> "avrt") } -url_labels[@count]=url_for(:controller => 'stats', :action => 'show_selected_actions_from_chart', :index => @count, :id=> "avrt_end") - -time_labels = Array.new(@count){ |i| "#{i}-#{i+1}" } -time_labels[0] = "< 1" -time_labels[@count] = "> #{@count}" --%> -&title=<%= t('stats.current_running_time_of_incomplete_visible_actions') %>,{font-size:16},& -&y_legend=<%= t('stats.running_time_legend.actions') %>,10,0x736AFF& -&y2_legend=<%= t('stats.running_time_legend.percentage') %>,10,0xFF0000& -&x_legend=<%= t('stats.running_time_legend.weeks') %>,11,0x736AFF& -&y_ticks=5,10,5& -&filled_bar=50,0x9933CC,0x8010A0& -&values=<%= @actions_running_time_array.join(",") -%>& -&links=<%= url_labels.join(",") %>& -&line_2=2,0xFF0000& -&values_2=<%= @cum_percent_done.join(",") -%>& -&x_labels=<%= time_labels.join(",")%>& -&y_min=0& -<% - # add one to @max for people who have no actions completed yet. - # OpenFlashChart cannot handle y_max=0 --%> -&y_max=<%=1+@max_actions+@max_actions/10-%>& -&x_label_style=9,,2,2& -&show_y2=true& -&y2_lines=2& -&y2_min=0& -&y2_max=100& diff --git a/app/views/stats/index.html.erb b/app/views/stats/index.html.erb index ebb780fa..44c4f458 100644 --- a/app/views/stats/index.html.erb +++ b/app/views/stats/index.html.erb @@ -1,5 +1,3 @@ -<%= javascript_include_tag "swf_fu" %> -

<%= t('stats.totals') %>

diff --git a/app/views/stats/pie_chart_data.html.erb b/app/views/stats/pie_chart_data.html.erb deleted file mode 100644 index 31beb727..00000000 --- a/app/views/stats/pie_chart_data.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -&title=<%= @data.title %>,{font-size:16}& -&pie=<%= @data.alpha %>,#505050,{font-size: 12px; color: #404040;}& -&x_axis_steps=1& &y_ticks=5,10,5& &line=3,#87421F& &y_min=0& &y_max=20& -&values=<%= @data.values.join(",") %>& -&pie_labels=<%= @data.labels.join(",") %>& -&links=<%= @data.ids.map{|id| context_path(id)}.join(",") %>& -&colours=#d01f3c,#356aa0,#C79810,#c61fd0,#1fc6d0,#1fd076,#72d01f,#c6d01f,#d0941f,#40941f& -&tool_tip=#x_label#: #val#%25& -&x_label_style=9,,2,1& diff --git a/app/views/stats/show_selection_from_chart.html.erb b/app/views/stats/show_selection_from_chart.html.erb index 80b40306..29e9dfdb 100644 --- a/app/views/stats/show_selection_from_chart.html.erb +++ b/app/views/stats/show_selection_from_chart.html.erb @@ -1,7 +1,5 @@ -<%= render :partial => 'chart', :locals => {:chart => @chart} -%> -

-<%= t('stats.click_to_update_actions') %> <%= raw t('stats.click_to_return', :link => link_to(t('stats.click_to_return_link'), stats_path)) %> +<%= raw t('stats.click_to_return', :link => link_to(t('stats.click_to_return_link'), stats_path)) %> <% unless @further -%> diff --git a/test/controllers/context_actions_data_test.rb b/test/controllers/context_actions_data_test.rb deleted file mode 100644 index 0bcaae6a..00000000 --- a/test/controllers/context_actions_data_test.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'test_helper' - -class ContextActionsDataTest < ActionController::TestCase - tests StatsController - - def test_total_with_more_than_10_items - login_as(:admin_user) - contexts = [ - {'id' => 1, 'name' => 'one', 'total' => 11}, - {'id' => 2, 'name' => 'two', 'total' => 4}, - {'id' => 3, 'name' => 'three', 'total' => 8} - ] - Stats::TopContextsQuery.any_instance.stubs(:result).returns contexts - - get :context_total_actions_data - - assert_equal [47, 17, 34], assigns[:data].values - end - - def test_running_actions - login_as(:admin_user) - contexts = [ - {'id' => 1, 'name' => 'one', 'total' => 11}, - {'id' => 2, 'name' => 'two', 'total' => 4}, - {'id' => 3, 'name' => 'three', 'total' => 8} - ] - Stats::TopContextsQuery.any_instance.stubs(:result).returns contexts - - get :context_running_actions_data - - assert_equal [47, 17, 34], assigns[:data].values - end - -end diff --git a/test/controllers/stats_controller_test.rb b/test/controllers/stats_controller_test.rb index 85ef0f8d..74edf489 100644 --- a/test/controllers/stats_controller_test.rb +++ b/test/controllers/stats_controller_test.rb @@ -1,5 +1,6 @@ require 'test_helper' +# TODO: Add more detailed testing of the charts. There are previously defined tests in VCS before the Flash to Chart.js change. class StatsControllerTest < ActionController::TestCase def test_get_index_when_not_logged_in @@ -13,35 +14,6 @@ class StatsControllerTest < ActionController::TestCase assert_response :success end - def test_get_charts - login_as(:admin_user) - %w{ - actions_done_last30days_data - actions_done_last12months_data - actions_completion_time_data - actions_visible_running_time_data - actions_running_time_data - actions_open_per_week_data - actions_day_of_week_all_data - actions_day_of_week_30days_data - actions_time_of_day_all_data - actions_time_of_day_30days_data - }.each do |action| - get action - assert_response :success - assert_template "stats/"+action - end - - %w{ - context_total_actions_data - context_running_actions_data - }.each do |action| - get action - assert_response :success - assert_template "stats/pie_chart_data" - end - end - def test_totals login_as(:admin_user) get :index @@ -102,300 +74,6 @@ class StatsControllerTest < ActionController::TestCase assert_response :success end - def test_actions_done_last12months_data - travel_to Time.local(2013, 1, 15) do - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - - given_todos_for_stats - - # When I get the chart data - get :actions_done_last12months_data - assert_response :success - - # Then the todos for the chart should be retrieved - #assert_not_nil assigns['actions_done_last12months'] - #assert_not_nil assigns['actions_created_last12months'] - #assert_equal 7, assigns['actions_created_last12months'].count, "very old todo should not be retrieved" - - # And they should be totalled in a hash - assert_equal 2, assigns['actions_created_last12months_array'][0], "there should be two todos in current month" - - assert_equal 1, assigns['actions_created_last12months_array'][1], "there should be one todo in previous month" - assert_equal 1, assigns['actions_created_last12months_array'][2], "there should be one todo in two month ago" - assert_equal 1, assigns['actions_created_last12months_array'][3], "there should be one todo in three month ago" - assert_equal 2, assigns['actions_created_last12months_array'][4], "there should be two todos (1 created & 1 done) in four month ago" - - assert_equal 1, assigns['actions_done_last12months_array'][1], "there should be one completed todo one-two months ago" - assert_equal 1, assigns['actions_done_last12months_array'][2], "there should be one completed todo two-three months ago" - assert_equal 1, assigns['actions_done_last12months_array'][4], "there should be one completed todo four-five months ago" - - # And they should be averaged over three months - assert_equal 2/3.0, assigns['actions_done_avg_last12months_array'][1], "fourth month should be excluded" - assert_equal 2/3.0, assigns['actions_done_avg_last12months_array'][2], "fourth month should be included" - - assert_equal (3)/3.0, assigns['actions_created_avg_last12months_array'][1], "one every month" - assert_equal (4)/3.0, assigns['actions_created_avg_last12months_array'][2], "two in fourth month" - - # And the current month should be interpolated - fraction = Time.zone.now.day.to_f / Time.zone.now.end_of_month.day.to_f - assert_equal (2*(1/fraction)+2)/3.0, assigns['interpolated_actions_created_this_month'], "two this month and one in the last two months" - assert_equal (2)/3.0, assigns['interpolated_actions_done_this_month'], "none this month and one two the last two months" - - # And totals should be calculated - assert_equal 2, assigns['max'], "max of created or completed todos in one month" - end - end - - def test_empty_last12months_data - travel_to Time.local(2013, 1, 15) do - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - given_todos_for_stats - get :actions_done_last12months_data - assert_response :success - end - end - - def test_out_of_bounds_events_for_last12months_data - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - create_todo_in_past(2.years) - create_todo_in_past(15.months) - - get :actions_done_last12months_data - assert_response :success - end - - def test_actions_done_last30days_data - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - - given_todos_for_stats - - # When I get the chart data - get :actions_done_last30days_data - assert_response :success - - # only tests relevant differences with actions_done_last_12months_data - - assert_equal 31, assigns['actions_done_last30days_array'].size, "30 complete days plus 1 for the current day" - assert_equal 2, assigns['max'], "two actions created on one day is max" - end - - def test_actions_done_lastyears_data - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - - given_todos_for_stats - - # When I get the chart data - get :actions_done_lastyears_data - assert_response :success - - # only tests difference with actions_done_last_12months_data - - # And the last two months are corrected - assert_equal 2/3.0, assigns['actions_done_avg_last_months_array'][23] - assert_equal 2/3.0, assigns['actions_done_avg_last_months_array'][24] - end - - def test_actions_completion_time_data - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - - given_todos_for_stats - - # When I get the chart data - get :actions_completion_time_data - assert_response :success - - # do not test stuff already implicitly tested in other tests - assert_equal 104, assigns['max_weeks'], "two years is 104 weeks (for completed_at)" - assert_equal 3, assigns['max_actions'], "3 completed within one week" - assert_equal 11, assigns['actions_completion_time_array'].size, "there should be 10 weeks of data + 1 for the rest" - assert_equal 1, assigns['actions_completion_time_array'][10], "there is one completed todo after the 10 weeks cut_off" - assert_equal 100.0, assigns['cum_percent_done'][10], "cumulative percentage should add up to 100%" - end - - def test_actions_running_time_data - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - - given_todos_for_stats - - # When I get the chart data - get :actions_running_time_data - assert_response :success - - # do not test stuff already implicitly tested in other tests - assert_equal 17, assigns['max_weeks'], "there are actions in the first 17 weeks of this year" - assert_equal 2, assigns['max_actions'], "2 actions running long together" - assert_equal 18, assigns['actions_running_time_array'].size, "there should be 17 weeks ( < cut_off) of data + 1 for the rest" - assert_equal 1, assigns['actions_running_time_array'][17], "there is one running todos in week 17 and zero after 17 weeks ( < cut off; ) " - assert_equal 100.0, assigns['cum_percent_done'][17], "cumulative percentage should add up to 100%" - end - - def test_actions_open_per_week_data - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - - given_todos_for_stats - - # When I get the chart data - get :actions_open_per_week_data - assert_response :success - - # do not test stuff already implicitly tested in other tests - assert_equal 17, assigns['max_weeks'], "there are actions in the first 17 weeks of this year" - assert_equal 4, assigns['max_actions'], "4 actions running together" - assert_equal 17, assigns['actions_open_per_week_array'].size, "there should be 17 weeks ( < cut_off) of data" - end - - def test_actions_visible_running_time_data - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - - given_todos_for_stats - # Given todo1 is deferred (i.e. not visible) - @todo_today1.show_from = Time.zone.now + 1.week - @todo_today1.save - - # When I get the chart data - get :actions_visible_running_time_data - assert_response :success - - # do not test stuff already implicitly tested in other tests - assert_equal 17, assigns['max_weeks'], "there are actions in the first 17 weeks of this year" - assert_equal 1, assigns['max_actions'], "1 action running long; 1 is deferred" - assert_equal 1, assigns['actions_running_time_array'][0], "there is one running todos and one deferred todo created in week 1" - assert_equal 18, assigns['actions_running_time_array'].size, "there should be 17 weeks ( < cut_off) of data + 1 for the rest" - assert_equal 1, assigns['actions_running_time_array'][17], "there is one running todos in week 17 and zero after 17 weeks ( < cut off; ) " - assert_equal 100.0, assigns['cum_percent_done'][17], "cumulative percentage should add up to 100%" - end - - def test_context_total_actions_data - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - - given_todos_for_stats - - # When I get the chart data - get :context_total_actions_data - assert_response :success - - assert_equal 9, assigns['data'].sum, "Nine todos in 1 context" - assert_equal 1, assigns['data'].values.size - - # Given 10 more todos in 10 different contexts - 1.upto(10) do |i| - context = @current_user.contexts.create!(:name => "context #{i}") - @current_user.todos.create!(:description => "created today with new context #{i}", :context => context) - end - - # When I get the chart data - get :context_total_actions_data - assert_response :success - - assert_equal 19, assigns['data'].sum, "added 10 todos" - assert_equal 10, assigns['data'].values.size, "pie slices limited to max 10" - assert_equal 10, assigns['data'].values[9], "pie slices limited to max 10; last pie contains sum of rest (in percentage)" - assert_equal "(others)", assigns['data'].labels[9], "pie slices limited to max 10; last slice contains label for others" - end - - def test_context_running_actions_data - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - - given_todos_for_stats - - # When I get the chart data - get :context_running_actions_data - assert_response :success - - assert_equal 4, assigns['data'].sum, "Four todos in 1 context" - assert_equal 1, assigns['data'].values.size - - # Given 10 more todos in 10 different contexts - 1.upto(10) do |i| - context = @current_user.contexts.create!(:name => "context #{i}") - @current_user.todos.create!(:description => "created today with new context #{i}", :context => context) - end - - # When I get the chart data - get :context_running_actions_data - assert_response :success - - assert_equal 10, assigns['data'].values.size, "pie slices limited to max 10" - assert_equal 14, assigns['data'].values[9], "pie slices limited to max 10; last pie contains sum of rest (in percentage)" - assert_equal "(others)", assigns['data'].labels[9], "pie slices limited to max 10; last slice contains label for others" - end - - def test_actions_day_of_week_all_data - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - - given_todos_for_stats - - # When I get the chart data - get :actions_day_of_week_all_data - assert_response :success - - # FIXME: testdata is relative from today, so not stable to test on day_of_week - # trivial not_nil tests - assert_not_nil assigns['max'] - assert_not_nil assigns['actions_creation_day_array'] - assert_not_nil assigns['actions_completion_day_array'] - end - - def test_actions_day_of_week_30days_data - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - - given_todos_for_stats - - # When I get the chart data - get :actions_day_of_week_30days_data - assert_response :success - - # FIXME: testdata is relative from today, so not stable to test on day_of_week - # trivial not_nil tests - assert_not_nil assigns['max'] - assert_not_nil assigns['actions_creation_day_array'] - assert_not_nil assigns['actions_completion_day_array'] - end - - def test_actions_time_of_day_all_data - login_as(:admin_user) - @current_user = User.find(users(:admin_user).id) - @current_user.todos.delete_all - - given_todos_for_stats - - # When I get the chart data - get :actions_time_of_day_all_data - assert_response :success - - # FIXME: testdata is relative from today, so not stable to test on day_of_week - # for now just trivial not_nil tests - assert_not_nil assigns['max'] - assert_not_nil assigns['actions_creation_hour_array'] - assert_not_nil assigns['actions_completion_hour_array'] - end - def test_show_selected_actions_from_chart_avrt login_as(:admin_user) @current_user = User.find(users(:admin_user).id) diff --git a/test/models/pie_chart_data_test.rb b/test/models/pie_chart_data_test.rb deleted file mode 100644 index e50c8db0..00000000 --- a/test/models/pie_chart_data_test.rb +++ /dev/null @@ -1,78 +0,0 @@ -require 'minimal_test_helper' -require 'app/models/stats/pie_chart_data' -require 'active_support/core_ext/string' - -class Stats::PieChartDataTest < Minitest::Test - - def test_with_0_items - data = Stats::PieChartData.new([], 'a chart', 50) - - assert_equal [], data.values - assert_equal [], data.labels - assert_equal [], data.ids - end - - def test_with_less_than_10_items - items = [ - {'id' => 1, 'name' => 'one', 'total' => 11}, - {'id' => 2, 'name' => 'two', 'total' => 4}, - {'id' => 3, 'name' => 'three', 'total' => 8}, - {'id' => 4, 'name' => 'four', 'total' => 13}, - {'id' => 5, 'name' => 'five', 'total' => 20}, - {'id' => 6, 'name' => 'six', 'total' => 17}, - {'id' => 7, 'name' => 'seven', 'total' => 5}, - {'id' => 8, 'name' => 'eight', 'total' => 1}, - {'id' => 9, 'name' => 'nine', 'total' => 6} - ] - - data = Stats::PieChartData.new(items, 'a chart', 50) - - assert_equal [12, 4, 9, 15, 23, 20, 5, 1, 7], data.values - assert_equal ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"], data.labels - assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9], data.ids - end - - def test_with_exactly_10_items - items = [ - {'id' => 1, 'name' => 'one', 'total' => 11}, - {'id' => 2, 'name' => 'two', 'total' => 4}, - {'id' => 3, 'name' => 'three', 'total' => 8}, - {'id' => 4, 'name' => 'four', 'total' => 13}, - {'id' => 5, 'name' => 'five', 'total' => 20}, - {'id' => 6, 'name' => 'six', 'total' => 17}, - {'id' => 7, 'name' => 'seven', 'total' => 5}, - {'id' => 8, 'name' => 'eight', 'total' => 1}, - {'id' => 9, 'name' => 'nine', 'total' => 6}, - {'id' => 10, 'name' => 'ten', 'total' => 19} - ] - - data = Stats::PieChartData.new(items, 'a chart', 50) - - assert_equal [10, 3, 7, 12, 19, 16, 4, 0, 5, 18], data.values - assert_equal ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"], data.labels - assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], data.ids - end - - def test_with_more_than_10_items - items = [ - {'id' => 1, 'name' => 'one', 'total' => 11}, - {'id' => 2, 'name' => 'two', 'total' => 4}, - {'id' => 3, 'name' => 'three', 'total' => 8}, - {'id' => 4, 'name' => 'four', 'total' => 13}, - {'id' => 5, 'name' => 'five', 'total' => 20}, - {'id' => 6, 'name' => 'six', 'total' => 17}, - {'id' => 7, 'name' => 'seven', 'total' => 5}, - {'id' => 8, 'name' => 'eight', 'total' => 1}, - {'id' => 9, 'name' => 'nine', 'total' => 6}, - {'id' => 10, 'name' => 'ten', 'total' => 19}, - {'id' => 11, 'name' => 'eleven', 'total' => 14} - ] - - data = Stats::PieChartData.new(items, 'a chart', 50) - - assert_equal [9, 3, 6, 11, 16, 14, 4, 0, 5, 27], data.values - assert_equal ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "(others)"], data.labels - assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, -1], data.ids - end - -end