timekeeper 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/tk +4 -65
- data/bin/tv +4 -71
- data/lib/timekeeper.rb +8 -4
- data/lib/timekeeper/keep.rb +48 -55
- data/lib/timekeeper/keeper.rb +50 -0
- data/lib/timekeeper/keeper_options.rb +59 -0
- data/lib/timekeeper/runner.rb +37 -0
- data/lib/timekeeper/viewer.rb +38 -0
- data/lib/timekeeper/viewer_options.rb +55 -0
- metadata +6 -3
- data/lib/timekeeper/timekeeper.rb +0 -37
- data/lib/timekeeper/timeviewer.rb +0 -31
data/bin/tk
CHANGED
@@ -1,68 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
#
|
4
|
-
# Timekeeper. Keeping track of your time.
|
5
|
-
#
|
6
|
-
# == Usage
|
7
|
-
#
|
8
|
-
# tk [OPTIONS]
|
9
|
-
#
|
10
|
-
# -h, --help:
|
11
|
-
# show help
|
12
|
-
#
|
13
|
-
# --config [file]
|
14
|
-
# Location of your configuration file
|
15
|
-
#
|
16
|
-
# --title [title], -t [title]:
|
17
|
-
# What do you want to register
|
18
|
-
#
|
19
|
-
# --target [target], -c [target]:
|
20
|
-
# Who is going to pay?
|
21
|
-
#
|
22
|
-
# --time [time], -s [time]:
|
23
|
-
# How long did it take?
|
24
|
-
#
|
25
|
-
# --description [description], -m [description]
|
26
|
-
# More? You want to be more specific?
|
27
|
-
#
|
28
|
-
# --date [date], -d [date]
|
29
|
-
# When exactly did it happen?
|
30
|
-
#
|
31
|
-
# --remove [id]
|
32
|
-
# Remove a record.
|
33
|
-
#
|
34
|
-
require File.expand_path(File.dirname(__FILE__) + "/../lib/timekeeper")
|
2
|
+
require 'rubygems'
|
35
3
|
|
36
|
-
|
37
|
-
require
|
4
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
5
|
+
require 'timekeeper'
|
38
6
|
|
39
|
-
|
40
|
-
[ "--help", "-h", GetoptLong::NO_ARGUMENT ],
|
41
|
-
[ "--title", "-t", GetoptLong::REQUIRED_ARGUMENT ],
|
42
|
-
[ "--target", "-c", GetoptLong::REQUIRED_ARGUMENT ],
|
43
|
-
[ "--time", "-s", GetoptLong::REQUIRED_ARGUMENT ],
|
44
|
-
[ "--description","-m", GetoptLong::REQUIRED_ARGUMENT ],
|
45
|
-
[ "--date", "-d", GetoptLong::REQUIRED_ARGUMENT ],
|
46
|
-
[ "--remove" , GetoptLong::REQUIRED_ARGUMENT ],
|
47
|
-
[ "--config" , GetoptLong::REQUIRED_ARGUMENT ]
|
48
|
-
)
|
49
|
-
|
50
|
-
if ARGV.length == 0
|
51
|
-
puts "Please provide some options, type --help"
|
52
|
-
exit 0
|
53
|
-
end
|
54
|
-
|
55
|
-
tk = Timekeeper.new
|
56
|
-
|
57
|
-
attributes = {}
|
58
|
-
opts.each do |opt, arg|
|
59
|
-
case opt
|
60
|
-
when "--help": RDoc::usage
|
61
|
-
when "--config": tk.config arg
|
62
|
-
when "--remove": tk.delete(arg); exit 0
|
63
|
-
else
|
64
|
-
attributes.store(opt.gsub("-",""), arg)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
tk.store(attributes)
|
7
|
+
Timekeeper::Runner.tk(ARGV)
|
data/bin/tv
CHANGED
@@ -1,74 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
#
|
4
|
-
# Timeviewer. Keeping an eye on your tracked time.
|
5
|
-
#
|
6
|
-
# == Usage
|
7
|
-
#
|
8
|
-
# tv [OPTIONS]
|
9
|
-
#
|
10
|
-
# -h, --help:
|
11
|
-
# show help
|
12
|
-
#
|
13
|
-
# --config [file]
|
14
|
-
# Location of your configuration file
|
15
|
-
#
|
16
|
-
# --name [name], -n [name]:
|
17
|
-
# Query by name
|
18
|
-
#
|
19
|
-
# --title [title], -t [title]:
|
20
|
-
# Query by title
|
21
|
-
#
|
22
|
-
# --target [target], -c [target]:
|
23
|
-
# Query by target
|
24
|
-
#
|
25
|
-
# --description [description], -m [description]
|
26
|
-
# Query by description
|
27
|
-
#
|
28
|
-
# --date [date], -d [date]
|
29
|
-
# Query by date
|
30
|
-
#
|
31
|
-
require File.dirname(__FILE__) + '/../lib/timekeeper'
|
32
|
-
|
33
|
-
require "getoptlong"
|
34
|
-
require "rdoc/usage"
|
35
|
-
require "fastercsv"
|
2
|
+
require 'rubygems'
|
36
3
|
|
37
|
-
|
38
|
-
|
39
|
-
[ "--csv" , GetoptLong::NO_ARGUMENT ],
|
40
|
-
[ "--all" , GetoptLong::NO_ARGUMENT ],
|
41
|
-
[ "--name", "-n", GetoptLong::REQUIRED_ARGUMENT ],
|
42
|
-
[ "--title", "-t", GetoptLong::REQUIRED_ARGUMENT ],
|
43
|
-
[ "--target", "-c", GetoptLong::REQUIRED_ARGUMENT ],
|
44
|
-
[ "--time", "-s", GetoptLong::REQUIRED_ARGUMENT ],
|
45
|
-
[ "--description","-m", GetoptLong::REQUIRED_ARGUMENT ],
|
46
|
-
[ "--date", "-d", GetoptLong::REQUIRED_ARGUMENT ],
|
47
|
-
[ "--config" , GetoptLong::REQUIRED_ARGUMENT ]
|
48
|
-
)
|
4
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
5
|
+
require 'timekeeper'
|
49
6
|
|
50
|
-
|
51
|
-
puts "Please provide some options, type --help"
|
52
|
-
exit 0
|
53
|
-
end
|
54
|
-
|
55
|
-
tv = Timeviewer.new
|
56
|
-
output = nil
|
57
|
-
|
58
|
-
attributes = {}
|
59
|
-
opts.each do |opt, arg|
|
60
|
-
case opt
|
61
|
-
when "--help": RDoc::usage
|
62
|
-
when "--csv" : output = :csv
|
63
|
-
when "--config": tv.config arg
|
64
|
-
else
|
65
|
-
attributes.store(opt.gsub("-",""), arg)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
records = tv.all
|
70
|
-
if output
|
71
|
-
Timeviewer.export(records, "export", output)
|
72
|
-
else
|
73
|
-
puts records.collect{|r| Keep.new(r) }
|
74
|
-
end
|
7
|
+
Timekeeper::Runner.tv(ARGV)
|
data/lib/timekeeper.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
-
require "rubygems"
|
2
1
|
require "rufus/tokyo"
|
2
|
+
require "fastercsv"
|
3
|
+
require "optparse"
|
3
4
|
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
5
|
+
require "timekeeper/keep"
|
6
|
+
require "timekeeper/keeper"
|
7
|
+
require "timekeeper/viewer"
|
8
|
+
require "timekeeper/runner"
|
9
|
+
require "timekeeper/keeper_options"
|
10
|
+
require "timekeeper/viewer_options"
|
data/lib/timekeeper/keep.rb
CHANGED
@@ -1,72 +1,65 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Timekeeper
|
2
|
+
|
3
|
+
class Keep
|
4
4
|
|
5
|
-
|
5
|
+
attr_accessor :name, :time, :title, :description, :target, :date, :pk
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
def initialize(attributes)
|
8
|
+
set_attributes(attributes)
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
def update(attributes)
|
12
|
+
set_attributes(attributes)
|
13
|
+
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
def date=(value)
|
16
|
+
if value
|
17
|
+
if value.is_a?(Date)
|
18
|
+
@date = value
|
19
|
+
else
|
20
|
+
@date = parse_date(value.to_s)
|
21
|
+
end
|
21
22
|
end
|
22
23
|
end
|
23
|
-
|
24
|
+
|
25
|
+
def validate
|
26
|
+
mandatory(%w(name target title date time))
|
27
|
+
end
|
24
28
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
elsif NO.include?(value)
|
29
|
-
@track = false
|
29
|
+
def to_hash
|
30
|
+
{:name => name, :time => time, :title => title, :description => description,
|
31
|
+
:target => target, :date => date}
|
30
32
|
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def validate
|
34
|
-
mandatory(%w(name target title date time))
|
35
|
-
end
|
36
|
-
|
37
|
-
def to_hash
|
38
|
-
{:name => name, :time => time, :title => title, :description => description,
|
39
|
-
:target => target, :date => date, :track => track}
|
40
|
-
end
|
41
33
|
|
42
|
-
|
43
|
-
|
44
|
-
|
34
|
+
def to_s
|
35
|
+
"#{pk}|#{name}|#{target}|#{title}|#{description}|#{date}|#{time}"
|
36
|
+
end
|
45
37
|
|
46
|
-
|
38
|
+
private
|
47
39
|
|
48
|
-
|
49
|
-
|
50
|
-
|
40
|
+
def set_attributes(attributes)
|
41
|
+
attributes.each do |key, value|
|
42
|
+
respond_to?("#{key}=") ? send("#{key}=", value) : raise(StandardError, "unknown attribute: #{key}")
|
43
|
+
end
|
44
|
+
validate
|
45
|
+
self
|
51
46
|
end
|
52
|
-
validate
|
53
|
-
self
|
54
|
-
end
|
55
47
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
48
|
+
def parse_date(value)
|
49
|
+
case value
|
50
|
+
when "today" : Date.today
|
51
|
+
when "yesterday": Date.today - 1
|
52
|
+
when "tomorrow" : Date.today + 1
|
53
|
+
else
|
54
|
+
Date.parse(value)
|
55
|
+
end
|
63
56
|
end
|
64
|
-
end
|
65
57
|
|
66
|
-
|
67
|
-
|
68
|
-
|
58
|
+
def mandatory(attributes)
|
59
|
+
attributes.each do |attribute|
|
60
|
+
raise(StandardError, "#{attribute} is mandatory") unless send(attribute)
|
61
|
+
end
|
69
62
|
end
|
70
|
-
end
|
71
63
|
|
72
|
-
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Timekeeper
|
2
|
+
|
3
|
+
class Keeper
|
4
|
+
|
5
|
+
def config(file="timekeeper.yml")
|
6
|
+
@config ||= YAML.load_file(file)
|
7
|
+
end
|
8
|
+
|
9
|
+
def delete(id)
|
10
|
+
table.delete(id)
|
11
|
+
end
|
12
|
+
|
13
|
+
def delete_all
|
14
|
+
table.clear
|
15
|
+
end
|
16
|
+
|
17
|
+
def close
|
18
|
+
table.close
|
19
|
+
end
|
20
|
+
|
21
|
+
def count
|
22
|
+
table.count
|
23
|
+
end
|
24
|
+
|
25
|
+
def store(attributes)
|
26
|
+
attributes.store("name", config["name"])
|
27
|
+
attributes.store("date", Date.today) unless attributes["date"]
|
28
|
+
table[table.genuid] = Keep.new(attributes).to_hash
|
29
|
+
end
|
30
|
+
|
31
|
+
def get(id)
|
32
|
+
if attributes = table.lget(id.to_s).values.first
|
33
|
+
Keep.new(attributes)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def update(id, attributes_to_update)
|
38
|
+
if attributes = table.lget(id.to_s).values.first
|
39
|
+
table[id] = Keep.new(attributes).update(attributes_to_update).to_hash
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def table
|
46
|
+
@table ||= Rufus::Tokyo::Table.new(File.join(config["db_path"],"#{config["name"]}-time.tct"))
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Timekeeper
|
2
|
+
|
3
|
+
class KeeperOptions < Hash
|
4
|
+
attr_reader :opts
|
5
|
+
|
6
|
+
def initialize(args)
|
7
|
+
super()
|
8
|
+
|
9
|
+
@opts = OptionParser.new do |o|
|
10
|
+
o.banner = "Usage: #{File.basename($0)} [options]"
|
11
|
+
|
12
|
+
o.on("--config FILE", "location of your configuration file - default is ./timekeeper.yml") do |file|
|
13
|
+
self[:config] = file
|
14
|
+
end
|
15
|
+
|
16
|
+
o.on('-t', '--title TITLE', 'What do you want to register?') do |title|
|
17
|
+
self[:title] = title
|
18
|
+
end
|
19
|
+
|
20
|
+
o.on('-c', '--target TARGET', 'Who is going to pay?') do |target|
|
21
|
+
self[:target] = target
|
22
|
+
end
|
23
|
+
|
24
|
+
o.on('-s', '--time TIME', 'How long did it take?') do |time|
|
25
|
+
self[:time] = time
|
26
|
+
end
|
27
|
+
|
28
|
+
o.on('-m', '--description DESCRIPTION', 'More? You want to be more specific?') do |description|
|
29
|
+
self[:description] = description
|
30
|
+
end
|
31
|
+
|
32
|
+
o.on('-d', '--date DATE', 'When exactly did it happen?') do |date|
|
33
|
+
self[:date] = date
|
34
|
+
end
|
35
|
+
|
36
|
+
o.on('--remove ID', 'Remove a record.') do |id|
|
37
|
+
self[:remove] = id
|
38
|
+
end
|
39
|
+
|
40
|
+
o.on('--update ID', 'Remove a record.') do |id|
|
41
|
+
self[:update] = id
|
42
|
+
end
|
43
|
+
|
44
|
+
o.on_tail('-h', '--help', 'Display this help and exit') do
|
45
|
+
puts @opts
|
46
|
+
exit
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
begin
|
52
|
+
@opts.parse!(args)
|
53
|
+
rescue OptionParser::InvalidOption => e
|
54
|
+
self[:invalid_argument] = e.message
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Timekeeper
|
2
|
+
|
3
|
+
class Runner
|
4
|
+
|
5
|
+
def self.tk(args)
|
6
|
+
options = KeeperOptions.new(args)
|
7
|
+
if options.any?
|
8
|
+
tk = Keeper.new
|
9
|
+
tk.config(options.delete(:config)) if options[:config]
|
10
|
+
|
11
|
+
if id = options[:remove]
|
12
|
+
tk.delete(id)
|
13
|
+
elsif id = options.delete(:update)
|
14
|
+
tk.update(id, options)
|
15
|
+
else
|
16
|
+
tk.store(options)
|
17
|
+
end
|
18
|
+
else
|
19
|
+
puts options.opts
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.tv(args)
|
24
|
+
options = ViewerOptions.new(args)
|
25
|
+
tv = Viewer.new
|
26
|
+
tv.config(options.delete(:config)) if options[:config]
|
27
|
+
records = tv.all
|
28
|
+
if output = options.delete(:output)
|
29
|
+
Viewer.export(records, output[0], output[1])
|
30
|
+
else
|
31
|
+
puts records
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Timekeeper
|
2
|
+
|
3
|
+
class Viewer
|
4
|
+
|
5
|
+
def config(file="timekeeper.yml")
|
6
|
+
@config ||= YAML.load_file(file)
|
7
|
+
end
|
8
|
+
|
9
|
+
def all
|
10
|
+
tables.collect{|table| table.query.collect{|attrs| Keep.new(attrs)}}.flatten!
|
11
|
+
end
|
12
|
+
|
13
|
+
def close
|
14
|
+
tables.each {|table| table.close}
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.export(records, name="timekeeper", type= :csv)
|
18
|
+
if records.any?
|
19
|
+
case type.to_s
|
20
|
+
when "csv"
|
21
|
+
FasterCSV.open("#{name}.#{type}", "w") do |csv|
|
22
|
+
csv << records[0].keys
|
23
|
+
records.each do |record|
|
24
|
+
csv << record.values
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def tables
|
34
|
+
@tables ||= config["team"].collect{|t| Rufus::Tokyo::Table.new(File.join(config["db_path"],"#{t}-time.tct"))}
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Timekeeper
|
2
|
+
|
3
|
+
class ViewerOptions < Hash
|
4
|
+
attr_reader :opts
|
5
|
+
|
6
|
+
def initialize(args)
|
7
|
+
super()
|
8
|
+
|
9
|
+
@opts = OptionParser.new do |o|
|
10
|
+
o.banner = "Usage: #{File.basename($0)} [options]"
|
11
|
+
|
12
|
+
o.on("--config FILE", "location of your configuration file - default is ./timekeeper.yml") do |file|
|
13
|
+
self[:config] = file
|
14
|
+
end
|
15
|
+
|
16
|
+
o.on("--csv [FILE]", "export to csv") do |file|
|
17
|
+
self[:output] = [(file || "timekeeper"), :csv]
|
18
|
+
end
|
19
|
+
|
20
|
+
o.on('-n', '--name NAME', 'Query on name') do |title|
|
21
|
+
self[:title] = title
|
22
|
+
end
|
23
|
+
|
24
|
+
o.on('-t', '--title TITLE', 'Query on title') do |title|
|
25
|
+
self[:title] = title
|
26
|
+
end
|
27
|
+
|
28
|
+
o.on('-c', '--target TARGET', 'Query on target') do |target|
|
29
|
+
self[:target] = target
|
30
|
+
end
|
31
|
+
|
32
|
+
o.on('-m', '--description DESCRIPTION', 'Query on description') do |description|
|
33
|
+
self[:description] = description
|
34
|
+
end
|
35
|
+
|
36
|
+
o.on('-d', '--date DATE', 'Query on date') do |date|
|
37
|
+
self[:date] = date
|
38
|
+
end
|
39
|
+
|
40
|
+
o.on_tail('-h', '--help', 'Display this help and exit') do
|
41
|
+
puts @opts
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
begin
|
48
|
+
@opts.parse!(args)
|
49
|
+
rescue OptionParser::InvalidOption => e
|
50
|
+
self[:invalid_argument] = e.message
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timekeeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- atog
|
@@ -55,8 +55,11 @@ extra_rdoc_files:
|
|
55
55
|
files:
|
56
56
|
- lib/timekeeper.rb
|
57
57
|
- lib/timekeeper/keep.rb
|
58
|
-
- lib/timekeeper/
|
59
|
-
- lib/timekeeper/
|
58
|
+
- lib/timekeeper/keeper.rb
|
59
|
+
- lib/timekeeper/keeper_options.rb
|
60
|
+
- lib/timekeeper/runner.rb
|
61
|
+
- lib/timekeeper/viewer.rb
|
62
|
+
- lib/timekeeper/viewer_options.rb
|
60
63
|
- LICENSE
|
61
64
|
- README.rdoc
|
62
65
|
has_rdoc: true
|
@@ -1,37 +0,0 @@
|
|
1
|
-
class Timekeeper
|
2
|
-
|
3
|
-
def config(file="timekeeper.yml")
|
4
|
-
@config ||= YAML.load_file(file)
|
5
|
-
end
|
6
|
-
|
7
|
-
def delete(id)
|
8
|
-
table.delete(id)
|
9
|
-
end
|
10
|
-
|
11
|
-
def delete_all
|
12
|
-
table.clear
|
13
|
-
end
|
14
|
-
|
15
|
-
def store(attributes)
|
16
|
-
attributes.store("name", config["name"])
|
17
|
-
attributes.store("date", Date.today) unless attributes["date"]
|
18
|
-
table[table.genuid] = Keep.new(attributes).to_hash
|
19
|
-
end
|
20
|
-
|
21
|
-
def get(id)
|
22
|
-
if attributes = table.lget(id.to_s).values.first
|
23
|
-
Keep.new(attributes)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def update(id, attributes_to_update)
|
28
|
-
if attributes = table.lget(id.to_s).values.first
|
29
|
-
table[id] = Keep.new(attributes).update(attributes_to_update).to_hash
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def table
|
34
|
-
@table ||= Rufus::Tokyo::Table.new(File.join(config["db_path"],"#{config["name"]}-time.tct"))
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
class Timeviewer
|
2
|
-
|
3
|
-
def config(file="timekeeper.yml")
|
4
|
-
@config ||= YAML.load_file(file)
|
5
|
-
end
|
6
|
-
|
7
|
-
def all
|
8
|
-
tables.collect{|table| table.query}.flatten!
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.export(records, name="export", type= :csv)
|
12
|
-
if records.any?
|
13
|
-
case type
|
14
|
-
when :csv
|
15
|
-
FasterCSV.open("#{name}.#{type}", "w") do |csv|
|
16
|
-
csv << records[0].keys
|
17
|
-
records.each do |record|
|
18
|
-
csv << record.values
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def tables
|
28
|
-
@tables ||= config["team"].collect{|t| Rufus::Tokyo::Table.new(File.join(config["db_path"],"#{t}-time.tct"))}
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|