cards 0.7 → 0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +9 -0
- data/README.txt +1 -1
- data/Rakefile +7 -1
- data/examples/csv to dot/generate_card_walls +3 -3
- data/examples/custom csv builder/Stories.csv +16 -0
- data/examples/custom csv builder/Stories.tracker.csv +29 -0
- data/examples/custom csv builder/generate_card_wall +31 -0
- data/examples/excel to visio/Business Processes.xls +0 -0
- data/examples/excel to visio/TPS-small.png +0 -0
- data/examples/excel to visio/generate card walls.rb +10 -0
- data/examples/excel to visio/readme.html +104 -0
- data/examples/importing into tracker api/Stories.csv +16 -0
- data/examples/importing into tracker api/Voting Example.numbers +0 -0
- data/examples/importing into tracker api/appscript_example.rb +18 -0
- data/examples/importing into tracker api/from_numbers_09 +50 -0
- data/examples/importing into tracker api/generate_card_wall +32 -0
- data/examples/importing into tracker api/osa.rb +39 -0
- data/examples/numbers to omnigraffle/Voting Example.numbers +0 -0
- data/examples/numbers to omnigraffle/generate_card_walls +11 -9
- data/lib/cards.rb +3 -1
- data/lib/cards/csv_builder.rb +36 -34
- data/lib/cards/csv_parser.rb +6 -44
- data/lib/cards/numbers_parser.rb +43 -0
- data/lib/cards/swim_lanes.rb +1 -0
- data/lib/cards/tabular_parser.rb +78 -0
- data/lib/cards/tracker_csv.rb +15 -13
- data/lib/cards/writers/dot_writer.rb +6 -2
- data/spec/cards/csv_parser_spec.rb +22 -4
- data/spec/cards/numbers_parser_spec.rb +25 -0
- data/spec/fixtures/Voting Example.numbers +0 -0
- metadata +37 -17
- data/Manifest.txt +0 -40
- data/examples/csv to dot/Stories.dot +0 -63
- data/examples/numbers to omnigraffle/Voting Example.numbers/Contents/PkgInfo +0 -1
- data/examples/numbers to omnigraffle/Voting Example.numbers/QuickLook/Thumbnail.jpg +0 -0
- data/examples/numbers to omnigraffle/Voting Example.numbers/document-thumbnail.tiff +0 -0
- data/examples/numbers to omnigraffle/Voting Example.numbers/index.xml.gz +0 -0
- data/examples/numbers to omnigraffle/Voting Example/Cards-Goals.csv +0 -7
- data/examples/numbers to omnigraffle/Voting Example/Cards-Stories.csv +0 -16
- data/examples/numbers to omnigraffle/Voting Example/Cards-Workflow.csv +0 -7
data/CHANGES.txt
CHANGED
data/README.txt
CHANGED
data/Rakefile
CHANGED
@@ -11,7 +11,7 @@ require 'hoe'
|
|
11
11
|
require 'lib/cards'
|
12
12
|
|
13
13
|
desc "Default Task"
|
14
|
-
task :default => [:spec]
|
14
|
+
task :default => [:generate_manifest, :spec]
|
15
15
|
|
16
16
|
task :test => :spec
|
17
17
|
|
@@ -19,6 +19,12 @@ Spec::Rake::SpecTask.new(:spec) do |t|
|
|
19
19
|
t.spec_files = FileList['spec/**/*_spec.rb']
|
20
20
|
end
|
21
21
|
|
22
|
+
task :generate_manifest do
|
23
|
+
File.open("Manifest.txt", "w") do |f|
|
24
|
+
f << FileList["CHANGES.txt", "Rakefile", "README.txt", "examples/**/*", "lib/**/*", "spec/**/*"].to_a.join("\n")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
22
28
|
desc "export to dot file"
|
23
29
|
task :run_dot do
|
24
30
|
file = ENV["FILE"] || SAMPLE_FILE
|
@@ -1,10 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
2
|
require 'rubygems'
|
3
|
+
gem 'cards'
|
4
4
|
require 'cards'
|
5
|
-
|
6
5
|
include Cards
|
7
6
|
|
7
|
+
|
8
8
|
def csv_file(name)
|
9
9
|
CsvParser.new(File.dirname(__FILE__) + "/#{name}.csv")
|
10
10
|
end
|
@@ -22,4 +22,4 @@ end
|
|
22
22
|
puts "generated Stories.dot"
|
23
23
|
|
24
24
|
# uncomment this line if you want to see the generated file
|
25
|
-
# `open "#{File.dirname(__FILE__)}/Stories.dot"`
|
25
|
+
# `open "#{File.dirname(__FILE__)}/Stories.dot"`
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Activity,Task,Story,Note,Estimate,Priority
|
2
|
+
Voter,Vote on question,Ability to see question,,1,H
|
3
|
+
,,Ability to see choices,,1,M
|
4
|
+
,,Ability to choose,This is the server trip,2,H
|
5
|
+
,Navigate questions,Ability to continue to next / prev,,1,H
|
6
|
+
,,Ability to see list of questions,This includes ability to jump to that question,4,H
|
7
|
+
,Submit,Ability to return to new screen,,1,M
|
8
|
+
Admin,Create questions,Ability to enter question,,4,H
|
9
|
+
,,Ability to reorder question,,4,H
|
10
|
+
,,Ability to enter multiple choice question,,1,L
|
11
|
+
,,Ability to enter text question,,1,H
|
12
|
+
,,Ability to enter long text question,,1,H
|
13
|
+
,,Ability to enter list question,,2,L
|
14
|
+
,Compile votes,Ability to see results in spreadsheet,,4,H
|
15
|
+
,,Ability to see summary of results,This includes percentage of each question answering which answer,2,M
|
16
|
+
,Announce winners,,,,
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Story,Labels,Story Type,Estimate,Description,Priority
|
2
|
+
Ability to see question,"Vote on question, H",,1,"while Voter
|
3
|
+
",2
|
4
|
+
Ability to see choices,"Vote on question, M",,1,"while Voter
|
5
|
+
",1
|
6
|
+
Ability to choose,"Vote on question, H",,2,"while Voter
|
7
|
+
This is the server trip",2
|
8
|
+
Ability to continue to next / prev,"Navigate questions, H",,1,"while Voter
|
9
|
+
",2
|
10
|
+
Ability to see list of questions,"Navigate questions, H",,4,"while Voter
|
11
|
+
This includes ability to jump to that question",2
|
12
|
+
Ability to return to new screen,"Submit, M",,1,"while Voter
|
13
|
+
",1
|
14
|
+
Ability to enter question,"Create questions, H",,4,"while Admin
|
15
|
+
",2
|
16
|
+
Ability to reorder question,"Create questions, H",,4,"while Admin
|
17
|
+
",2
|
18
|
+
Ability to enter multiple choice question,"Create questions, L",,1,"while Admin
|
19
|
+
",0
|
20
|
+
Ability to enter text question,"Create questions, H",,1,"while Admin
|
21
|
+
",2
|
22
|
+
Ability to enter long text question,"Create questions, H",,1,"while Admin
|
23
|
+
",2
|
24
|
+
Ability to enter list question,"Create questions, L",,2,"while Admin
|
25
|
+
",0
|
26
|
+
Ability to see results in spreadsheet,"Compile votes, H",,4,"while Admin
|
27
|
+
",2
|
28
|
+
Ability to see summary of results,"Compile votes, M",,2,"while Admin
|
29
|
+
This includes percentage of each question answering which answer",1
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
gem 'cards'
|
4
|
+
require 'cards'
|
5
|
+
include Cards
|
6
|
+
|
7
|
+
|
8
|
+
def csv_file(name)
|
9
|
+
CsvParser.new(File.dirname(__FILE__) + "/#{name}.csv")
|
10
|
+
end
|
11
|
+
|
12
|
+
class Tracker < CsvBuilder
|
13
|
+
PRIORITY = %w(L M H)
|
14
|
+
|
15
|
+
def header
|
16
|
+
["Story", "Labels", "Story Type", "Estimate", "Description", "Priority"]
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_story(name, row = {})
|
20
|
+
@csv << [
|
21
|
+
name,
|
22
|
+
"#{@task}, #{row[:priority]}",
|
23
|
+
nil,
|
24
|
+
row[:estimate],
|
25
|
+
"while #{@activity}\n#{row[:note]}",
|
26
|
+
PRIORITY.index(row[:priority])
|
27
|
+
]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Tracker.from csv_file("Stories")
|
Binary file
|
Binary file
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/CardWallGenerator/include.rb'
|
2
|
+
|
3
|
+
|
4
|
+
data = load_excel_data 'Business Processes.xls', 1
|
5
|
+
create_visio_document data, 'Caution.vsd'
|
6
|
+
|
7
|
+
data = load_excel_data 'Business Processes.xls', 2
|
8
|
+
create_visio_document data, 'TPS.vsd'
|
9
|
+
|
10
|
+
|
@@ -0,0 +1,104 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Card Wall Generator</title>
|
4
|
+
</head>
|
5
|
+
<body>
|
6
|
+
<div align="center">
|
7
|
+
<div style="width:800;" align="left">
|
8
|
+
<h1>Card Wall Generator</h1>
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
<h2>What is it?</h2>
|
13
|
+
<hr/>
|
14
|
+
|
15
|
+
<p>
|
16
|
+
this tool will take an excel spreadsheet with a hierarchical story list in it, and generate
|
17
|
+
a "card wall" in visio from it.
|
18
|
+
</p>
|
19
|
+
|
20
|
+
<p style="text-align:right">
|
21
|
+
<img src="TPS-small.png"><br>
|
22
|
+
<i>a "card wall"</i>
|
23
|
+
</p>
|
24
|
+
|
25
|
+
<p>
|
26
|
+
the spreadsheet might look like - <a href="business processes.xls">business processes.xls</a>
|
27
|
+
</p>
|
28
|
+
|
29
|
+
<p>
|
30
|
+
and the card wall might look like - <a href="TPS.vsd">TPS.vsd</a><br>
|
31
|
+
</p>
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
<h2>Installation</h2>
|
37
|
+
<hr/>
|
38
|
+
|
39
|
+
<h3>You will need:</h3>
|
40
|
+
|
41
|
+
<ul>
|
42
|
+
<li>Windows - sorry only works on windows right now...
|
43
|
+
<li>Excel
|
44
|
+
<li>Visio
|
45
|
+
<li>Ruby - download it from here - <a href="http://rubyforge.org/projects/rubyinstaller/">http://rubyforge.org/projects/rubyinstaller/</a>
|
46
|
+
</ul>
|
47
|
+
|
48
|
+
<p>
|
49
|
+
Once you have all those installed, you can test your installation by double clicking the
|
50
|
+
"generate card walls.rb" file. It should open excel for a second, then open up visio and
|
51
|
+
generate 2 card walls.
|
52
|
+
</p>
|
53
|
+
|
54
|
+
<h3>The Driver File</h3>
|
55
|
+
|
56
|
+
<p>
|
57
|
+
What the card wall generator does is configured by the "generate card walls.rb" file. Open
|
58
|
+
it up and take a look. You should see stuff like :
|
59
|
+
</p>
|
60
|
+
|
61
|
+
<code><pre>
|
62
|
+
data = load_excel_data 'Business Processes.xls', 1
|
63
|
+
create_visio_document data, 'Caution.vsd'
|
64
|
+
</pre></code>
|
65
|
+
|
66
|
+
<p>You can customize this for your needs. Basically copy these 2 lines for every card wall
|
67
|
+
you want to create, and substitute these for the values :
|
68
|
+
<ul>
|
69
|
+
<li>excel file with the master story list - "Business Processes.xls"
|
70
|
+
<li>index of the sheet within the excel file - "1"
|
71
|
+
<li>visio file that will be created - "Caution.vsd"
|
72
|
+
</ul>
|
73
|
+
</p>
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
<h2>More Information</h2>
|
78
|
+
<hr/>
|
79
|
+
|
80
|
+
<p>Visit the project website at :</p>
|
81
|
+
|
82
|
+
<p><a href="http://rubyforge.org/projects/cardwallgen">http://rubyforge.org/projects/cardwallgen</a></p>
|
83
|
+
|
84
|
+
<p>The documentation is still pretty sparse. If you can find someone that knows ruby, have them poke
|
85
|
+
around, and they'll probably be able to figure out how to do most things. Otherwise, email the list
|
86
|
+
at cardwallgen-users@rubyforge.org, or sign up for the list at the project website.</p>
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
<h2>License</h2>
|
92
|
+
<hr/>
|
93
|
+
|
94
|
+
<p>
|
95
|
+
<i>Copyright (C) 2006 Jeremy Stell-Smith</i>
|
96
|
+
</p>
|
97
|
+
|
98
|
+
<p>
|
99
|
+
This software is distributed under the LGPL license.
|
100
|
+
</p>
|
101
|
+
</div>
|
102
|
+
</div>
|
103
|
+
</body>
|
104
|
+
</html>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Activity,Task,Story,Note,Estimate,Priority
|
2
|
+
Voter,Vote on question,Ability to see question,,1,H
|
3
|
+
,,Ability to see choices,,1,M
|
4
|
+
,,Ability to choose,This is the server trip,2,H
|
5
|
+
,Navigate questions,Ability to continue to next / prev,,1,H
|
6
|
+
,,Ability to see list of questions,This includes ability to jump to that question,3,H
|
7
|
+
,Submit,Ability to return to new screen,,1,M
|
8
|
+
Admin,Create questions,Ability to enter question,,3,H
|
9
|
+
,,Ability to reorder question,,3,H
|
10
|
+
,,Ability to enter multiple choice question,,1,L
|
11
|
+
,,Ability to enter text question,,1,H
|
12
|
+
,,Ability to enter long text question,,1,H
|
13
|
+
,,Ability to enter list question,,2,L
|
14
|
+
,Compile votes,Ability to see results in spreadsheet,,3,H
|
15
|
+
,,Ability to see summary of results,This includes percentage of each question answering which answer,2,M
|
16
|
+
,Announce winners,,,,
|
Binary file
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'appscript'
|
3
|
+
|
4
|
+
itunes = Appscript.app('iTunes')
|
5
|
+
|
6
|
+
track = itunes.current_track
|
7
|
+
p track # <OSA::Itunes::FileTrack:0x1495e20>
|
8
|
+
p track.name # "Over The Rainbow"
|
9
|
+
p track.artist # "Keith Jarrett"
|
10
|
+
p track.duration # 362.368988037109
|
11
|
+
p track.date_added.to_s # "2006-06-30"
|
12
|
+
p track.enabled? # true
|
13
|
+
|
14
|
+
# Play the selected track.
|
15
|
+
itunes.play
|
16
|
+
|
17
|
+
# Fade the volume.
|
18
|
+
100.times { |i| itunes.sound_volume = i; sleep 0.1 }
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require File.dirname(__FILE__) + "/../../lib/cards" # you probably want to include the gem version
|
4
|
+
require 'rest_client'
|
5
|
+
|
6
|
+
token = "d6b1b5ded944959aec78754ff9f018bd"
|
7
|
+
project_id = "9989"
|
8
|
+
priority = %w(L M H)
|
9
|
+
|
10
|
+
project = RestClient::Resource.new("http://www.pivotaltracker.com/services/v2/projects/#{project_id}",
|
11
|
+
:headers => { "X-TrackerToken" => token })
|
12
|
+
|
13
|
+
# puts project["stories?filter=type:bug"].get
|
14
|
+
|
15
|
+
require 'rbosa'
|
16
|
+
numbers = OSA.app('Numbers')
|
17
|
+
|
18
|
+
# itunes = OSA.app('iTunes')
|
19
|
+
# track = itunes.current_track
|
20
|
+
# p track # <OSA::Itunes::FileTrack:0x1495e20>
|
21
|
+
# p track.name # "Over The Rainbow"
|
22
|
+
# p track.artist # "Keith Jarrett"
|
23
|
+
# p track.duration # 362.368988037109
|
24
|
+
# p track.date_added.to_s # "2006-06-30"
|
25
|
+
# p track.enabled? # true
|
26
|
+
#
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
csv = Cards::CsvParser.new(File.dirname(__FILE__) + "/Stories.csv")
|
34
|
+
rows = csv.denormalized_rows(:story, [:activity, :task])
|
35
|
+
rows = rows.sort_by {|row| priority.index(row[:priority])}
|
36
|
+
|
37
|
+
rows.each do |row|
|
38
|
+
puts "adding #{row[:story]}"
|
39
|
+
|
40
|
+
params = {}
|
41
|
+
params[:name] = row[:story]
|
42
|
+
# params[:story_type] = "bug"
|
43
|
+
params[:current_state] = "unstarted"
|
44
|
+
params[:requested_by] = "Cards Test User"
|
45
|
+
params[:estimate] = row[:estimate]
|
46
|
+
params[:description] = "while #{row[:activity]}\n#{row[:note]}"
|
47
|
+
|
48
|
+
# project["stories"].post(:story => params)
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require File.dirname(__FILE__) + "/../../lib/cards" # you probably want to include the gem version
|
4
|
+
require 'rest_client'
|
5
|
+
|
6
|
+
token = "d6b1b5ded944959aec78754ff9f018bd"
|
7
|
+
project_id = "9989"
|
8
|
+
priority = %w(L M H)
|
9
|
+
|
10
|
+
project = RestClient::Resource.new("http://www.pivotaltracker.com/services/v2/projects/#{project_id}",
|
11
|
+
:headers => { "X-TrackerToken" => token })
|
12
|
+
|
13
|
+
# puts project["stories?filter=type:bug"].get
|
14
|
+
|
15
|
+
csv = Cards::CsvParser.new(File.dirname(__FILE__) + "/Stories.csv")
|
16
|
+
rows = csv.denormalized_rows(:story, [:activity, :task])
|
17
|
+
rows = rows.sort_by {|row| priority.index(row[:priority])}
|
18
|
+
|
19
|
+
rows.each do |row|
|
20
|
+
puts "adding #{row[:story]}"
|
21
|
+
|
22
|
+
params = {}
|
23
|
+
params[:name] = row[:story]
|
24
|
+
# params[:story_type] = "bug"
|
25
|
+
params[:current_state] = "unstarted"
|
26
|
+
params[:requested_by] = "Cards Test User"
|
27
|
+
params[:estimate] = row[:estimate]
|
28
|
+
params[:description] = "while #{row[:activity]}\n#{row[:note]}"
|
29
|
+
|
30
|
+
project["stories"].post(:story => params)
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rbosa'
|
3
|
+
|
4
|
+
def find_table(document, name)
|
5
|
+
document.sheets.each do |sheet|
|
6
|
+
sheet.tables.each do |table|
|
7
|
+
return table
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
numbers = OSA.app('Numbers')
|
13
|
+
document = numbers.open(File.dirname(__FILE__) + "/Voting Example.numbers")
|
14
|
+
table = find_table(document, "Stories")
|
15
|
+
|
16
|
+
p table.name
|
17
|
+
table.rows.each do |row|
|
18
|
+
values = []
|
19
|
+
row.cells.map do |cell|
|
20
|
+
values << cell.name << cell.value
|
21
|
+
end
|
22
|
+
p values
|
23
|
+
end
|
24
|
+
|
25
|
+
# itunes = OSA.app('iTunes')
|
26
|
+
#
|
27
|
+
# track = itunes.current_track
|
28
|
+
# p track # <OSA::Itunes::FileTrack:0x1495e20>
|
29
|
+
# p track.name # "Over The Rainbow"
|
30
|
+
# p track.artist # "Keith Jarrett"
|
31
|
+
# p track.duration # 362.368988037109
|
32
|
+
# p track.date_added.to_s # "2006-06-30"
|
33
|
+
# p track.enabled? # true
|
34
|
+
#
|
35
|
+
# # Play the selected track.
|
36
|
+
# itunes.play
|
37
|
+
#
|
38
|
+
# # Fade the volume.
|
39
|
+
# 100.times { |i| itunes.sound_volume = i; sleep 0.1 }
|
Binary file
|
@@ -1,29 +1,31 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# this doesn't actually read the numbers document, you must export csv from numbers as we've done here,
|
3
|
-
# the csv can then be parsed and turned into omnigraffle
|
4
|
-
|
5
2
|
require 'rubygems'
|
3
|
+
gem 'cards'
|
6
4
|
require 'cards'
|
5
|
+
require 'cards/numbers_parser'
|
7
6
|
include Cards
|
8
7
|
|
9
|
-
|
10
|
-
|
8
|
+
# this requires numbers '09, before that you must export to csv and use the csv parser
|
9
|
+
|
10
|
+
def table(name)
|
11
|
+
file = File.dirname(__FILE__) + "/Voting Example.numbers"
|
12
|
+
NumbersParser.new(file, name)
|
11
13
|
end
|
12
14
|
|
13
15
|
CardWall.colors[:goal] = :green
|
14
16
|
CardWall.writer = GraffleWriter
|
15
17
|
|
16
|
-
CardWall.from
|
18
|
+
CardWall.from table("Goals") do
|
17
19
|
column :goal
|
18
20
|
end
|
19
21
|
|
20
|
-
CardWall.from
|
22
|
+
CardWall.from table("Workflow") do
|
21
23
|
row :role
|
22
24
|
column :task, :wrap_at => 5
|
23
25
|
end
|
24
26
|
|
25
|
-
CardWall.from
|
26
|
-
row :
|
27
|
+
CardWall.from table("Stories") do
|
28
|
+
row :activity
|
27
29
|
row :task
|
28
30
|
column :story, :wrap_at => 4 do |card, row|
|
29
31
|
card.name = " #{row[:estimate]}\n\n#{card.name}" unless row[:estimate].blank?
|
data/lib/cards.rb
CHANGED
@@ -9,9 +9,11 @@ require 'cards/card_wall'
|
|
9
9
|
require 'cards/writers/dot_writer'
|
10
10
|
require 'cards/writers/graffle_writer'
|
11
11
|
|
12
|
+
# csv builders
|
13
|
+
require 'cards/csv_builder'
|
12
14
|
require 'cards/master_story_list'
|
13
15
|
require 'cards/tracker_csv'
|
14
16
|
|
15
17
|
module Cards
|
16
|
-
VERSION = "0.
|
18
|
+
VERSION = "0.9"
|
17
19
|
end
|
data/lib/cards/csv_builder.rb
CHANGED
@@ -1,46 +1,48 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
module Cards
|
2
|
+
class CsvBuilder
|
3
|
+
def initialize(file_name)
|
4
|
+
@file_name = file_name
|
5
|
+
@file = File.open(file_name, "wb")
|
6
|
+
@csv = CSV::Writer.create(@file)
|
7
|
+
@csv << header
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def header
|
11
|
+
raise "implement me"
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
def self.from(parser)
|
15
|
+
builder = self.new(parser.default_output_file + ".#{self.to_s.gsub("Cards::", "").downcase}.csv")
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
parser.each_row do |row|
|
18
|
+
builder.process(row)
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
builder.done
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
def process(row)
|
25
|
+
[:activity, :task, :story].each do |handler|
|
26
|
+
send("add_#{handler}", row[handler], row) if row[handler]
|
27
|
+
end
|
26
28
|
end
|
27
|
-
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
def add_activity(name, params = {})
|
31
|
+
@activity = name
|
32
|
+
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
def add_task(name, params = {})
|
35
|
+
@task = name
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
def add_story(name, params = {})
|
39
|
+
raise "implement me"
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
def done
|
43
|
+
@csv.close
|
44
|
+
@file.close
|
45
|
+
`open #{@file_name.gsub(' ', '\\ ')}`
|
46
|
+
end
|
45
47
|
end
|
46
48
|
end
|
data/lib/cards/csv_parser.rb
CHANGED
@@ -1,60 +1,22 @@
|
|
1
1
|
require 'csv'
|
2
|
+
require 'cards/tabular_parser'
|
2
3
|
|
3
4
|
module Cards
|
4
5
|
class CsvParser
|
6
|
+
include TabularParser
|
7
|
+
|
5
8
|
def initialize(file)
|
6
9
|
@file = file
|
7
10
|
end
|
8
11
|
|
9
|
-
def
|
10
|
-
rows = []
|
11
|
-
each_row {|row| rows << row}
|
12
|
-
rows
|
13
|
-
end
|
14
|
-
|
15
|
-
def each_row
|
16
|
-
header = nil
|
12
|
+
def each_unparsed_row
|
17
13
|
CSV.open(@file, 'r') do |row|
|
18
|
-
|
19
|
-
header = define_header(row)
|
20
|
-
else
|
21
|
-
yield Row.new(header, row)
|
22
|
-
end
|
14
|
+
yield row
|
23
15
|
end
|
24
16
|
end
|
25
|
-
|
17
|
+
|
26
18
|
def default_output_file
|
27
19
|
File.basename(@file).sub(/\..*/, '')
|
28
20
|
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def define_header(header_row)
|
33
|
-
header = {}
|
34
|
-
header_row.each_with_index do |name, i|
|
35
|
-
header[name.downcase.gsub(' ', '_').to_sym] = i
|
36
|
-
end
|
37
|
-
return header
|
38
|
-
end
|
39
|
-
|
40
|
-
class Row
|
41
|
-
def initialize(header, row)
|
42
|
-
@header, @row = header, row
|
43
|
-
end
|
44
|
-
|
45
|
-
def [](key)
|
46
|
-
index = @header[key] || raise("can't find column header #{key.inspect} in #{@header.inspect}")
|
47
|
-
@row[index]
|
48
|
-
end
|
49
|
-
|
50
|
-
def to_h
|
51
|
-
h = {}
|
52
|
-
@header.each_key do |column_header|
|
53
|
-
val = @row[@header[column_header]]
|
54
|
-
h[column_header] = val unless val.blank?
|
55
|
-
end
|
56
|
-
h
|
57
|
-
end
|
58
|
-
end
|
59
21
|
end
|
60
22
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rbosa'
|
2
|
+
require 'cards/tabular_parser'
|
3
|
+
|
4
|
+
module Cards
|
5
|
+
class NumbersParser
|
6
|
+
include TabularParser
|
7
|
+
|
8
|
+
def initialize(file, table_name)
|
9
|
+
@file, @table_name = file, table_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def each_unparsed_row
|
13
|
+
numbers = OSA.app('Numbers')
|
14
|
+
document = numbers.open(@file)
|
15
|
+
table = find_table(document, @table_name)
|
16
|
+
|
17
|
+
table.rows.each do |row|
|
18
|
+
values = []
|
19
|
+
row.cells.map do |cell|
|
20
|
+
value = cell.value
|
21
|
+
value = nil if value == 0
|
22
|
+
values << value
|
23
|
+
end
|
24
|
+
yield values
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def default_output_file
|
29
|
+
@table_name
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def find_table(document, name)
|
35
|
+
document.sheets.each do |sheet|
|
36
|
+
sheet.tables.each do |table|
|
37
|
+
return table if table.name.downcase == name.downcase
|
38
|
+
end
|
39
|
+
end
|
40
|
+
raise "table #{name} not found in #{document.name}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/cards/swim_lanes.rb
CHANGED
@@ -0,0 +1,78 @@
|
|
1
|
+
module Cards
|
2
|
+
module TabularParser
|
3
|
+
def rows
|
4
|
+
rows = []
|
5
|
+
each_row {|row| rows << row}
|
6
|
+
rows
|
7
|
+
end
|
8
|
+
|
9
|
+
def each_row
|
10
|
+
header = nil
|
11
|
+
each_unparsed_row do |row|
|
12
|
+
if header.nil?
|
13
|
+
header = define_header(row)
|
14
|
+
else
|
15
|
+
yield Row.new(header, row)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# this method will turn something of the form
|
21
|
+
#
|
22
|
+
# activity | task | story |
|
23
|
+
# a | | |
|
24
|
+
# | b | |
|
25
|
+
# | | c |
|
26
|
+
# | | d |
|
27
|
+
#
|
28
|
+
# into
|
29
|
+
#
|
30
|
+
# activity | task | story |
|
31
|
+
# a | b | c |
|
32
|
+
# a | b | d |
|
33
|
+
#
|
34
|
+
def denormalized_rows(key_column, columns_to_denormalize)
|
35
|
+
last_row = {}
|
36
|
+
rows = []
|
37
|
+
each_row do |row|
|
38
|
+
row = row.to_h
|
39
|
+
columns_to_denormalize.each do |c|
|
40
|
+
row[c] = last_row[c] if row[c].blank?
|
41
|
+
end
|
42
|
+
rows << row unless row[key_column].blank?
|
43
|
+
last_row = row
|
44
|
+
end
|
45
|
+
rows
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def define_header(header_row)
|
51
|
+
header = {}
|
52
|
+
header_row.each_with_index do |name, i|
|
53
|
+
header[name.downcase.gsub(' ', '_').to_sym] = i
|
54
|
+
end
|
55
|
+
return header
|
56
|
+
end
|
57
|
+
|
58
|
+
class Row
|
59
|
+
def initialize(header, row)
|
60
|
+
@header, @row = header, row
|
61
|
+
end
|
62
|
+
|
63
|
+
def [](key)
|
64
|
+
index = @header[key] || raise("can't find column header #{key.inspect} in #{@header.inspect}")
|
65
|
+
@row[index]
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_h
|
69
|
+
h = {}
|
70
|
+
@header.each_key do |column_header|
|
71
|
+
val = @row[@header[column_header]]
|
72
|
+
h[column_header] = val unless val.blank?
|
73
|
+
end
|
74
|
+
h
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/cards/tracker_csv.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
require 'cards/csv_builder'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Cards
|
4
|
+
class TrackerCsv < CsvBuilder
|
5
|
+
def header
|
6
|
+
["Story", "Labels", "Story Type", "Estimate", "Description"]
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
def add_story(name, params = {})
|
10
|
+
return unless [nil, '', 'Story', 'Chore'].include?(params[:story_type])
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
@csv << [
|
13
|
+
name,
|
14
|
+
@task,
|
15
|
+
params[:story_type],
|
16
|
+
nil, # params[:estimate],
|
17
|
+
"#{@activity}\n#{params[:description]}"
|
18
|
+
]
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|
@@ -1,7 +1,11 @@
|
|
1
1
|
module Cards
|
2
2
|
class DotWriter
|
3
|
-
def initialize(
|
4
|
-
|
3
|
+
def initialize(file)
|
4
|
+
if file.respond_to? :puts
|
5
|
+
@file = file
|
6
|
+
else
|
7
|
+
@file = File.open(file + ".dot", "w")
|
8
|
+
end
|
5
9
|
@node_color = {:green => "darkseagreen1", :blue => "lightblue", :red => "pink", :yellow => "lightyellow"}
|
6
10
|
@nodes = []
|
7
11
|
|
@@ -7,22 +7,40 @@ include Cards
|
|
7
7
|
describe CsvParser do
|
8
8
|
include FileSandbox
|
9
9
|
|
10
|
-
|
10
|
+
before do
|
11
11
|
sandbox.new :file => 'tmp.csv', :with_contents =>
|
12
12
|
"activity,task,story,estimate
|
13
13
|
manage email,,
|
14
14
|
,read email,
|
15
15
|
,,display email body
|
16
|
-
manage email,think about email
|
16
|
+
manage email,think about email,mow the lawn,1
|
17
17
|
,read email,,2
|
18
18
|
,,display email body,3"
|
19
|
-
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should parse csv" do
|
20
22
|
rows = CsvParser.new(sandbox['tmp.csv'].path).rows
|
21
23
|
rows[0].to_h.should == {:activity => 'manage email'}
|
22
24
|
rows[1].to_h.should == {:task => 'read email'}
|
23
25
|
rows[2].to_h.should == {:story => 'display email body'}
|
24
|
-
rows[3].to_h.should == {:activity => 'manage email', :task => 'think about email', :estimate => "1"}
|
26
|
+
rows[3].to_h.should == {:activity => 'manage email', :task => 'think about email', :story => 'mow the lawn', :estimate => "1"}
|
25
27
|
rows[4].to_h.should == {:task => 'read email', :estimate => "2"}
|
26
28
|
rows[5].to_h.should == {:story => 'display email body', :estimate => "3"}
|
27
29
|
end
|
30
|
+
|
31
|
+
it "should denormalize rows" do
|
32
|
+
rows = CsvParser.new(sandbox['tmp.csv'].path).denormalized_rows(:story, [:activity, :task])
|
33
|
+
rows.size.should == 3
|
34
|
+
rows[0].should == {:activity => 'manage email',
|
35
|
+
:task => 'read email',
|
36
|
+
:story => 'display email body'}
|
37
|
+
rows[1].should == {:activity => 'manage email',
|
38
|
+
:task => 'think about email',
|
39
|
+
:story => 'mow the lawn',
|
40
|
+
:estimate => "1"}
|
41
|
+
rows[2].should == {:activity => 'manage email',
|
42
|
+
:task => 'read email',
|
43
|
+
:story => 'display email body',
|
44
|
+
:estimate => '3'}
|
45
|
+
end
|
28
46
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'cards/numbers_parser'
|
3
|
+
|
4
|
+
# not the best test, but it will do
|
5
|
+
describe Cards::NumbersParser do
|
6
|
+
describe "each_row" do
|
7
|
+
it "should find all rows in Voting Example" do
|
8
|
+
file = File.expand_path(File.dirname(__FILE__) + "/../fixtures/Voting Example.numbers")
|
9
|
+
parser = Cards::NumbersParser.new(file, "Workflow")
|
10
|
+
rows = parser.rows
|
11
|
+
rows[0].to_h.should == {:role => "Voter", :task => "Vote on question"}
|
12
|
+
rows[1].to_h.should == {:task => "Navigate questions"}
|
13
|
+
rows[2].to_h.should == {:task => "Submit"}
|
14
|
+
rows[3].to_h.should == {:role => "Admin", :task => "Create questions"}
|
15
|
+
rows[4].to_h.should == {:task => "Compile votes"}
|
16
|
+
rows[5].to_h.should == {:task => "Announce winners"}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "default_output_file" do
|
21
|
+
it "should be the table name" do
|
22
|
+
Cards::NumbersParser.new("some file.numbers", "larry").default_output_file.should == "larry"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cards
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.9"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Stell-Smith
|
@@ -9,17 +9,18 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-03-05 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: hoe
|
17
|
+
type: :development
|
17
18
|
version_requirement:
|
18
19
|
version_requirements: !ruby/object:Gem::Requirement
|
19
20
|
requirements:
|
20
21
|
- - ">="
|
21
22
|
- !ruby/object:Gem::Version
|
22
|
-
version: 1.
|
23
|
+
version: 1.8.2
|
23
24
|
version:
|
24
25
|
description: CardWallGen is a program that reads a requirements map and generates a view of it. Typically it reads it from excel or csv and generates a graphical view in visio or omnigraffle, though it may also generate another csv view of it.
|
25
26
|
email: jeremystellsmith@gmail.com
|
@@ -29,48 +30,67 @@ extensions: []
|
|
29
30
|
|
30
31
|
extra_rdoc_files:
|
31
32
|
- CHANGES.txt
|
32
|
-
- Manifest.txt
|
33
33
|
- README.txt
|
34
34
|
files:
|
35
35
|
- CHANGES.txt
|
36
|
-
- Manifest.txt
|
37
|
-
- README.txt
|
38
36
|
- Rakefile
|
39
|
-
-
|
40
|
-
- examples/csv to dot
|
37
|
+
- README.txt
|
38
|
+
- examples/csv to dot
|
41
39
|
- examples/csv to dot/generate_card_walls
|
42
|
-
- examples/
|
43
|
-
- examples/
|
44
|
-
- examples/
|
45
|
-
- examples/
|
46
|
-
- examples/
|
47
|
-
- examples/
|
48
|
-
- examples/
|
40
|
+
- examples/csv to dot/Stories.csv
|
41
|
+
- examples/custom csv builder
|
42
|
+
- examples/custom csv builder/generate_card_wall
|
43
|
+
- examples/custom csv builder/Stories.csv
|
44
|
+
- examples/custom csv builder/Stories.tracker.csv
|
45
|
+
- examples/excel to visio
|
46
|
+
- examples/excel to visio/Business Processes.xls
|
47
|
+
- examples/excel to visio/generate card walls.rb
|
48
|
+
- examples/excel to visio/readme.html
|
49
|
+
- examples/excel to visio/TPS-small.png
|
50
|
+
- examples/importing into tracker api
|
51
|
+
- examples/importing into tracker api/appscript_example.rb
|
52
|
+
- examples/importing into tracker api/from_numbers_09
|
53
|
+
- examples/importing into tracker api/generate_card_wall
|
54
|
+
- examples/importing into tracker api/osa.rb
|
55
|
+
- examples/importing into tracker api/Stories.csv
|
56
|
+
- examples/importing into tracker api/Voting Example.numbers
|
57
|
+
- examples/numbers to omnigraffle
|
49
58
|
- examples/numbers to omnigraffle/generate_card_walls
|
50
|
-
-
|
59
|
+
- examples/numbers to omnigraffle/Voting Example.numbers
|
60
|
+
- lib/cards
|
51
61
|
- lib/cards/builder.rb
|
52
62
|
- lib/cards/card.rb
|
53
63
|
- lib/cards/card_wall.rb
|
54
64
|
- lib/cards/csv_builder.rb
|
55
65
|
- lib/cards/csv_parser.rb
|
56
66
|
- lib/cards/extensions.rb
|
67
|
+
- lib/cards/layouts
|
57
68
|
- lib/cards/layouts/column_layout.rb
|
58
69
|
- lib/cards/layouts/nil_layout.rb
|
59
70
|
- lib/cards/layouts/row_layout.rb
|
60
71
|
- lib/cards/master_story_list.rb
|
72
|
+
- lib/cards/numbers_parser.rb
|
61
73
|
- lib/cards/swim_lanes.rb
|
74
|
+
- lib/cards/tabular_parser.rb
|
62
75
|
- lib/cards/text.rb
|
63
76
|
- lib/cards/tracker_csv.rb
|
77
|
+
- lib/cards/writers
|
64
78
|
- lib/cards/writers/dot_writer.rb
|
65
79
|
- lib/cards/writers/graffle_writer.rb
|
66
80
|
- lib/cards/writers/text_writer.rb
|
81
|
+
- lib/cards.rb
|
82
|
+
- spec/cards
|
67
83
|
- spec/cards/card_spec.rb
|
68
84
|
- spec/cards/card_wall_spec.rb
|
69
85
|
- spec/cards/csv_parser_spec.rb
|
70
86
|
- spec/cards/extensions_spec.rb
|
87
|
+
- spec/cards/numbers_parser_spec.rb
|
71
88
|
- spec/cards/swim_lanes_spec.rb
|
89
|
+
- spec/cards/writers
|
72
90
|
- spec/cards/writers/dot_writer_spec.rb
|
73
91
|
- spec/cards/writers/text_writer_spec.rb
|
92
|
+
- spec/fixtures
|
93
|
+
- spec/fixtures/Voting Example.numbers
|
74
94
|
- spec/spec_helper.rb
|
75
95
|
has_rdoc: true
|
76
96
|
homepage: http://rubyforge.org/projects/cardwallgen
|
@@ -95,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
115
|
requirements: []
|
96
116
|
|
97
117
|
rubyforge_project: cardwallgen
|
98
|
-
rubygems_version: 1.
|
118
|
+
rubygems_version: 1.3.1
|
99
119
|
signing_key:
|
100
120
|
specification_version: 2
|
101
121
|
summary: CardWallGen is a program that reads a requirements map and generates a view of it. Typically it reads it from excel or csv and generates a graphical view in visio or omnigraffle, though it may also generate another csv view of it.
|
data/Manifest.txt
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
CHANGES.txt
|
2
|
-
Manifest.txt
|
3
|
-
README.txt
|
4
|
-
Rakefile
|
5
|
-
examples/csv to dot/Stories.csv
|
6
|
-
examples/csv to dot/Stories.dot
|
7
|
-
examples/csv to dot/generate_card_walls
|
8
|
-
examples/numbers to omnigraffle/Voting Example.numbers/Contents/PkgInfo
|
9
|
-
examples/numbers to omnigraffle/Voting Example.numbers/QuickLook/Thumbnail.jpg
|
10
|
-
examples/numbers to omnigraffle/Voting Example.numbers/document-thumbnail.tiff
|
11
|
-
examples/numbers to omnigraffle/Voting Example.numbers/index.xml.gz
|
12
|
-
examples/numbers to omnigraffle/Voting Example/Cards-Goals.csv
|
13
|
-
examples/numbers to omnigraffle/Voting Example/Cards-Stories.csv
|
14
|
-
examples/numbers to omnigraffle/Voting Example/Cards-Workflow.csv
|
15
|
-
examples/numbers to omnigraffle/generate_card_walls
|
16
|
-
lib/cards.rb
|
17
|
-
lib/cards/builder.rb
|
18
|
-
lib/cards/card.rb
|
19
|
-
lib/cards/card_wall.rb
|
20
|
-
lib/cards/csv_builder.rb
|
21
|
-
lib/cards/csv_parser.rb
|
22
|
-
lib/cards/extensions.rb
|
23
|
-
lib/cards/layouts/column_layout.rb
|
24
|
-
lib/cards/layouts/nil_layout.rb
|
25
|
-
lib/cards/layouts/row_layout.rb
|
26
|
-
lib/cards/master_story_list.rb
|
27
|
-
lib/cards/swim_lanes.rb
|
28
|
-
lib/cards/text.rb
|
29
|
-
lib/cards/tracker_csv.rb
|
30
|
-
lib/cards/writers/dot_writer.rb
|
31
|
-
lib/cards/writers/graffle_writer.rb
|
32
|
-
lib/cards/writers/text_writer.rb
|
33
|
-
spec/cards/card_spec.rb
|
34
|
-
spec/cards/card_wall_spec.rb
|
35
|
-
spec/cards/csv_parser_spec.rb
|
36
|
-
spec/cards/extensions_spec.rb
|
37
|
-
spec/cards/swim_lanes_spec.rb
|
38
|
-
spec/cards/writers/dot_writer_spec.rb
|
39
|
-
spec/cards/writers/text_writer_spec.rb
|
40
|
-
spec/spec_helper.rb
|
@@ -1,63 +0,0 @@
|
|
1
|
-
digraph G {
|
2
|
-
graph [nodesep=.1, ranksep=.1, ordering=out];
|
3
|
-
node [shape=box, color=black, style=filled, width=2, height=1.2, fixedsize=true, labeljust="l"];
|
4
|
-
edge [style=invis, weight=1];
|
5
|
-
card_0_0 [label="Voter",fillcolor=lightblue];
|
6
|
-
card_0_1 [label="Vote on question",fillcolor=pink];
|
7
|
-
card_0_2 [label="Ability to see\nquestion 1",fillcolor=lightyellow];
|
8
|
-
card_0_3 [label="Ability to see\nchoices 1",fillcolor=lightyellow];
|
9
|
-
card_0_4 [label="Ability to choose\nThis is the server\ntrip 2",fillcolor=lightyellow];
|
10
|
-
card_1_1 [label="Navigate questions",fillcolor=pink];
|
11
|
-
card_1_2 [label="Ability to continue\nto next / prev 1",fillcolor=lightyellow];
|
12
|
-
card_1_3 [label="Ability to see list\nof questions This\nincludes ability to\njump to that\nquestion 4",fillcolor=lightyellow];
|
13
|
-
card_2_1 [label="Submit",fillcolor=pink];
|
14
|
-
card_2_2 [label="Ability to return to\nnew screen 1",fillcolor=lightyellow];
|
15
|
-
card_3_0 [label="Admin",fillcolor=lightblue];
|
16
|
-
card_3_1 [label="Create questions",fillcolor=pink];
|
17
|
-
card_3_2 [label="Ability to enter\nquestion 4",fillcolor=lightyellow];
|
18
|
-
card_3_3 [label="Ability to reorder\nquestion 4",fillcolor=lightyellow];
|
19
|
-
card_3_4 [label="Ability to enter\nmultiple choice\nquestion 1",fillcolor=lightyellow];
|
20
|
-
card_3_5 [label="Ability to enter\ntext question 1",fillcolor=lightyellow];
|
21
|
-
card_4_2 [label="Ability to enter\nlong text question\n1",fillcolor=lightyellow];
|
22
|
-
card_4_3 [label="Ability to enter\nlist question 2",fillcolor=lightyellow];
|
23
|
-
card_5_1 [label="Compile votes",fillcolor=pink];
|
24
|
-
card_5_2 [label="Ability to see\nresults in\nspreadsheet 4",fillcolor=lightyellow];
|
25
|
-
card_5_3 [label="Ability to see\nsummary of results\nThis includes\npercentage of each\nquestion answering\nwhich answer 2",fillcolor=lightyellow];
|
26
|
-
card_6_1 [label="Announce winners",fillcolor=pink];
|
27
|
-
gap_1_0 [style=invis];
|
28
|
-
gap_2_0 [style=invis];
|
29
|
-
gap_4_0 [style=invis];
|
30
|
-
gap_4_1 [style=invis];
|
31
|
-
gap_5_0 [style=invis];
|
32
|
-
gap_6_0 [style=invis];
|
33
|
-
{rank=same; card_0_0; gap_1_0; gap_2_0; card_3_0; gap_4_0; gap_5_0; gap_6_0};
|
34
|
-
{rank=same; card_0_1; card_1_1; card_2_1; card_3_1; gap_4_1; card_5_1; card_6_1};
|
35
|
-
{rank=same; card_0_2; card_1_2; card_2_2; card_3_2; card_4_2; card_5_2};
|
36
|
-
card_0_0 -> gap_1_0;
|
37
|
-
gap_1_0 -> gap_2_0;
|
38
|
-
gap_2_0 -> card_3_0;
|
39
|
-
card_3_0 -> gap_4_0;
|
40
|
-
gap_4_0 -> gap_5_0;
|
41
|
-
gap_5_0 -> gap_6_0;
|
42
|
-
card_0_0 -> card_0_1;
|
43
|
-
card_0_1 -> card_0_2;
|
44
|
-
card_0_2 -> card_0_3;
|
45
|
-
card_0_3 -> card_0_4;
|
46
|
-
gap_1_0 -> card_1_1;
|
47
|
-
card_1_1 -> card_1_2;
|
48
|
-
card_1_2 -> card_1_3;
|
49
|
-
gap_2_0 -> card_2_1;
|
50
|
-
card_2_1 -> card_2_2;
|
51
|
-
card_3_0 -> card_3_1;
|
52
|
-
card_3_1 -> card_3_2;
|
53
|
-
card_3_2 -> card_3_3;
|
54
|
-
card_3_3 -> card_3_4;
|
55
|
-
card_3_4 -> card_3_5;
|
56
|
-
gap_4_0 -> gap_4_1;
|
57
|
-
gap_4_1 -> card_4_2;
|
58
|
-
card_4_2 -> card_4_3;
|
59
|
-
gap_5_0 -> card_5_1;
|
60
|
-
card_5_1 -> card_5_2;
|
61
|
-
card_5_2 -> card_5_3;
|
62
|
-
gap_6_0 -> card_6_1;
|
63
|
-
}
|
@@ -1 +0,0 @@
|
|
1
|
-
????????
|
Binary file
|
Binary file
|
Binary file
|
@@ -1,16 +0,0 @@
|
|
1
|
-
Role,Task,Story,Note,Estimate
|
2
|
-
Voter,Vote on question,Ability to see question,,1
|
3
|
-
,,Ability to see choices,,1
|
4
|
-
,,Ability to choose,This is the server trip,2
|
5
|
-
,Navigate questions,Ability to continue to next / prev,,1
|
6
|
-
,,Ability to see list of questions,This includes ability to jump to that question,4
|
7
|
-
,Submit,Ability to return to new screen,,1
|
8
|
-
Admin,Create questions,Ability to enter question,,4
|
9
|
-
,,Ability to reorder question,,4
|
10
|
-
,,Ability to enter multiple choice question,,1
|
11
|
-
,,Ability to enter text question,,1
|
12
|
-
,,Ability to enter long text question,,1
|
13
|
-
,,Ability to enter list question,,2
|
14
|
-
,Compile votes,Ability to see results in spreadsheet,,4
|
15
|
-
,,Ability to see summary of results,This includes percentage of each question answering which answer,2
|
16
|
-
,Announce winners,,,
|