image

  • フォト Amazonギフト券
    ※この時計の時刻は、閲覧しているパソコンのものであり、必ずしも正確な時間とは限りません

検索

最近のトラックバック

無料ブログはココログ

« 2008年12月31日 | トップページ | 2009年1月2日 »

2009年1月1日

2009-01-01

GanttProject のデータを ruby で パースしてみた

HappyMapper をつかって GanttProject のデータファイル(xml形式) をパースして、csv に変換させてみた。
出力書式を csv 形式にしたが、プログラム上では ファイル内容は ruby の object に変換できているので、各種の出力形式に変形させるのは簡単だ。
# xfy/xvcd で ganttproject データを表示/編集できるようにしたいとも思っている。

この作業を通じて、GanttProject の XML データ構造もほぼ 理解できたし、HappyMapper の内部もだいぶ 理解できた。
# freemind のデータや XBRL のインスタンスデータも、 happymapper で十分に扱えそうだ。
# parse した結果の Object を to_yaml して、memcached や、RDB に保持すると面白いかもしれない。

以下にソースコードと、実行例を示す。
# niffty の homepage にもファイル群を upload してある。
# See - http://homepage2.nifty.com/youichi_kato/src.html
#          ganttproject データの解析(2009-01-01)

$ cat ganttproject.rb

# 2009-01-02 katoy
# ganttproject の xml データを happymapper で解釈する。
#     happymapper (0.1.2)
#    ganttroject 2.0.9
#
# happymapper には、次のパッチを当てる
#   - root エレメントを解釈できるようにする。 (:deep の扱い)
#   - 再帰構造を解釈できるようにする          (:deep の扱い)
#
# *** happymapper-0.1.2-org/lib/happymapper.rb2009-01-01 16:29:34.000000000 +0900
# --- happymapper-0.1.2/lib/happymapper.rb2009-01-01 16:49:23.000000000 +0900
# ***************
# *** 62,67 ****
# --- 62,68 ----
#   def parse(xml, o={})
#         options = {
#           :single => false,
# +         :deep => true,
#           :use_default_namespace => false,
#     }.merge(o)
#         
# ***************
# *** 73,79 ****
#          node.register_default_namespace(namespace.chop)
#     node.find("#{ namespace}#{get_tag_name}")
#         else
# !         doc.find(get_tag_name)
#         end
#         
#         collection = create_collection(nodes, namespace)
# --- 74,84 ----
#           node.register_default_namespace(namespace.chop)
#   node.find("#{ namespace}#{ get_tag_name}")
#         else
# !         if options[:deep]
# !           doc.find("//#{  get_tag_name}")
# !         else
# !           doc.find("./#{  get_tag_name}")
# !         end
#         end
#

require 'rubygems'
require 'happymapper'
require 'pp'

$KCODE = 'utf8'

module GANTT_PROJECT

  class Field
    include HappyMapper

    tag "field"
    attribute :id, String
    attribute :name, String
    attribute :width, Integer
    attribute :order, Integer
  end

  class View
    include HappyMapper

    tag  "view"
    attribute :id, String
    element :field, Field
  end

  class DayType
    include HappyMapper

    tag  "day-type"
    attribute :id, String
  end

  class Calendar
    include HappyMapper

    tag  "calendar"
    attribute :id, String
    attribute :name, String
