sportdb 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
- ### 0.0.1 / 2012-10-04
1
+ ### 0.1.0 / 2012-10-06
2
2
 
3
3
  * Everything is new. First release
@@ -2,4 +2,11 @@ History.markdown
2
2
  Manifest.txt
3
3
  README.markdown
4
4
  Rakefile
5
+ bin/sportdb
5
6
  lib/sportdb.rb
7
+ lib/sportdb/cli/opts.rb
8
+ lib/sportdb/cli/runner.rb
9
+ lib/sportdb/models.rb
10
+ lib/sportdb/schema.rb
11
+ lib/sportdb/utils.rb
12
+ lib/sportdb/version.rb
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'hoe'
2
- require './lib/sportdb.rb'
2
+ require './lib/sportdb/version.rb'
3
3
 
4
4
  Hoe.spec 'sportdb' do
5
5
 
@@ -17,4 +17,9 @@ Hoe.spec 'sportdb' do
17
17
  self.readme_file = 'README.markdown'
18
18
  self.history_file = 'History.markdown'
19
19
 
20
- end
20
+ end
21
+
22
+ ## todo: add depends for
23
+ ## - activerecord
24
+ ## - ar-sqlite?
25
+ ## - activesupport
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'sportdb'
4
+
5
+ SportDB.main
@@ -1,4 +1,46 @@
1
+ ###
2
+ # NB: for local testing run like:
3
+ #
4
+ # 1.8.x: ruby -Ilib -rrubygems lib/sportdb.rb
5
+ # 1.9.x: ruby -Ilib lib/sportdb.rb
6
+
7
+ # core and stlibs
8
+
9
+ require 'yaml'
10
+ require 'pp'
11
+ require 'logger'
12
+ require 'optparse'
13
+ require 'fileutils'
14
+
15
+ # rubygems
16
+
17
+ require 'active_record' ## todo: add sqlite3? etc.
18
+
19
+
20
+ # our own code
21
+
22
+ require 'sportdb/schema'
23
+ require 'sportdb/models'
24
+ require 'sportdb/utils'
25
+ require 'sportdb/version'
26
+ require 'sportdb/cli/opts'
27
+ require 'sportdb/cli/runner'
1
28
 
2
29
  module SportDB
