diff --git a/Gemfile b/Gemfile index c0e12cb6c..d239d1449 100644 --- a/Gemfile +++ b/Gemfile @@ -42,6 +42,8 @@ gem 'rack-attack' gem 'google_drive' +gem 'lazy_high_charts' + group :development do gem 'web-console' gem 'spring' diff --git a/Gemfile.lock b/Gemfile.lock index 0a315411a..42549af8a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -125,6 +125,7 @@ GEM haml (>= 4.0.6, < 6.0) html2haml (>= 1.0.1) railties (>= 4.0.1) + hash-deep-merge (0.1.1) highline (1.7.8) html2haml (2.2.0) erubis (~> 2.7.0) @@ -155,6 +156,8 @@ GEM kramdown (1.15.0) launchy (2.4.3) addressable (~> 2.3) + lazy_high_charts (1.5.8) + hash-deep-merge listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -390,6 +393,7 @@ DEPENDENCIES jquery-rails koala kramdown + lazy_high_charts listen minitest-retry pg diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 950acf152..1132b5d81 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -16,4 +16,7 @@ //= require scrivito_section_widgets //= require scrivito //= require bootstrap-sprockets +//= require highcharts/highcharts +//= require highcharts/highcharts-more +//= require highcharts/highstock //= require_tree . diff --git a/app/controllers/static_pages_controller.rb b/app/controllers/static_pages_controller.rb index e59d786a3..c0a4a495b 100644 --- a/app/controllers/static_pages_controller.rb +++ b/app/controllers/static_pages_controller.rb @@ -32,6 +32,10 @@ def stats EventHistory.where(evented_at: Time.zone.local(year).beginning_of_year..Time.zone.local(year).end_of_year).sum(:participants) end + + @annual_dojos_chart = HighChartsBuilder.build_annual_dojos + @annual_event_histories_chart = HighChartsBuilder.build_annual_event_histories + @annual_participants_chart = HighChartsBuilder.build_annual_participants end def letsencrypt diff --git a/app/models/high_charts_builder.rb b/app/models/high_charts_builder.rb new file mode 100644 index 000000000..c6b847c6b --- /dev/null +++ b/app/models/high_charts_builder.rb @@ -0,0 +1,72 @@ +class HighChartsBuilder + class << self + def build_annual_dojos + source = Dojo.where('created_at < ?', Time.current.beginning_of_year).group("DATE_TRUNC('year', created_at)").count + data = annual_chart_data_from(source) + + LazyHighCharts::HighChart.new('graph') do |f| + f.title(text: '全国の道場数の推移') + f.xAxis(categories: data[:years]) + f.series(type: 'column', name: '増加数', yAxis: 0, data: data[:increase_nums]) + f.series(type: 'line', name: '累積合計', yAxis: 1, data: data[:cumulative_sums]) + f.yAxis [ + { title: { text: '増加数' } }, + { title: { text: '累積合計' }, opposite: true } + ] + f.chart(width: 600) + f.colors(["#A0D3B5", "#505D6B"]) + end + end + + def build_annual_event_histories + source = EventHistory.where('evented_at < ?', Time.current.beginning_of_year).group("DATE_TRUNC('year', evented_at)").count + data = annual_chart_data_from(source) + + LazyHighCharts::HighChart.new('graph') do |f| + f.title(text: '開催回数の推移') + f.xAxis(categories: data[:years]) + f.series(type: 'column', name: '開催回数', yAxis: 0, data: data[:increase_nums]) + f.series(type: 'line', name: '累積合計', yAxis: 1, data: data[:cumulative_sums]) + f.yAxis [ + { title: { text: '開催回数' } }, + { title: { text: '累積合計' }, opposite: true } + ] + f.chart(width: 600) + f.colors(["#F4C34F", "#BD2561"]) + end + end + + def build_annual_participants + source = EventHistory.where('evented_at < ?', Time.current.beginning_of_year).group("DATE_TRUNC('year', evented_at)").sum(:participants) + data = annual_chart_data_from(source) + + LazyHighCharts::HighChart.new('graph') do |f| + f.title(text: '参加者数の推移') + f.xAxis(categories: data[:years]) + f.series(type: 'column', name: '参加者数', yAxis: 0, data: data[:increase_nums]) + f.series(type: 'line', name: '累積合計', yAxis: 1, data: data[:cumulative_sums]) + f.yAxis [ + { title: { text: '参加者数' } }, + { title: { text: '累積合計' }, opposite: true } + ] + f.chart(width: 600) + f.colors(["#EF685E", "#35637D"]) + end + end + + private + + def annual_chart_data_from(source) + sorted_list = source.each.with_object({}) {|(k, v), h| h[k.year] = v }.sort + years = sorted_list.map(&:first) + increase_nums = sorted_list.map(&:last) + cumulative_sums = increase_nums.size.times.map {|i| increase_nums[0..i].inject(:+) } + + { + years: years, + increase_nums: increase_nums, + cumulative_sums: cumulative_sums + } + end + end +end diff --git a/app/views/static_pages/stats.html.haml b/app/views/static_pages/stats.html.haml index 6d898ad09..03c50561e 100644 --- a/app/views/static_pages/stats.html.haml +++ b/app/views/static_pages/stats.html.haml @@ -9,19 +9,6 @@ %p 本ページでは全国の CoderDojo の統計情報をまとめています。 CoderDojo の活動状況を把握する際などにご活用ください。 - %h3 全国の道場 - #accordion.panel-group{"aria-multiselectable" => "true", :role => "tablist"} - - @regions_and_dojos.each_with_index do |(region, dojos), index| - .panel.panel-default - .panel-heading{:id => "heading#{index}", :role => "tab"} - %h4.panel-title - %a{"data-parent" => "#accordion", "data-toggle" => "collapse", :href => "##{"collapse#{index}"}", :role => "button"} - %i.fa.fa-chevron-right{"aria-hidden" => "true"} - = region - \- #{dojos.count} Dojos - .panel-collapse.collapse{:id => "collapse#{index}", :role => "tabpanel"} - .panel-body.grayscale-bg - = render partial: 'dojo', collection: dojos %h3 開催回数 = @sum_of_events 回 @@ -60,6 +47,22 @@ - @range.each do |year| %td= @participants[year] %td= @participants.values.inject(:+) + = high_chart("annual_dojos", @annual_dojos_chart) + = high_chart("annual_event_histories", @annual_event_histories_chart) + = high_chart("annual_participants", @annual_participants_chart) + %h3 全国の道場 + #accordion.panel-group{"aria-multiselectable" => "true", :role => "tablist"} + - @regions_and_dojos.each_with_index do |(region, dojos), index| + .panel.panel-default + .panel-heading{:id => "heading#{index}", :role => "tab"} + %h4.panel-title + %a{"data-parent" => "#accordion", "data-toggle" => "collapse", :href => "##{"collapse#{index}"}", :role => "button"} + %i.fa.fa-chevron-right{"aria-hidden" => "true"} + = region + \- #{dojos.count} Dojos + .panel-collapse.collapse{:id => "collapse#{index}", :role => "tabpanel"} + .panel-body.grayscale-bg + = render partial: 'dojo', collection: dojos %h3 関連リンク %ul{:style => "list-style: none; margin-left: -40px;"}