#    has_one :default_week, DefaultWeek
#    has_one :overriden_day_types, overrideDayTypes
#    has_one :days, Days
  end

  class DayTypes
    include HappyMapper

    tag  "day-types"
    has_many :dayType, DayType
    has_one :calendar, Calendar
  end

  class DateStr
    include HappyMapper

    tag  "date"
    attribute :year, String
    attribute :month, String
    attribute :date, String
  end

  class Calendars
    include HappyMapper

    tag  "calendars"
    has_many :date, DateStr
    has_one :day_types, DayTypes
  end

  class Depend
    include HappyMapper

    tag  "depend"
    attribute :id, String
    attribute :type, String
    attribute :difference, String
    attribute :hardness, String
  end

  class Task
    include HappyMapper

    tag  "task"
    attribute :id, String
    attribute :name, String
    attribute :color, String
    attribute :meeting, String
    attribute :start, Date
    attribute :duration, Integer
    attribute :complete, Integer
    attribute :priority, Integer
    attribute :expand, String
    has_many :task, Task, :deep => false
    has_many :depend, Depend

    def print(nest = 0)
      puts "#{'    ' * nest}id=#{id} name=[#{name}]"

      self.task.each do |t|
        t.print(nest + 1)
      end
    end

  end

  class TaskProperty
    include HappyMapper

    tag  "taskproperty"
    attribute :id, String
    attribute :name, String
    attribute :type, String
    attribute :valuetype, String
  end

  class Tasks
    include HappyMapper

    tag  "tasks"
    attribute :color, String
    has_many :taskproperties, TaskProperty
    has_many :task, Task, :deep => false
  end

  class Resource
    include HappyMapper

    tag  "resource"
    attribute :id, String
    attribute :name, String
    attribute :function, String
    attribute :contacts, String
    attribute :phone, String
  end

  class Resources
    include HappyMapper

    tag  "resources"
    has_many :resource, Resource
  end

  class Allocation
    include HappyMapper

    tag  "allocation"
    attribute :task_id, String, :tag=>"task-id"
    attribute :resource_id, String, :tag=>"resource-id"
    attribute :function, String
    attribute :responsible, String
    attribute :load, String
  end

  class Allocations
    include HappyMapper

    tag  "allocations"
    has_many :allocation, Allocation
  end

  class Role
    include HappyMapper

    tag  "role"
    attribute :id, String
    attribute :name, String
  end

  class Roles
    include HappyMapper

    tag  "roles"
    attribute :rolesetName, String
    has_many :roles, Role
  end

  class Project
    include HappyMapper

    tag  "project"
    attribute :name, String
    attribute :company, String
    has_many :view, View
    has_one :description, String
    has_one :calendars, Calendars
    has_one :tasks, Tasks
    has_one :allocations, Allocations
    has_one :resources, Resources
  end

end

if __FILE__ == $0

  GANT_FILE = 'g.xml'
  file_contents = File.read(GANT_FILE)

  proj = GANTT_PROJECT::Project.parse(file_contents, :single => true)

  proj.tasks.task.each do |t|
    t.print
  end

  pp proj.view
  pp proj.calendars
  pp proj.allocations
  pp proj.resources
end

$ gant2csv.rb

# 2009-01-02 katoy
# ganttproject のファイルから、csv 形式を得る。

require "ganttproject"

# resource.id -> name の Hash
@person_name = { }

def make_person_name_info (res)
  res.resource.each do |r|
    @person_name[r.id] = r.name
  end
end

def search_persons(allocs, id)
  p_names = []
  allocs.allocation.each do |a|
    if id == a.task_id
      p_names << @person_name[a.resource_id]
    end
  end
  p_names
end

def csv_task (task, allocs, nest = 1)
  # finish = start + task.duration
  start = task.start.strftime("%y/%m/%d")
  peoples = search_persons(allocs, task.id)

  puts "#{task.id},\"#{' ' * nest}#{task.name}\",#{start},#{task.duration},#{task.complete},\"\",\"#{peoples}\",\"\","
  task.task.each do |t|
    csv_task(t, allocs, nest + 1)
  end
end

GANT_FILE = 'g.xml'
file_contents = File.read(GANT_FILE)
proj = GANTT_PROJECT::Project.parse(file_contents, :single => true)

make_person_name_info(proj.resources)

puts "ID,名前,開始日,期間,進捗,ウェブリンク,リソース,メモ,"
proj.tasks.task.each do |t|
  csv_task(t, proj.allocations)
end

puts

