- 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にライブラリを配置した。
/javascripts/calendar/calendar.js /javascripts/calendar/lang/calendar-ja.js /javascripts/calendar/calendar-setup.js <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]>/plugin_assets/redmine_daizu/javascripts/html5jp/excanvas/excanvas.js<![endif]--> /plugin_assets/redmine_daizu/javascripts/html5jp/graph/circle.js <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すると・・・

おおお!できましたね!!!