- NetBeans6.5で作ります。
- ソースはGoogle Codeを参照のこと。
- redmineは「c:\fujihara\Ruby\redmine-0.8.0」にあって、WEBrickを使って動かす。
ValueObject
表示用データを格納するValueObjectをplugin_root/app/libに作成。
Main
# To change this template, choose Tools | Templates # and open the template in the editor. class TimeReportMainVO TRACKER_SUM_STRING = "合計" def initialize @project_name = "" #FIXME @trackers = Hash.new() all_trackers = Tracker.find(:all) all_trackers.each do |tracker| @trackers[tracker.name] = TimeReportDetailVO.new() end @trackers[TRACKER_SUM_STRING] = TimeReportDetailVO.new() end def get_tracker(name) return trackers[name] end def put_tracker(name, value) trackers[name] = value end attr_accessor :project_name, :trackers end
Main has Detailになっている。
Detail
# To change this template, choose Tools | Templates # and open the template in the editor. class TimeReportDetailVO def initialize @estimated_hours = 0.0 @actual_performances = 0.0 @percentages = 0.0 end attr_accessor :estimated_hours, :actual_performances, :percentages end
Controller
ControllerではVOに計算したデータを格納する。
daizu_time_report_controller.rb
require 'logger' require 'time_report_detail_v_o' require 'time_report_main_v_o' class DaizuTimeReportController < ApplicationController before_filter :init TRACKER_SUM_STRING = "合計" def index if @project_id && @start_date && @due_date # counting per tracker. # counting estimated_hours and time_entries and percentages. @results = [] if @project_id == "all" @projects.each do |project| calc_per_project(project) end all_sumvo = calc_allsum(@results) @results.push(all_sumvo) else project = Project.find(:first, :conditions => ["id = ?", @project_id]) calc_per_project(project) end end end def calc_per_project(project) # per project. mainvo = TimeReportMainVO.new() mainvo.project_name = project.name issues = Issue.find(:all, :conditions => ["start_date >= ? and due_date <= ? and project_id = ?", @start_date, @due_date, project.id]) mainvo = count_per_tracker(issues, mainvo) mainvo = calc_percentages(mainvo) @results.push(mainvo) end def count_per_tracker(issues, mainvo) sumvo = mainvo.get_tracker(TRACKER_SUM_STRING) # counting per project and per tracker. issues.each do |issue| tracker_name = @trakcer_names[issue.tracker_id] detailvo = mainvo.get_tracker(tracker_name) # counting estimated_hours. detailvo.estimated_hours += issue.estimated_hours sumvo.estimated_hours += issue.estimated_hours # counting time_entries. time_entry = TimeEntry.find(:all, :conditions => ["issue_id = ?", issue.id]) time_entry.each do |entry| detailvo.actual_performances += entry.hours sumvo.actual_performances += entry.hours end mainvo.put_tracker(tracker_name, detailvo) end mainvo.put_tracker(TRACKER_SUM_STRING, sumvo) return mainvo end def calc_percentages(mainvo) mainvo.trackers.each do |key, detailvo| detailvo.percentages = calc_percentage(detailvo.estimated_hours, detailvo.actual_performances) mainvo.put_tracker(key, detailvo) end return mainvo end def calc_percentage(estimated_hours, actual_performances) if estimated_hours != 0 && actual_performances != 0 percentage = (actual_performances / estimated_hours) * 100 percentage = percentage * 100 percentage = percentage.round percentage = percentage / 100 return percentage else return 0.0 end end def calc_allsum(results) sumvo = TimeReportMainVO.new() sumvo.project_name = TRACKER_SUM_STRING results.each do |result| result.trackers.each do |tracker_name, detailvo| detailsumvo = sumvo.get_tracker(tracker_name) detailsumvo.estimated_hours += detailvo.estimated_hours detailsumvo.actual_performances += detailvo.actual_performances sumvo.put_tracker(tracker_name, detailsumvo) end end sumvo.trackers.each do |tracker_name, tracker| detailsumvo = sumvo.get_tracker(tracker_name) detailsumvo.percentages = calc_percentage(detailsumvo.estimated_hours, detailsumvo.actual_performances) end return sumvo end def init @log = Logger.new(STDOUT) @log.level = Logger::DEBUG @project_id = params[:project_id] @start_date = params[:start_date] @due_date = params[:due_date] @projects = Project.find :all @trackers = Tracker.find(:all) @trackers.push(Tracker.new(:name => TRACKER_SUM_STRING)) @trakcer_names = {} @trackers.each do |tracker| @trakcer_names[tracker.id] = tracker.name end end end
View
グラフで表示するためにHTML5.JPのライブラリを利用。
plugin_root/app/assets/javascripts/html5jpにライブラリを配置した。
<script src="/javascripts/calendar/calendar.js" type="text/javascript"></script> <script src="/javascripts/calendar/lang/calendar-ja.js" type="text/javascript"></script> <script src="/javascripts/calendar/calendar-setup.js" type="text/javascript"></script> <link href="/stylesheets/calendar.css" media="screen" rel="stylesheet" type="text/css" /> <h2><%= link_to h('大豆トップページ'), :controller => 'daizu_main', :action => 'index' %> > タイムレポート</h2> <% form_tag({ :controller => 'daizu_time_report', :action => 'index' }, :id => 'query_form') do %> <p><label for="project_id">プロジェクト</label> <select name="project_id"> <option value="all">全てのプロジェクト</option> <% @projects.each do |project| %> <option value="<%= project.id %>"><%= project.name %></option> <% end %> </select> <p><label for="issue_start_date">開始日</label> <input id="issue_start_date" name="start_date" size="15" type="text" value="<%= params[:start_date] %>" /> <img alt="Calendar" class="calendar-trigger" id="issue_start_date_trigger" src="/images/calendar.png" /> <script type="text/javascript"> //<![CDATA[ Calendar.setup({inputField : 'issue_start_date', ifFormat : '%Y-%m-%d', button : 'issue_start_date_trigger' }); //]]> </script></p> <p><label for="issue_due_date">期限日</label> <input id="issue_due_date" name="due_date" size="15" type="text" value="<%= params[:due_date] %>" /> <img alt="Calendar" class="calendar-trigger" id="issue_due_date_trigger" src="/images/calendar.png" /> <script type="text/javascript"> //<![CDATA[ Calendar.setup({inputField : 'issue_due_date', ifFormat : '%Y-%m-%d', button : 'issue_due_date_trigger' }); //]]> </script></p> <button type="submit">GO</button> <% end %> <% if @results %> <p>[from:<%= params[:start_date] %> to:<%= params[:due_date] %>] のタイムレポート。</p> <table class="list"> <tr> <th></th> <% @trackers.each do |tracker| %> <th colspan="3" ><%= tracker.name %></th> <% end %> </tr> <tr> <th></th> <% @trackers.each do |tracker| %> <th>予想</th> <th>実績</th> <th>進捗</th> <% end %> </tr> <% @results.each do |result| %> <tr> <th><%= result.project_name %></th> <% @trackers.each do |tracker| %> <td><%= result.get_tracker(tracker.name).estimated_hours %></td> <td><%= result.get_tracker(tracker.name).actual_performances %></td> <td> <table class="progress" style="width: 40px;"> <tr> <% if result.get_tracker(tracker.name).percentages == 0 %> <td class="todo" style="width:100%;"></td> <% elsif result.get_tracker(tracker.name).percentages == 100 %> <td class="closed" style="width:100%;"></td> <% elsif result.get_tracker(tracker.name).percentages > 100 %> <td style="width:100%;background-color:red;"></td> <% else %> <td class="closed" style="<%= "width:" + result.get_tracker(tracker.name).percentages.to_s + "%;" %>"></td> <td class="todo" style="<%= "width:" + (100 - result.get_tracker(tracker.name).percentages).to_s + "%;" %>"></td> <% end %> </tr> </table> <p class="pourcent"><%= result.get_tracker(tracker.name).percentages.to_s %>%</p> </td> <% end %> </tr> <% end %> </table> <% if params[:project_id] != "all" %> <% @results.each do |result| %> <h3><%= result.project_name %>の統計情報</h3> <!--[if IE]><script src="/plugin_assets/redmine_daizu/javascripts/html5jp/excanvas/excanvas.js" type="text/javascript"></script><![endif]--> <script src="/plugin_assets/redmine_daizu/javascripts/html5jp/graph/circle.js" type="text/javascript"></script> <script type="text/javascript"> window.onload = function() { var cg = new html5jp.graph.circle("yosou"); if( ! cg ) { return; } var items = [ <% @trackers.each do |tracker| %> <% if tracker.name != "合計" %> <% if result.get_tracker(tracker.name).actual_performances != 0.0 %> ["<%=tracker.name%>", <%= result.get_tracker(tracker.name).actual_performances %>], <% end %> <% end %> <% end %> ]; cg.draw(items); var cg = new html5jp.graph.circle("jisseki"); if( ! cg ) { return; } var items = [ <% @trackers.each do |tracker| %> <% if tracker.name != "合計" %> <% if result.get_tracker(tracker.name).estimated_hours != 0.0 %> ["<%=tracker.name%>", <%= result.get_tracker(tracker.name).estimated_hours %>], <% end %> <% end %> <% end %> ]; cg.draw(items); }; </script> <table> <tr> <td> <h4>予想</h4> <div> <canvas width="300" height="200" id="yosou"></canvas> </div> </td> <td> <h4>実績</h4> <div> <canvas width="300" height="200" id="jisseki"></canvas> </div> </td> </tr> </table> <% end %> <% end %> <% end %>
できあがりのイメージ
画面で値を設定してSubumitすると・・・
おおお!できましたね!!!