puts "ID,名前,e-mail,電話番号,役割,"
proj.resources.resource.each do |r|
  puts "#{r.id},\"#{r.name}\",\"#{r.contacts}\",\"#{r.phone}\",\"#{r.function}\","
end

$ cat g.xml   // ganttproject の download ファイル中にあるサンプルデータを整形、改名したもの

<?xml version="1.0" encoding="UTF-8"?>
<project name="My house building project" company="Myself LLC"
    webLink="www.myselfllc.net" view-date="2006-01-01" view-index="0"
    gantt-divider-location="369" resource-divider-location="322" version="2.0">
    <description>xxx</description>
    <view zooming-state="default:6" id="gantt-chart" />
    <view id="resource-table">
        <field id="0" name="名前" width="54" order="0" />
        <field id="1" name="役割" width="45" order="0" />
    </view>
    <!-- -->
    <calendars>
        <day-types>
            <day-type id="0" />
            <day-type id="1" />
            <calendar id="1" name="default">
                <default-week sun="1" mon="0" tue="0" wed="0" thu="0"
                    fri="0" sat="1" />
                <overriden-day-types />
                <days />
            </calendar>
        </day-types>
        <date year="2006" month="2" date="14" />
    </calendars>
    <tasks color="#99ccff">
        <taskproperties>
            <taskproperty id="tpd0" name="type" type="default"
                valuetype="icon" />
            <taskproperty id="tpd1" name="priority" type="default"
                valuetype="icon" />
            <taskproperty id="tpd2" name="info" type="default"
                valuetype="icon" />
            <taskproperty id="tpd3" name="name" type="default"
                valuetype="text" />
            <taskproperty id="tpd4" name="begindate" type="default"
                valuetype="date" />
            <taskproperty id="tpd5" name="enddate" type="default"
                valuetype="date" />
            <taskproperty id="tpd6" name="duration" type="default"
                valuetype="int" />
            <taskproperty id="tpd7" name="completion" type="default"
                valuetype="int" />
            <taskproperty id="tpd8" name="coordinator" type="default"
                valuetype="text" />
            <taskproperty id="tpd9" name="predecessorsr" type="default"
                valuetype="text" />
        </taskproperties>
        <task id="0" name="Architectural design" color="#99ccff" meeting="false"
            start="2006-01-09" duration="26" complete="75" priority="1" expand="true">
            <task id="9" name="Create draft of architecture" color="#99ccff"
                meeting="false" start="2006-01-09" duration="10" complete="100"
                priority="1" expand="true">
                <depend id="10" type="2" difference="0" hardness="Strong" />
                <depend id="12" type="2" difference="0" hardness="Strong" />
            </task>
            <task id="10" name="Prepare construction documents" color="#99ccff"
                meeting="false" start="2006-01-23" duration="15" complete="65"
                priority="1" expand="true">
                <depend id="17" type="2" difference="0" hardness="Strong" />
            </task>
            <task id="17" name="Agreement on architectural plan " color="#000000"
                meeting="true" start="2006-02-13" duration="1" complete="0"
                priority="1" expand="true">
                <depend id="1" type="2" difference="0" hardness="Strong" />
            </task>
        </task>
        <task id="11" name="Interior design" color="#99ccff" meeting="false"
            start="2006-01-23" duration="10" complete="33" priority="1" expand="true">
            <depend id="6" type="2" difference="0" hardness="Strong" />
            <task id="12" name="Pre-design" color="#99ccff" meeting="false"
                start="2006-01-23" duration="5" complete="100" priority="1" expand="true">
                <depend id="13" type="2" difference="0" hardness="Strong" />
                <depend id="14" type="2" difference="0" hardness="Strong" />
            </task>
            <task id="13" name="Furniture selection" color="#99ccff"
                meeting="false" start="2006-01-30" duration="5" complete="0"
                priority="1" expand="true" />
            <task id="14" name="Equipment planning" color="#99ccff" meeting="false"
                start="2006-01-30" duration="5" complete="0" priority="1" expand="true">
                <notes><![CDATA[Embedded devices, kitchen, washing machine, dryer etc]]></notes>
            </task>
        </task>
        <task id="7" name="Construction phase" color="#99ccff" meeting="false"
            start="2006-02-15" duration="76" complete="0" priority="1" expand="true">
            <depend id="20" type="2" difference="0" hardness="Strong" />
            <task id="1" name="Foundation building" color="#99ccff" meeting="false"
                start="2006-02-15" duration="15" complete="0" priority="1" expand="false">
                <depend id="2" type="2" difference="0" hardness="Strong" />
            </task>
            <task id="2" name="Ground Floor building" color="#99ccff"
                meeting="false" start="2006-03-08" duration="20" complete="0"
                priority="1" expand="false">
                <depend id="4" type="2" difference="0" hardness="Strong" />
            </task>
            <task id="4" name="First Floor building" color="#99ccff"
                meeting="false" start="2006-04-05" duration="20" complete="0"
                priority="1" expand="false">
                <depend id="5" type="2" difference="0" hardness="Strong" />
            </task>
            <task id="5" name="Roof" color="#99ccff" meeting="false" start="2006-05-03"
                duration="10" complete="0" priority="1" expand="false">
                <depend id="18" type="2" difference="0" hardness="Strong" />
            </task>
            <task id="16" name="Connect to communications" color="#99ccff"
                meeting="false" start="2006-05-18" duration="10" complete="0"
                priority="1" expand="true" />
            <task id="18" name="Construction completed " color="#000000"
                meeting="true" start="2006-05-17" duration="1" complete="0"
                priority="1" expand="true">
                <depend id="6" type="2" difference="0" hardness="Strong" />
                <depend id="16" type="2" difference="0" hardness="Strong" />
            </task>
        </task>
        <task id="8" name="Decoration phase" color="#99ccff" meeting="false"
            start="2006-05-18" duration="11" complete="0" priority="1" expand="true">
            <task id="6" name="Walls" color="#99ccff" meeting="false" start="2006-05-18"
                duration="5" complete="0" priority="1" expand="false">
                <depend id="15" type="2" difference="0" hardness="Strong" />
            </task>
            <task id="15" name="Furniture" color="#99ccff" meeting="false"
                start="2006-05-25" duration="3" complete="0" priority="1" expand="true">
                <depend id="20" type="2" difference="0" hardness="Strong" />
            </task>
            <task id="20" name="Bring your family here" color="#000000"
                meeting="true" start="2006-06-01" duration="1" complete="0"
                priority="1" expand="true" />
        </task>
    </tasks>
    <resources>
        <resource id="1" name="Jack House" function="Default:1"
            contacts="jack.house@myselfllc.net" phone="0044 077345456" />
        <resource id="0" name="John Black" function="4"
            contacts="john.black@myselfllc.net" phone="+44 0794353567" />
        <resource id="2" name="Michelangelo" function="0"
            contacts="mickelangelo@heaven.net" phone="078 9059056" />
        <resource id="3" name="Tom White" function="1"
            contacts="tom.white@myselfllc.net" phone="07978978978" />
        <resource id="4" name="Peter Green" function="1"
            contacts="peter.green@myselfllc.net" phone="0797897856" />
        <resource id="5" name="George Brown" function="1"
            contacts="george.brown@myselfllc.net" phone="07967766447" />
        <resource id="6" name="John Silver" function="2"
            contacts="john.silver@myselfllc.net" phone="07778967889" />
    </resources>
    <allocations>
        <allocation task-id="9" resource-id="1" function="Default:1"
            responsible="false" load="50.0" />
        <allocation task-id="9" resource-id="2" function="0"
            responsible="true" load="100.0" />
        <allocation task-id="10" resource-id="2" function="0"
            responsible="true" load="100.0" />
        <allocation task-id="12" resource-id="1" function="Default:1"
            responsible="true" load="100.0" />
        <allocation task-id="12" resource-id="2" function="0"
            responsible="false" load="50.0" />
        <allocation task-id="13" resource-id="1" function="Default:1"
            responsible="true" load="100.0" />
        <allocation task-id="14" resource-id="1" function="Default:1"
            responsible="true" load="50.0" />
        <allocation task-id="14" resource-id="2" function="0"
            responsible="false" load="50.0" />
        <allocation task-id="1" resource-id="0" function="4"
            responsible="false" load="100.0" />
        <allocation task-id="1" resource-id="5" function="1"
            responsible="false" load="100.0" />
        <allocation task-id="1" resource-id="3" function="1"
            responsible="false" load="100.0" />
        <allocation task-id="1" resource-id="6" function="2"
            responsible="true" load="100.0" />
        <allocation task-id="2" resource-id="5" function="1"
            responsible="false" load="100.0" />
        <allocation task-id="2" resource-id="3" function="1"
            responsible="false" load="100.0" />
        <allocation task-id="2" resource-id="4" function="1"
            responsible="false" load="100.0" />
        <allocation task-id="2" resource-id="6" function="2"
            responsible="true" load="100.0" />
        <allocation task-id="4" resource-id="5" function="1"
            responsible="false" load="100.0" />
        <allocation task-id="4" resource-id="3" function="1"
            responsible="false" load="100.0" />
        <allocation task-id="4" resource-id="4" function="1"
            responsible="false" load="100.0" />
        <allocation task-id="4" resource-id="6" function="2"
            responsible="true" load="100.0" />
        <allocation task-id="5" resource-id="3" function="5"
            responsible="false" load="100.0" />
        <allocation task-id="5" resource-id="6" function="2"
            responsible="true" load="100.0" />
        <allocation task-id="16" resource-id="0" function="4"
            responsible="true" load="100.0" />
        <allocation task-id="16" resource-id="4" function="1"
            responsible="false" load="100.0" />
        <allocation task-id="6" resource-id="5" function="1"
            responsible="false" load="100.0" />
        <allocation task-id="6" resource-id="3" function="1"
            responsible="false" load="100.0" />
        <allocation task-id="6" resource-id="4" function="1"
            responsible="false" load="100.0" />
        <allocation task-id="6" resource-id="6" function="2"
            responsible="true" load="100.0" />
        <allocation task-id="15" resource-id="1" function="Default:1"
            responsible="true" load="100.0" />
        <allocation task-id="15" resource-id="3" function="1"
            responsible="false" load="100.0" />
    </allocations>
    <vacations />
    <taskdisplaycolumns>
        <displaycolumn property-id="tpd3" order="0" width="117" />
        <displaycolumn property-id="tpd4" order="1" width="92" />
        <displaycolumn property-id="tpd5" order="2" width="90" />
    </taskdisplaycolumns>
    <previous />
    <roles roleset-name="Default" />
    <roles>
        <role id="0" name="Architect" />
        <role id="1" name="Bricklayer" />
        <role id="2" name="Foreman" />
        <role id="3" name="Decorator" />
        <role id="4" name="Excavator operator" />
        <role id="5" name="Roofer" />
    </roles>