3
- VERSION = '0.0.1'
4
- end
30
+
31
+ def self.banner
32
+ "sportdb #{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
33
+ end
34
+
35
+ def self.root
36
+ "#{File.expand_path( File.dirname(File.dirname(__FILE__)) )}"
37
+ end
38
+
39
+ def self.main
40
+ Runner.new.run(ARGV)
41
+ end
42
+
43
+ end # module SportDB
44
+
45
+
46
+ SportDB.main if __FILE__ == $0
@@ -0,0 +1,35 @@
1
+ module SportDB
2
+
3
+ class Opts
4
+
5
+ def create=(boolean)
6
+ @create = boolean
7
+ end
8
+
9
+ def create?
10
+ return false if @create.nil? # default create flag is false
11
+ @create == true
12
+ end
13
+
14
+
15
+ def output_path=(value)
16
+ @output_path = value
17
+ end
18
+
19
+ def output_path
20
+ @output_path || '.'
21
+ end
22
+
23
+
24
+ def data_path=(value)
25
+ @data_path = value
26
+ end
27
+
28
+ def data_path
29
+ @data_path || '.'
30
+ end
31
+
32
+
33
+ end # class Opts
34
+
35
+ end # module SportDB
@@ -0,0 +1,130 @@
1
+
2
+ module SportDB
3
+
4
+ class Runner
5
+
6
+ def initialize
7
+ @logger = Logger.new(STDOUT)
8
+ @logger.level = Logger::INFO
9
+
10
+ @opts = Opts.new
11
+ end
12
+
13
+ attr_reader :logger, :opts
14
+
15
+ def run( args )
16
+ opt=OptionParser.new do |cmd|
17
+
18
+ cmd.banner = "Usage: sportdb [options]"
19
+
20
+ ## todo: change to different flag?? use -c/--config ???
21
+ cmd.on( '-c', '--create', 'Create DB Schema' ) { opts.create = true }
22
+
23
+ cmd.on( '-o', '--output PATH', "Output Path (default is #{opts.output_path})" ) { |path| opts.output_path = path }
24
+
25
+ ### todo: in future allow multiple search path??
26
+ cmd.on( '-i', '--include PATH', "Data Path (default is #{opts.data_path})" ) { |path| opts.data_path = path }
27
+
28
+ cmd.on( '-v', '--version', "Show version" ) do
29
+ puts SportDB.banner
30
+ exit
31
+ end
32
+
33
+ cmd.on( "--verbose", "Show debug trace" ) do
34
+ logger.datetime_format = "%H:%H:%S"
35
+ logger.level = Logger::DEBUG
36
+
37
+ ## todo: set ActiveRecord Logger to stdout??
38
+ end
39
+
40
+ cmd.on_tail( "-h", "--help", "Show this message" ) do
41
+ puts <<EOS
42
+
43
+ sportdb - sport.db command line tool
44
+
45
+ #{cmd.help}
46
+
47
+ Examples:
48
+ sportdb cl/teams cl/2012_13/cl # import champions league (cl)
49
+ sportdb -c # create database schema
50
+
51
+ More Examples:
52
+ sportdb # show stats (table counts, table props)
53
+ sportdb -i ../sport.db/db cl/teams cl/2012_13/cl # import champions league (cl) in db folder
54
+
55
+ Further information:
56
+ http://geraldb.github.com/sport.db
57
+
58
+ EOS
59
+ exit
60
+ end
61
+ end
62
+
63
+ opt.parse!( args )
64
+
65
+ puts SportDB.banner
66
+
67
+ puts "working directory: #{Dir.pwd}"
68
+
69
+ db_config = {
70
+ :adapter => 'sqlite3',
71
+ :database => "#{opts.output_path}/sport.db"
72
+ }
73
+
74
+ puts "Connecting to db using settings: "
75
+ pp db_config
76
+
77
+ ActiveRecord::Base.establish_connection( db_config )
78
+
79
+ if opts.create?
80
+ CreateDB.up
81
+ end
82
+
83
+ args.each do |arg|
84
+ name = arg # File.basename( arg, '.*' )
85
+ path = "#{opts.data_path}/#{name}.rb"
86
+
87
+ puts "*** loading data '#{name}' (#{path})..."
88
+
89
+ text = File.read( path )
90
+
91
+ SportDB.module_eval( text )
92
+
93
+ # NB: same as
94
+ #
95
+ # module SportDB
96
+ # <code here>
97
+ # end
98
+
99
+ # require path
100
+ # require "#{Dir.pwd}/db/#{seed}.rb"
101
+
102
+ # Prop.create!( :key => "db.#{name}.version", :value => SportDB::VERSION )
103
+
104
+ end
105
+
106
+ dump_stats
107
+ dump_props
108
+
109
+ puts 'Done.'
110
+
111
+ end # method run
112
+
113
+ def dump_stats
114
+ # todo: use %5d or similar to format string
115
+ puts "Stats:"
116
+ puts " #{Event.count} events"
117
+ puts " #{Team.count} teams"
118
+ puts " #{Game.count} games"
119
+ end
120
+
121
+ def dump_props
122
+ # todo: use %5 or similar to format string
123
+ puts "Props:"
124
+ Prop.order( 'created_at asc' ).all.each do |prop|
125
+ puts " #{prop.key} / #{prop.value} || #{prop.created_at}"
126
+ end
127
+ end
128
+
129
+ end # class Runner
130
+ end # module SportDB
@@ -0,0 +1,215 @@
1
+ module SportDB
2
+
3
+ class Team < ActiveRecord::Base
4
+
5
+ has_many :home_games, :class_name => 'Game', :foreign_key => 'team1_id'
6
+ has_many :away_games, :class_name => 'Game', :foreign_key => 'team2_id'
7
+
8
+
9
+ def self.create_from_ary!( teams )
10
+ teams.each do |values|
11
+
12
+ ## key & title required
13
+ attr = {
14
+ :key => values[0],
15
+ :title => values[1]
16
+ }
17
+
18
+ ## check for optional values
19
+ values[2..-1].each do |value|
20
+ if value.length == 3 ## assume its a tag (three latters)
21
+ attr[ :tag ] = value
22
+ else
23
+ attr[ :title2 ] = value
24
+ end
25
+ end
26
+
27
+ Team.create!( attr )
28
+ end # each team
29
+ end
30
+
31
+ def key
32
+ #todo/fix: generate_key w/ on save callback
33
+
34
+ # generate key if necessary (for debugging only - should be not null field!)
35
+ value = read_attribute(:key)
36
+ value = "?#{title.downcase.gsub( /\s/, '_').gsub( /[^a-z0-9_]/, '*' )}?" if value.blank?
37
+ value
38
+ end
39
+
40
+ end # class Team
41
+
42
+
43
+ class Game < ActiveRecord::Base
44
+
45
+ belongs_to :team1, :class_name => 'Team', :foreign_key => 'team1_id'
46
+ belongs_to :team2, :class_name => 'Team', :foreign_key => 'team2_id'
47
+
48
+ belongs_to :round
49
+ belongs_to :group # group is optional
50
+
51
+ before_save :calc_toto12x
52
+
53
+
54
+ def self.create_knockouts_from_ary!( games, round )
55
+ Game.create_from_ary!( games, round, true )
56
+ end
57
+
58
+ def self.create_from_ary!( games, round, knockout=false )
59
+ games.each do |values|
60
+ Game.create!(
61
+ :round =>round,
62
+ :pos =>values[0],
63
+ :team1 =>values[1],
64
+ :score1 =>values[2][0],
65
+ :score2 =>values[2][1],
66
+ :score3 =>values[2][2],
67
+ :score4 =>values[2][3],
68
+ :score5 =>values[2][4],
69
+ :score6 =>values[2][5],
70
+ :team2 =>values[3],
71
+ :play_at =>values[4],
72
+ :group =>values[5], # Note: group is optional (may be null/nil)
73
+ :knockout =>knockout )
74
+ end # each games
75
+ end
76
+
77
+ def self.create_pairs_from_ary_for_group!( pairs, group )
78
+
79
+ pairs.each do |pair|
80
+ game1_attribs = {
81
+ :round =>pair[0][5],
82
+ :pos =>pair[0][0],
83
+ :team1 =>pair[0][1],
84
+ :score1 =>pair[0][2][0],
85
+ :score2 =>pair[0][2][1],
86
+ :team2 =>pair[0][3],
87
+ :play_at =>pair[0][4],
88
+ :group =>group }
89
+
90
+ game2_attribs = {
91
+ :round =>pair[1][5],
92
+ :pos =>pair[1][0],
93
+ :team1 =>pair[1][1],
94
+ :score1 =>pair[1][2][0],
95
+ :score2 =>pair[1][2][1],
96
+ :team2 =>pair[1][3],
97
+ :play_at =>pair[1][4],
98
+ :group =>group }
99
+
100
+ game1 = Game.create!( game1_attribs )
101
+ game2 = Game.create!( game2_attribs )
102
+
103
+ # linkup games
104
+ game1.next_game_id = game2.id
105
+ game1.save!
106
+
107
+ game2.prev_game_id = game1.id
108
+ game2.save!
109
+ end # each pair
110
+ end
111
+
112
+ def self.create_knockout_pairs_from_ary!( pairs, round1, round2 )
113
+
114
+ pairs.each do |pair|
115
+ game1_attribs = {
116
+ :round =>round1,
117
+ :pos =>pair[0][0],
118
+ :team1 =>pair[0][1],
119
+ :score1 =>pair[0][2][0],
120
+ :score2 =>pair[0][2][1],
121
+ :team2 =>pair[0][3],
122
+ :play_at =>pair[0][4] }
123
+
124
+ game2_attribs = {
125
+ :round =>round2,
126
+ :pos =>pair[1][0],
127
+ :team1 =>pair[1][1],
128
+ :score1 =>pair[1][2][0],
129
+ :score2 =>pair[1][2][1],
130
+ :score3 =>pair[1][2][2],
131
+ :score4 =>pair[1][2][3],
132
+ :score5 =>pair[1][2][4],
133
+ :score6 =>pair[1][2][5],
134
+ :team2 =>pair[1][3],
135
+ :play_at =>pair[1][4],
136
+ :knockout =>true }
137
+
138
+ game1 = Game.create!( game1_attribs )
139
+ game2 = Game.create!( game2_attribs )
140
+
141
+ # linkup games
142
+ game1.next_game_id = game2.id
143
+ game1.save!
144
+
145
+ game2.prev_game_id = game1.id
146
+ game2.save!
147
+ end # each pair
148
+ end
149
+
150
+ def calc_toto12x
151
+ if score1.nil? || score2.nil?
152
+ self.toto12x = nil
153
+ elsif score1 == score2
154
+ self.toto12x = 'X'
155
+ elsif score1 > score2
156
+ self.toto12x = '1'
157
+ elsif score1 < score2
158
+ self.toto12x = '2'
159
+ end
160
+ end
161
+
162
+ end # class Game
163
+
164
+
165
+ class Event < ActiveRecord::Base
166
+
167
+ has_many :rounds, :order => 'pos' # all (fix and flex) rounds
168
+
169
+ has_many :groups, :order => 'pos'
170
+
171
+ has_many :event_teams, :class_name => 'EventTeam'
172
+ has_many :teams, :through => :event_teams
173
+
174
+ end # class Event
175
+
176
+
177
+ class EventTeam < ActiveRecord::Base
178
+ self.table_name = 'events_teams'
179
+
180
+ belongs_to :event
181
+ belongs_to :team
182
+ end
183
+
184
+ class Group < ActiveRecord::Base
185
+
186
+ has_many :games, :order => 'pos'
187
+ belongs_to :event
188
+
189
+ has_many :group_teams, :class_name => 'GroupTeam'
190
+ has_many :teams, :through => :group_teams
191
+
192
+ end # class Group
193
+
194
+ class GroupTeam < ActiveRecord::Base
195
+ self.table_name = 'groups_teams'
196
+
197
+ belongs_to :group
198
+ belongs_to :team
199
+ end
200
+
201
+
202
+ class Round < ActiveRecord::Base
203
+
204
+ has_many :games, :order => 'pos'
205
+ belongs_to :event
206
+
207
+ end # class Round
208
+
209
+
210
+ class Prop < ActiveRecord::Base
211
+
212
+ end # class Prop
213
+
214
+
215
+ end # module SportDB
@@ -0,0 +1,118 @@
1
+
2
+ module SportDB
3
+
4
+ class CreateDB
5
+
6
+ def self.up
7
+
8
+ ActiveRecord::Schema.define do
9
+
10
+ create_table :props do |t|
11
+ t.string :key, :null => false
12
+ t.string :value, :null => false
13
+ t.timestamps
14
+ end
15
+
16
+ create_table :teams do |t|
17
+ t.string :title, :null => false
18
+ t.string :title2
19
+ t.string :key, :null => false # import/export key
20
+ t.string :tag # make it not null? - three letter tag (short title)
21
+ t.timestamps
22
+ end
23
+
24
+ add_index :teams, :key, :unique => true
25
+
26
+
27
+ create_table :events do |t|
28
+ t.string :title, :null => false
29
+ t.string :key, :null => false # import/export key
30
+ t.datetime :start_at, :null => false
31
+ t.timestamps
32
+ end
33
+
34
+ add_index :events, :key, :unique => true
35
+
36
+
37
+ create_table :rounds do |t|
38
+ t.references :event, :null => false
39
+ t.string :title, :null => false
40
+ t.string :title2
41
+ t.integer :pos, :null => false
42
+ t.boolean :playoff, :null => false, :default => false # "regular" season (group) games or post-season (playoff) knockouts (k.o's)
43
+ t.timestamps
44
+ end
45
+
46
+ add_index :rounds, :event_id # fk event_id index
47
+
48
+
49
+ create_table :groups do |t| # Teamgruppe (zB Gruppe A, Gruppe B, etc.)
50
+ t.references :event, :null => false
51
+ t.string :title, :null => false
52
+ t.integer :pos, :null => false
53
+ t.timestamps
54
+ end
55
+
56
+ add_index :groups, :event_id # fk event_id index
57
+
58
+
59
+ create_table :games do |t|
60
+ t.references :round, :null => false
61
+ t.integer :pos, :null => false
62
+ t.references :group # note: group is optional
63
+ t.references :team1, :null => false
64
+ t.references :team2, :null => false
65
+ t.datetime :play_at, :null => false
66
+ t.boolean :knockout, :null => false, :default => false
67
+ t.boolean :home, :null => false, :default => true # is team1 play at home (that is, at its home stadium)
68
+ t.integer :score1
69
+ t.integer :score2
70
+ t.integer :score3 # verlaengerung (opt)
71
+ t.integer :score4
72
+ t.integer :score5 # elfmeter (opt)
73
+ t.integer :score6
74
+ t.references :next_game # for hinspiel bei rueckspiel in knockout game
75
+ t.references :prev_game
76
+ t.string :toto12x # 1,2,X,nil calculate on save
77
+ t.string :key # import/export key
78
+ t.timestamps
79
+ end
80
+
81
+ add_index :games, :key, :unique => true
82
+ add_index :games, :round_id # fk round_id index
83
+ add_index :games, :group_id # fk group_id index
84
+ add_index :games, :next_game_id # fk next_game_id index
85
+ add_index :games, :prev_game_id # fk next_game_id index
86
+
87
+
88
+
89
+ # todo: remove id from join table (without extra fields)? why?? why not??
90
+ create_table :events_teams do |t|
91
+ t.references :event, :null => false
92
+ t.references :team, :null => false
93
+ t.timestamps
94
+ end
95
+
96
+ add_index :events_teams, [:event_id,:team_id], :unique => true
97
+ add_index :events_teams, :event_id
98
+
99
+
100
+ create_table :groups_teams do |t|
101
+ t.references :group, :null => false
102
+ t.references :team, :null => false
103
+ t.timestamps
104
+ end
105
+
106
+ add_index :groups_teams, [:group_id,:team_id], :unique => true
107
+ add_index :groups_teams, :group_id
108
+
109
+ end # block Schema.define
110
+
111
+
112
+ Prop.create!( :key => 'db.schema.version', :value => SportDB::VERSION )
113
+
114
+ end # method up
115
+
116
+ end # class CreateDB
117
+
118
+ end # module SportDB
@@ -0,0 +1,19 @@
1
+
2
+ ### some utils
3
+
4
+ class Time
5
+
6
+ def self.cet( str ) # central european time (cet) + central european summer time (cest)
7
+ ActiveSupport::TimeZone['Vienna'].parse( str )
8
+ end
9
+
10
+ def self.eet( str ) # eastern european time (eet) + 2 hours
11
+ ActiveSupport::TimeZone['Bucharest'].parse( str )
12
+ end
13
+
14
+ def self.cst( str ) # central standard time (cst) - 6 hours
15
+ ActiveSupport::TimeZone['Mexico City'].parse( str )
16
+ end
17
+
18
+ end # class Time
19
+
@@ -0,0 +1,4 @@
1
+
2
+ module SportDB
3
+ VERSION = '0.1.0'
4
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sportdb
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 0
9
8
  - 1
10
- version: 0.0.1
9
+ - 0
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Gerald Bauer
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-10-04 00:00:00 Z
18
+ date: 2012-10-06 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rdoc
@@ -49,8 +49,8 @@ dependencies:
49
49
  version_requirements: *id002
50
50
  description: sportdb - sport.db command line tool
51
51
  email: opensport@googlegroups.com
52
- executables: []
53
-
52
+ executables:
53
+ - sportdb
54
54
  extensions: []
55
55
 
56
56
  extra_rdoc_files:
@@ -60,7 +60,14 @@ files:
60
60
  - Manifest.txt
61
61
  - README.markdown
62
62
  - Rakefile
63
+ - bin/sportdb
63
64
  - lib/sportdb.rb
65
+ - lib/sportdb/cli/opts.rb
66
+ - lib/sportdb/cli/runner.rb
67
+ - lib/sportdb/models.rb
68
+ - lib/sportdb/schema.rb
69
+ - lib/sportdb/utils.rb
70
+ - lib/sportdb/version.rb
64
71
  homepage: http://geraldb.github.com/sport.db
65
72
  licenses: []
66
73