</project>

$ ruby gant2csv
ID,名前,開始日,期間,進捗,ウェブリンク,リソース,メモ,
0," Architectural design",06/01/09,26,75,"","","",
9,"  Create draft of architecture",06/01/09,10,100,"","Jack HouseMichelangelo","",
10,"  Prepare construction documents",06/01/23,15,65,"","Michelangelo","",
17,"  Agreement on architectural plan ",06/02/13,1,0,"","","",
11," Interior design",06/01/23,10,33,"","","",
12,"  Pre-design",06/01/23,5,100,"","Jack HouseMichelangelo","",
13,"  Furniture selection",06/01/30,5,0,"","Jack House","",
14,"  Equipment planning",06/01/30,5,0,"","Jack HouseMichelangelo","",
7," Construction phase",06/02/15,76,0,"","","",
1,"  Foundation building",06/02/15,15,0,"","John BlackGeorge BrownTom WhiteJohn Silver","",
2,"  Ground Floor building",06/03/08,20,0,"","George BrownTom WhitePeter GreenJohn Silver","",
4,"  First Floor building",06/04/05,20,0,"","George BrownTom WhitePeter GreenJohn Silver","",
5,"  Roof",06/05/03,10,0,"","Tom WhiteJohn Silver","",
16,"  Connect to communications",06/05/18,10,0,"","John BlackPeter Green","",
18,"  Construction completed ",06/05/17,1,0,"","","",
8," Decoration phase",06/05/18,11,0,"","","",
6,"  Walls",06/05/18,5,0,"","George BrownTom WhitePeter GreenJohn Silver","",
15,"  Furniture",06/05/25,3,0,"","Jack HouseTom White","",
20,"  Bring your family here",06/06/01,1,0,"","","",

ID,名前,e-mail,電話番号,役割,
1,"Jack House","jack.house@myselfllc.net","0044 077345456","Default:1",
0,"John Black","john.black@myselfllc.net","+44 0794353567","4",
2,"Michelangelo","mickelangelo@heaven.net","078 9059056","0",
3,"Tom White","tom.white@myselfllc.net","07978978978","1",
4,"Peter Green","peter.green@myselfllc.net","0797897856","1",
5,"George Brown","george.brown@myselfllc.net","07967766447","1",
6,"John Silver","john.silver@myselfllc.net","07778967889","2",

ピックアップ:今年1年間でHDDやmicroSDメモリカードはどれだけ値下がりしたのか、離婚 ともさかりえ, etc...

- http://yebo-blog.blogspot.com/2008/12/cuil.html
> yebo blog: 検索エンジンCuilが失速

- http://blog.programmableweb.com/2008/12/29/opensocial-java-php-python-and-ruby-libraries-released/
> OpenSocial Java, PHP, Python, and Ruby Libraries Released

- http://blog.livedoor.jp/geek/archives/50785956.html
> コミックマーケット75 秋葉原の「コミケ紙袋」 景気悪化の影響か - アキバBlog

- http://gigazine.net/index.php?/news/comments/20081231_pricedown/
> 今年1年間でHDDやmicroSDメモリカードはどれだけ値下がりしたのか? - GIGAZINE

- http://d.hatena.ne.jp/Siliqua_alta/20081230/1230646251
> 「他社より安くします」チラシのホントの理由(再掲) - Cahier de Siliqua_alta

> ... このサービスはもともと、価格を下げるためではなく、価格を高値で保つためのカルテルの手段としてアメリカで考案されたもの...

- http://ameblo.jp/tomosaka-rie/entry-10185585547.html
> 離婚|ともさかりえ オフィシャルブログ Powered by Ameba

- http://slashdot.jp/it/article.pl?sid=08/12/30/1321216
> スラッシュドット・ジャパン | Michael Meeks氏曰く、OpenOffice.orgプロジェクトは「極めて病んでいる」状態

- http://jp.techcrunch.com/archives/20081230md5-collision-creates-rogue-certificate-authority/
> MD5コリジョンでインチキ認証局は作れる(ネットにとっては悪い報せ)

- http://flowingdata.com/2008/12/19/5-best-data-visualization-projects-of-the-year/
> 5 Best Data Visualization Projects of the Year | FlowingData

- http://www.nicovideo.jp/watch/sm5702737
> アメリカ人のラーメンの作り方が凄すぎでワロタwww‐ニコニコ動画(ββ)

« 2008年12月31日 | トップページ | 2009年1月2日 »

mokuji

2013年12月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

google

  • twitter
  • __
  • _
    Googleボットチェッカー

合わせて読む

  • 合わせて読む
    フィードメーター - katoy: cocolog あわせて読みたい

リンク