footty 0.4.1 → 2024.5.10
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -3
- data/Manifest.txt +0 -3
- data/README.md +74 -86
- data/Rakefile +30 -30
- data/bin/footty +8 -5
- data/lib/footty/client.rb +106 -106
- data/lib/footty/version.rb +14 -14
- data/lib/footty.rb +161 -160
- metadata +7 -10
- data/test/helper.rb +0 -10
- data/test/test_client_euro.rb +0 -103
- data/test/test_client_worldcup.rb +0 -164
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34ac44dbe56d51fad5a516b69331ab594243cbac79f5c4b63f69271455773cd5
|
4
|
+
data.tar.gz: 428605f76f7713f3e61f8cf53cf80d5c8c3d6add43f649a0d701e9ca465d4259
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 359ab0cc33ca8b8482a1d2e9cb60ea58e96c95c5494dc35232018dba09fe164f22a8a167afc1536e90ed9dabb600fe412fab6d0c7aa1a4afa3e3967e3c857907
|
7
|
+
data.tar.gz: 344366274d54e0721d8a718af983dd555009db88a8d11f89e56149bef17cb24ff23e17c772ca133a31bef0e0ac65a1dc68207b45e3c9a4c9c429241d30398599
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
-
###
|
2
|
-
|
3
|
-
|
1
|
+
### 2024.5.10
|
2
|
+
### 1.0.0 / 2018-06-09
|
3
|
+
|
4
|
+
* Everything is new (again). First release.
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -1,86 +1,74 @@
|
|
1
|
-
# footty - football.db command line client for european ("euro") championship
|
2
|
-
|
3
|
-
* home :: [github.com/sportdb/footty](https://github.com/sportdb/footty)
|
4
|
-
* bugs :: [github.com/sportdb/footty/issues](https://github.com/sportdb/footty/issues)
|
5
|
-
* gem :: [rubygems.org/gems/footty](https://rubygems.org/gems/footty)
|
6
|
-
* rdoc :: [rubydoc.info/gems/footty](http://rubydoc.info/gems/footty)
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
Use `
|
39
|
-
|
40
|
-
$ footty
|
41
|
-
$ footty
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
## License
|
77
|
-
|
78
|
-
The `footty` scripts are dedicated to the public domain.
|
79
|
-
Use it as you please with no restrictions whatsoever.
|
80
|
-
|
81
|
-
|
82
|
-
## Questions? Comments?
|
83
|
-
|
84
|
-
Send them along to the
|
85
|
-
[Open Sports & Friends Forum/Mailing List](http://groups.google.com/group/opensport).
|
86
|
-
Thanks!
|
1
|
+
# footty - football.db command line client for european ("euro") championship 2024 and more
|
2
|
+
|
3
|
+
* home :: [github.com/sportdb/footty](https://github.com/sportdb/footty)
|
4
|
+
* bugs :: [github.com/sportdb/footty/issues](https://github.com/sportdb/footty/issues)
|
5
|
+
* gem :: [rubygems.org/gems/footty](https://rubygems.org/gems/footty)
|
6
|
+
* rdoc :: [rubydoc.info/gems/footty](http://rubydoc.info/gems/footty)
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
## Usage - Who's playing today?
|
13
|
+
|
14
|
+
The footty command line tool lets you query the online football.db HTTP JSON API services
|
15
|
+
for upcoming or past matches. For example:
|
16
|
+
|
17
|
+
$ footty # Defaults to today's euro 2024 matches
|
18
|
+
|
19
|
+
prints on Jun/14 2024:
|
20
|
+
|
21
|
+
#1 Fri Jun/14 Germany (GER) vs Scotland (SCO) Group A / Matchday 1
|
22
|
+
|
23
|
+
Use `tomorrow` or `t` or `+1` to print tomorrow's matches e.g.:
|
24
|
+
|
25
|
+
$ footty tomorrow # -or-
|
26
|
+
$ footty t
|
27
|
+
|
28
|
+
Use `yesterday` or `y` or `-1` to print yesterday's matches e.g.:
|
29
|
+
|
30
|
+
$ footty yesterday # -or-
|
31
|
+
$ footty y
|
32
|
+
|
33
|
+
Use `upcoming` or `up` or `u` to print all upcoming matches e.g.:
|
34
|
+
|
35
|
+
$ footty upcoming # -or-
|
36
|
+
$ footty up
|
37
|
+
|
38
|
+
Use `past` or `p` to print all past matches e.g.:
|
39
|
+
|
40
|
+
$ footty past # -or-
|
41
|
+
$ footty p
|
42
|
+
|
43
|
+
|
44
|
+
That's it. Enjoy the beautiful game.
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
## Trivia
|
50
|
+
|
51
|
+
Why tty? tty stands for teletype (tty) writer and is the old traditional (short) name for the unix command line.
|
52
|
+
|
53
|
+
|
54
|
+
## Install
|
55
|
+
|
56
|
+
Just install the gem:
|
57
|
+
|
58
|
+
$ gem install footty
|
59
|
+
|
60
|
+
|
61
|
+
## License
|
62
|
+
|
63
|
+
The `footty` scripts are dedicated to the public domain.
|
64
|
+
Use it as you please with no restrictions whatsoever.
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
## Questions? Comments?
|
71
|
+
|
72
|
+
Yes, you can. More than welcome.
|
73
|
+
See [Help & Support »](https://github.com/openfootball/help)
|
74
|
+
|
data/Rakefile
CHANGED
@@ -1,30 +1,30 @@
|
|
1
|
-
require 'hoe'
|
2
|
-
require './lib/footty/version.rb'
|
3
|
-
|
4
|
-
Hoe.spec 'footty' do
|
5
|
-
|
6
|
-
self.version = Footty::VERSION
|
7
|
-
|
8
|
-
self.summary = 'footty - football.db command line client for european "euro" championship
|
9
|
-
self.description = summary
|
10
|
-
|
11
|
-
self.urls = { home: 'https://github.com/sportdb/footty' }
|
12
|
-
|
13
|
-
self.author = 'Gerald Bauer'
|
14
|
-
self.email = 'opensport@googlegroups.com'
|
15
|
-
|
16
|
-
# switch extension to .markdown for gihub formatting
|
17
|
-
self.readme_file = 'README.md'
|
18
|
-
self.history_file = 'CHANGELOG.md'
|
19
|
-
|
20
|
-
self.extra_deps = [
|
21
|
-
['logutils' ],
|
22
|
-
['fetcher']
|
23
|
-
]
|
24
|
-
|
25
|
-
self.licenses = ['Public Domain']
|
26
|
-
|
27
|
-
self.spec_extras = {
|
28
|
-
required_ruby_version: '>= 2.3'
|
29
|
-
}
|
30
|
-
end
|
1
|
+
require 'hoe'
|
2
|
+
require './lib/footty/version.rb'
|
3
|
+
|
4
|
+
Hoe.spec 'footty' do
|
5
|
+
|
6
|
+
self.version = Footty::VERSION
|
7
|
+
|
8
|
+
self.summary = 'footty - football.db command line client for european "euro" championship 2024 and more - who is playing today?'
|
9
|
+
self.description = summary
|
10
|
+
|
11
|
+
self.urls = { home: 'https://github.com/sportdb/footty' }
|
12
|
+
|
13
|
+
self.author = 'Gerald Bauer'
|
14
|
+
self.email = 'opensport@googlegroups.com'
|
15
|
+
|
16
|
+
# switch extension to .markdown for gihub formatting
|
17
|
+
self.readme_file = 'README.md'
|
18
|
+
self.history_file = 'CHANGELOG.md'
|
19
|
+
|
20
|
+
self.extra_deps = [
|
21
|
+
['logutils' ],
|
22
|
+
['fetcher']
|
23
|
+
]
|
24
|
+
|
25
|
+
self.licenses = ['Public Domain']
|
26
|
+
|
27
|
+
self.spec_extras = {
|
28
|
+
required_ruby_version: '>= 2.3'
|
29
|
+
}
|
30
|
+
end
|
data/bin/footty
CHANGED
data/lib/footty/client.rb
CHANGED
@@ -1,106 +1,106 @@
|
|
1
|
-
module Footty
|
2
|
-
|
3
|
-
|
4
|
-
class Client
|
5
|
-
|
6
|
-
include LogUtils::Logging
|
7
|
-
|
8
|
-
|
9
|
-
def initialize( league:, year: )
|
10
|
-
@worker = Fetcher::Worker.new
|
11
|
-
|
12
|
-
@league = league
|
13
|
-
@year = year
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
|
-
APIS = {
|
18
|
-
worldcup: 'https://github.com/openfootball/worldcup.json/raw/master/$year$/worldcup.json',
|
19
|
-
euro: 'https://github.com/openfootball/euro.json/raw/master/$year$/euro.json'
|
20
|
-
}
|
21
|
-
|
22
|
-
### note:
|
23
|
-
## cache ALL methods - only do one web request for match schedule & results
|
24
|
-
def get_matches
|
25
|
-
@data ||= begin
|
26
|
-
str = APIS[ @league.downcase.to_sym ]
|
27
|
-
str = str.gsub( '$year$', @year.to_s )
|
28
|
-
|
29
|
-
get( str ) ## use "memoized" / cached result
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
## for testing lets you use /round/1 etc.
|
37
|
-
def round( num )
|
38
|
-
h = get_matches
|
39
|
-
matches = h[ 'rounds' ][ num-1 ] ## note: rounds hash starts with zero (not 1)
|
40
|
-
matches
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
def todays_matches( date: Date.today ) matches_for( date ); end
|
45
|
-
def tomorrows_matches( date: Date.today ) matches_for( date+1 ); end
|
46
|
-
def yesterdays_matches( date: Date.today ) matches_for( date-1 ); end
|
47
|
-
|
48
|
-
def matches_for( date )
|
49
|
-
hash = get_matches
|
50
|
-
matches = select_matches( hash[ 'rounds' ] ) { |match| date == Date.parse( match['date'] ) }
|
51
|
-
matches
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
def upcoming_matches( date: Date.today )
|
56
|
-
## note: includes todays matches for now
|
57
|
-
hash = get_matches
|
58
|
-
matches = select_matches( hash[ 'rounds' ] ) { |match| date <= Date.parse( match['date'] ) }
|
59
|
-
matches
|
60
|
-
end
|
61
|
-
|
62
|
-
def past_matches( date: Date.today )
|
63
|
-
hash = get_matches
|
64
|
-
matches = select_matches( hash[ 'rounds' ] ) { |match| date > Date.parse( match['date'] ) }
|
65
|
-
## note reveserve matches (chronological order/last first)
|
66
|
-
matches.reverse
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
def select_matches( rounds )
|
72
|
-
matches = []
|
73
|
-
rounds.each do |round|
|
74
|
-
round['matches'].each do |match|
|
75
|
-
if yield( match )
|
76
|
-
## hack: add (outer) round to match
|
77
|
-
match['round'] = round['name']
|
78
|
-
matches << match
|
79
|
-
else
|
80
|
-
## puts " skipping game play_date #{play_date}"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
matches
|
85
|
-
end
|
86
|
-
|
87
|
-
|
88
|
-
def get( str )
|
89
|
-
response = @worker.get_response( str )
|
90
|
-
|
91
|
-
if response.code == '200'
|
92
|
-
##
|
93
|
-
## fix/fix/todo/check:
|
94
|
-
## do we need to force utf-8 encoding? yes!!!!
|
95
|
-
## check for teams w/ non-ascii names
|
96
|
-
hash = JSON.parse( response.body )
|
97
|
-
## pp hash
|
98
|
-
hash
|
99
|
-
else
|
100
|
-
logger.error "fetch HTTP - #{response.code} #{response.message}"
|
101
|
-
nil
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
end # class Client
|
106
|
-
end # module Footty
|
1
|
+
module Footty
|
2
|
+
|
3
|
+
|
4
|
+
class Client
|
5
|
+
|
6
|
+
include LogUtils::Logging
|
7
|
+
|
8
|
+
|
9
|
+
def initialize( league:, year: )
|
10
|
+
@worker = Fetcher::Worker.new
|
11
|
+
|
12
|
+
@league = league
|
13
|
+
@year = year
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
APIS = {
|
18
|
+
worldcup: 'https://github.com/openfootball/worldcup.json/raw/master/$year$/worldcup.json',
|
19
|
+
euro: 'https://github.com/openfootball/euro.json/raw/master/$year$/euro.json'
|
20
|
+
}
|
21
|
+
|
22
|
+
### note:
|
23
|
+
## cache ALL methods - only do one web request for match schedule & results
|
24
|
+
def get_matches
|
25
|
+
@data ||= begin
|
26
|
+
str = APIS[ @league.downcase.to_sym ]
|
27
|
+
str = str.gsub( '$year$', @year.to_s )
|
28
|
+
|
29
|
+
get( str ) ## use "memoized" / cached result
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
## for testing lets you use /round/1 etc.
|
37
|
+
def round( num )
|
38
|
+
h = get_matches
|
39
|
+
matches = h[ 'rounds' ][ num-1 ] ## note: rounds hash starts with zero (not 1)
|
40
|
+
matches
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def todays_matches( date: Date.today ) matches_for( date ); end
|
45
|
+
def tomorrows_matches( date: Date.today ) matches_for( date+1 ); end
|
46
|
+
def yesterdays_matches( date: Date.today ) matches_for( date-1 ); end
|
47
|
+
|
48
|
+
def matches_for( date )
|
49
|
+
hash = get_matches
|
50
|
+
matches = select_matches( hash[ 'rounds' ] ) { |match| date == Date.parse( match['date'] ) }
|
51
|
+
matches
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def upcoming_matches( date: Date.today )
|
56
|
+
## note: includes todays matches for now
|
57
|
+
hash = get_matches
|
58
|
+
matches = select_matches( hash[ 'rounds' ] ) { |match| date <= Date.parse( match['date'] ) }
|
59
|
+
matches
|
60
|
+
end
|
61
|
+
|
62
|
+
def past_matches( date: Date.today )
|
63
|
+
hash = get_matches
|
64
|
+
matches = select_matches( hash[ 'rounds' ] ) { |match| date > Date.parse( match['date'] ) }
|
65
|
+
## note reveserve matches (chronological order/last first)
|
66
|
+
matches.reverse
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def select_matches( rounds )
|
72
|
+
matches = []
|
73
|
+
rounds.each do |round|
|
74
|
+
round['matches'].each do |match|
|
75
|
+
if yield( match )
|
76
|
+
## hack: add (outer) round to match
|
77
|
+
match['round'] = round['name']
|
78
|
+
matches << match
|
79
|
+
else
|
80
|
+
## puts " skipping game play_date #{play_date}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
matches
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
def get( str )
|
89
|
+
response = @worker.get_response( str )
|
90
|
+
|
91
|
+
if response.code == '200'
|
92
|
+
##
|
93
|
+
## fix/fix/todo/check:
|
94
|
+
## do we need to force utf-8 encoding? yes!!!!
|
95
|
+
## check for teams w/ non-ascii names
|
96
|
+
hash = JSON.parse( response.body )
|
97
|
+
## pp hash
|
98
|
+
hash
|
99
|
+
else
|
100
|
+
logger.error "fetch HTTP - #{response.code} #{response.message}"
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end # class Client
|
106
|
+
end # module Footty
|
data/lib/footty/version.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
|
2
|
-
module Footty
|
3
|
-
VERSION = '
|
4
|
-
|
5
|
-
def self.banner
|
6
|
-
"footty/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.root
|
10
|
-
File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
|
1
|
+
|
2
|
+
module Footty
|
3
|
+
VERSION = '2024.5.10'
|
4
|
+
|
5
|
+
def self.banner
|
6
|
+
"footty/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.root
|
10
|
+
File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
data/lib/footty.rb
CHANGED
@@ -1,160 +1,161 @@
|
|
1
|
-
## stdlibs
|
2
|
-
|
3
|
-
require 'net/http'
|
4
|
-
require 'uri'
|
5
|
-
require 'json'
|
6
|
-
require 'pp'
|
7
|
-
|
8
|
-
|
9
|
-
## 3rd party gems/libs
|
10
|
-
## require 'props'
|
11
|
-
|
12
|
-
require 'logutils'
|
13
|
-
require 'fetcher'
|
14
|
-
|
15
|
-
|
16
|
-
# our own code
|
17
|
-
require 'footty/version' # let it always go first
|
18
|
-
require 'footty/client'
|
19
|
-
|
20
|
-
|
21
|
-
module Footty
|
22
|
-
|
23
|
-
def self.client
|
24
|
-
## note: hard code tournament / league for now
|
25
|
-
@client ||= Client.new( league: 'euro', year:
|
26
|
-
end
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def self.main
|
31
|
-
puts banner # say hello
|
32
|
-
|
33
|
-
what = ARGV[0] || 'today'
|
34
|
-
what = what.downcase
|
35
|
-
|
36
|
-
## in the future make today "configurable" as param - why? why not?
|
37
|
-
today = Date.today
|
38
|
-
|
39
|
-
if ['yesterday', 'y', '-1'].include?( what )
|
40
|
-
matches = client.yesterdays_matches
|
41
|
-
if matches.empty?
|
42
|
-
puts "** No matches played yesterday.\n"
|
43
|
-
end
|
44
|
-
elsif ['tomorrow', 't', '+1', '1'].include?( what )
|
45
|
-
matches = client.tomorrows_matches
|
46
|
-
if matches.empty?
|
47
|
-
puts "** No matches scheduled tomorrow.\n"
|
48
|
-
end
|
49
|
-
elsif ['past', 'p', 'prev'].include?( what )
|
50
|
-
matches = client.past_matches
|
51
|
-
if matches.empty?
|
52
|
-
puts "** No matches played yet.\n"
|
53
|
-
end
|
54
|
-
elsif ['upcoming', 'up', 'u', 'next', 'n'].include?( what )
|
55
|
-
matches = client.upcoming_matches
|
56
|
-
if matches.empty?
|
57
|
-
puts "** No more matches scheduled.\n"
|
58
|
-
end
|
59
|
-
else
|
60
|
-
matches = client.todays_matches
|
61
|
-
|
62
|
-
## no matches today
|
63
|
-
if matches.empty?
|
64
|
-
puts "** No matches scheduled today.\n"
|
65
|
-
|
66
|
-
## note: was world cup 2018 - end date -- Date.new( 2018, 7, 11 )
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
##
|
103
|
-
|
104
|
-
|
105
|
-
print "
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
print "
|
130
|
-
print "
|
131
|
-
print "
|
132
|
-
print "'"
|
133
|
-
print "
|
134
|
-
print " (
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
print "
|
144
|
-
print "
|
145
|
-
print "'"
|
146
|
-
print "
|
147
|
-
print " (
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
1
|
+
## stdlibs
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
require 'json'
|
6
|
+
require 'pp'
|
7
|
+
|
8
|
+
|
9
|
+
## 3rd party gems/libs
|
10
|
+
## require 'props'
|
11
|
+
|
12
|
+
require 'logutils'
|
13
|
+
require 'fetcher'
|
14
|
+
|
15
|
+
|
16
|
+
# our own code
|
17
|
+
require 'footty/version' # let it always go first
|
18
|
+
require 'footty/client'
|
19
|
+
|
20
|
+
|
21
|
+
module Footty
|
22
|
+
|
23
|
+
def self.client
|
24
|
+
## note: hard code tournament / league for now
|
25
|
+
@client ||= Client.new( league: 'euro', year: 2024 ) ## use "singelton" / shared client
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
def self.main
|
31
|
+
puts banner # say hello
|
32
|
+
|
33
|
+
what = ARGV[0] || 'today'
|
34
|
+
what = what.downcase
|
35
|
+
|
36
|
+
## in the future make today "configurable" as param - why? why not?
|
37
|
+
today = Date.today
|
38
|
+
|
39
|
+
if ['yesterday', 'y', '-1'].include?( what )
|
40
|
+
matches = client.yesterdays_matches
|
41
|
+
if matches.empty?
|
42
|
+
puts "** No matches played yesterday.\n"
|
43
|
+
end
|
44
|
+
elsif ['tomorrow', 't', '+1', '1'].include?( what )
|
45
|
+
matches = client.tomorrows_matches
|
46
|
+
if matches.empty?
|
47
|
+
puts "** No matches scheduled tomorrow.\n"
|
48
|
+
end
|
49
|
+
elsif ['past', 'p', 'prev'].include?( what )
|
50
|
+
matches = client.past_matches
|
51
|
+
if matches.empty?
|
52
|
+
puts "** No matches played yet.\n"
|
53
|
+
end
|
54
|
+
elsif ['upcoming', 'up', 'u', 'next', 'n'].include?( what )
|
55
|
+
matches = client.upcoming_matches
|
56
|
+
if matches.empty?
|
57
|
+
puts "** No more matches scheduled.\n"
|
58
|
+
end
|
59
|
+
else
|
60
|
+
matches = client.todays_matches
|
61
|
+
|
62
|
+
## no matches today
|
63
|
+
if matches.empty?
|
64
|
+
puts "** No matches scheduled today.\n"
|
65
|
+
|
66
|
+
## note: was world cup 2018 - end date -- Date.new( 2018, 7, 11 )
|
67
|
+
## note: was euro 2020 (in 2021) - end date -- Date.new( 2021, 7, 11 )
|
68
|
+
if Date.today > Date.new( 2024, 7, 14 ) ## tournament is over, look back
|
69
|
+
puts "Past matches:"
|
70
|
+
matches = client.past_matches
|
71
|
+
else ## world cup is upcoming /in-progress,look forward
|
72
|
+
puts "Upcoming matches:"
|
73
|
+
matches = client.upcoming_matches
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
print_matches( matches )
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
def self.print_matches( matches )
|
86
|
+
## print games
|
87
|
+
|
88
|
+
today = Date.today
|
89
|
+
|
90
|
+
matches.each do |match|
|
91
|
+
print " %5s" % "\##{match['num']} "
|
92
|
+
|
93
|
+
date = Date.parse( match['date'] )
|
94
|
+
print "#{date.strftime('%a %b/%d')} " ## e.g. Thu Jun/14
|
95
|
+
if date > today
|
96
|
+
diff = (date - today).to_i
|
97
|
+
print "%10s" % "(in #{diff}d) "
|
98
|
+
end
|
99
|
+
|
100
|
+
print "%22s" % "#{match['team1']['name']} (#{match['team1']['code']})"
|
101
|
+
|
102
|
+
## todo/fix: add support for knockout scores
|
103
|
+
## with score1et/score1p (extra time and penalty)
|
104
|
+
if match['score1'] && match['score2']
|
105
|
+
print " #{match['score1']}-#{match['score2']} "
|
106
|
+
print "(#{match['score1i']}-#{match['score2i']}) "
|
107
|
+
else
|
108
|
+
print " vs "
|
109
|
+
end
|
110
|
+
|
111
|
+
print "%-22s" % "#{match['team2']['name']} (#{match['team2']['code']})"
|
112
|
+
|
113
|
+
if match['group']
|
114
|
+
print " #{match['group']} /" ## group phase/stage
|
115
|
+
end
|
116
|
+
|
117
|
+
print " #{match['round']} " ## knock out (k.o.) phase/stage
|
118
|
+
|
119
|
+
if match['stadium']
|
120
|
+
print " @ #{match['stadium']['name']}, #{match['city']}"
|
121
|
+
end
|
122
|
+
|
123
|
+
print "\n"
|
124
|
+
|
125
|
+
|
126
|
+
if match['goals1'] && match['goals2']
|
127
|
+
print " ["
|
128
|
+
match['goals1'].each_with_index do |goal,i|
|
129
|
+
print " " if i > 0
|
130
|
+
print "#{goal['name']}"
|
131
|
+
print " #{goal['minute']}"
|
132
|
+
print "+#{goal['offset']}" if goal['offset']
|
133
|
+
print "'"
|
134
|
+
print " (o.g.)" if goal['owngoal']
|
135
|
+
print " (pen.)" if goal['penalty']
|
136
|
+
end
|
137
|
+
match['goals2'].each_with_index do |goal,i|
|
138
|
+
if i == 0
|
139
|
+
print "; "
|
140
|
+
else
|
141
|
+
print " "
|
142
|
+
end
|
143
|
+
print "#{goal['name']}"
|
144
|
+
print " #{goal['minute']}"
|
145
|
+
print "+#{goal['offset']}" if goal['offset']
|
146
|
+
print "'"
|
147
|
+
print " (o.g.)" if goal['owngoal']
|
148
|
+
print " (pen.)" if goal['penalty']
|
149
|
+
end
|
150
|
+
print "]\n"
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end # module Footty
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
Footty.main if __FILE__ == $0
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: footty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2024.5.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logutils
|
@@ -64,16 +64,16 @@ dependencies:
|
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '
|
67
|
+
version: '4.1'
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '
|
74
|
+
version: '4.1'
|
75
75
|
description: footty - football.db command line client for european "euro" championship
|
76
|
-
|
76
|
+
2024 and more - who is playing today?
|
77
77
|
email: opensport@googlegroups.com
|
78
78
|
executables:
|
79
79
|
- footty
|
@@ -91,9 +91,6 @@ files:
|
|
91
91
|
- lib/footty.rb
|
92
92
|
- lib/footty/client.rb
|
93
93
|
- lib/footty/version.rb
|
94
|
-
- test/helper.rb
|
95
|
-
- test/test_client_euro.rb
|
96
|
-
- test/test_client_worldcup.rb
|
97
94
|
homepage: https://github.com/sportdb/footty
|
98
95
|
licenses:
|
99
96
|
- Public Domain
|
@@ -115,9 +112,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
115
112
|
- !ruby/object:Gem::Version
|
116
113
|
version: '0'
|
117
114
|
requirements: []
|
118
|
-
rubygems_version: 3.
|
115
|
+
rubygems_version: 3.4.10
|
119
116
|
signing_key:
|
120
117
|
specification_version: 4
|
121
118
|
summary: footty - football.db command line client for european "euro" championship
|
122
|
-
|
119
|
+
2024 and more - who is playing today?
|
123
120
|
test_files: []
|
data/test/helper.rb
DELETED
data/test/test_client_euro.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
###
|
2
|
-
# to run use
|
3
|
-
# ruby -I ./lib -I ./test test/test_client_euro.rb
|
4
|
-
|
5
|
-
require 'helper'
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
class TestClientEuro < MiniTest::Test
|
10
|
-
|
11
|
-
def setup
|
12
|
-
@client = Footty::Client.new( league: 'euro', year: 2020 )
|
13
|
-
end
|
14
|
-
|
15
|
-
|
16
|
-
def test_getters
|
17
|
-
today = Date.new( 2021, 6, 15 )
|
18
|
-
|
19
|
-
todays = @client.todays_matches( date: today )
|
20
|
-
pp todays
|
21
|
-
assert_equal 2, todays.size
|
22
|
-
|
23
|
-
yesterdays = @client.yesterdays_matches( date: today )
|
24
|
-
pp yesterdays
|
25
|
-
assert_equal 3, yesterdays.size
|
26
|
-
|
27
|
-
tomorrows = @client.tomorrows_matches( date: today )
|
28
|
-
pp tomorrows
|
29
|
-
assert_equal 3, tomorrows.size
|
30
|
-
|
31
|
-
past = @client.past_matches( date: today )
|
32
|
-
pp past
|
33
|
-
|
34
|
-
upcoming = @client.upcoming_matches( date: today )
|
35
|
-
pp upcoming
|
36
|
-
end
|
37
|
-
|
38
|
-
|
39
|
-
def test_todays_matches_2021_6_15
|
40
|
-
today = Date.new( 2021, 6, 15 )
|
41
|
-
ary = @client.todays_matches( date: today )
|
42
|
-
pp ary
|
43
|
-
=begin
|
44
|
-
[{"num"=>31,
|
45
|
-
"date"=>"2021-06-15",
|
46
|
-
"team1"=>{"name"=>"Hungary", "code"=>"HUN"},
|
47
|
-
"team2"=>{"name"=>"Portugal", "code"=>"POR"},
|
48
|
-
"score1"=>nil,
|
49
|
-
"score2"=>nil,
|
50
|
-
"score1i"=>nil,
|
51
|
-
"score2i"=>nil,
|
52
|
-
"group"=>"Group F",
|
53
|
-
"round"=>"Matchday 1"},
|
54
|
-
...
|
55
|
-
=end
|
56
|
-
|
57
|
-
assert_equal Array, ary.class ## for now just check return type (e.g. assume Array for parsed JSON data)
|
58
|
-
assert_equal 2, ary.size
|
59
|
-
assert_equal 'HUN', ary[0]['team1']['code']
|
60
|
-
assert_equal 'POR', ary[0]['team2']['code']
|
61
|
-
assert_equal 'Matchday 1', ary[0]['round']
|
62
|
-
# assert_equal 5, ary[0]['score1']
|
63
|
-
# assert_equal 0, ary[0]['score2']
|
64
|
-
end
|
65
|
-
|
66
|
-
|
67
|
-
def test_todays_matches_2021_6_10
|
68
|
-
today = Date.new( 2021, 6, 10 )
|
69
|
-
ary = @client.todays_matches( date: today )
|
70
|
-
## note: returns empty array if no matches scheduled/playing today
|
71
|
-
pp ary
|
72
|
-
|
73
|
-
assert_equal Array, ary.class ## for now just check return type (e.g. assume Array for parsed JSON data)
|
74
|
-
assert ary.empty?
|
75
|
-
end
|
76
|
-
|
77
|
-
|
78
|
-
def test_euro_round_1
|
79
|
-
h = @client.round( 1 )
|
80
|
-
|
81
|
-
pp h
|
82
|
-
=begin
|
83
|
-
{"name"=>"Matchday 1",
|
84
|
-
"matches"=>
|
85
|
-
[{"num"=>1,
|
86
|
-
"date"=>"2021-06-11",
|
87
|
-
"team1"=>{"name"=>"Turkey", "code"=>"TUR"},
|
88
|
-
"team2"=>{"name"=>"Italy", "code"=>"ITA"},
|
89
|
-
"score1"=>0,
|
90
|
-
"score2"=>3,
|
91
|
-
"score1i"=>0,
|
92
|
-
"score2i"=>0,
|
93
|
-
"group"=>"Group A"},
|
94
|
-
=end
|
95
|
-
|
96
|
-
assert_equal 'TUR', h['matches'][0]['team1']['code']
|
97
|
-
assert_equal 'ITA', h['matches'][0]['team2']['code']
|
98
|
-
assert_equal 0, h['matches'][0]['score1']
|
99
|
-
assert_equal 3, h['matches'][0]['score2']
|
100
|
-
end
|
101
|
-
|
102
|
-
|
103
|
-
end # class TestClientEuro
|
@@ -1,164 +0,0 @@
|
|
1
|
-
###
|
2
|
-
# to run use
|
3
|
-
# ruby -I ./lib -I ./test test/test_client_worldcup.rb
|
4
|
-
|
5
|
-
require 'helper'
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
class TestClientWorldCup < MiniTest::Test
|
10
|
-
|
11
|
-
def setup
|
12
|
-
@client = Footty::Client.new( league: 'worldcup', year: 2018 )
|
13
|
-
end
|
14
|
-
|
15
|
-
|
16
|
-
def test_getters
|
17
|
-
today = Date.new( 2018, 6, 16 )
|
18
|
-
|
19
|
-
todays = @client.todays_matches( date: today )
|
20
|
-
pp todays
|
21
|
-
assert_equal 4, todays.size
|
22
|
-
|
23
|
-
yesterdays = @client.yesterdays_matches( date: today )
|
24
|
-
pp yesterdays
|
25
|
-
assert_equal 3, yesterdays.size
|
26
|
-
|
27
|
-
tomorrows = @client.tomorrows_matches( date: today )
|
28
|
-
pp tomorrows
|
29
|
-
assert_equal 3, tomorrows.size
|
30
|
-
|
31
|
-
past = @client.past_matches( date: today )
|
32
|
-
pp past
|
33
|
-
|
34
|
-
upcoming = @client.upcoming_matches( date: today )
|
35
|
-
pp upcoming
|
36
|
-
end
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
def test_todays_matches_2018_6_14
|
41
|
-
today = Date.new( 2018, 6, 14 )
|
42
|
-
ary = @client.todays_matches( date: today )
|
43
|
-
## pp ary
|
44
|
-
=begin
|
45
|
-
[{"num"=>1,
|
46
|
-
"date"=>"2018-06-14",
|
47
|
-
"time"=>"18:00",
|
48
|
-
"team1"=>{"name"=>"Russia", "code"=>"RUS"},
|
49
|
-
"team2"=>{"name"=>"Saudi Arabia", "code"=>"KSA"},
|
50
|
-
"score1"=>nil,
|
51
|
-
"score2"=>nil,
|
52
|
-
"score1i"=>nil,
|
53
|
-
"score2i"=>nil,
|
54
|
-
"group"=>"Group A",
|
55
|
-
"stadium"=>{"key"=>"luzhniki", "name"=>"Luzhniki Stadium"},
|
56
|
-
"city"=>"Moscow",
|
57
|
-
"timezone"=>"UTC+3",
|
58
|
-
"round"=>"Matchday 1"}]
|
59
|
-
=end
|
60
|
-
|
61
|
-
assert_equal Array, ary.class ## for now just check return type (e.g. assume Array for parsed JSON data)
|
62
|
-
assert_equal 1, ary.size
|
63
|
-
assert_equal 'RUS', ary[0]['team1']['code']
|
64
|
-
assert_equal 'KSA', ary[0]['team2']['code']
|
65
|
-
assert_equal 'Matchday 1', ary[0]['round']
|
66
|
-
assert_equal 5, ary[0]['score1']
|
67
|
-
assert_equal 0, ary[0]['score2']
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_todays_matches_2018_6_10
|
71
|
-
today = Date.new( 2018, 6, 10 )
|
72
|
-
ary = @client.todays_matches( date: today )
|
73
|
-
## note: returns empty array if no matches scheduled/playing today
|
74
|
-
pp ary
|
75
|
-
|
76
|
-
assert_equal Array, ary.class ## for now just check return type (e.g. assume Array for parsed JSON data)
|
77
|
-
assert ary.empty?
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_world_2018_round_1
|
81
|
-
h = @client.round( 1 )
|
82
|
-
|
83
|
-
## pp h
|
84
|
-
=begin
|
85
|
-
{"name"=>"Matchday 1",
|
86
|
-
"matches"=>
|
87
|
-
[{"num"=>1,
|
88
|
-
"date"=>"2018-06-14",
|
89
|
-
"time"=>"18:00",
|
90
|
-
"team1"=>{"name"=>"Russia", "code"=>"RUS"},
|
91
|
-
"team2"=>{"name"=>"Saudi Arabia", "code"=>"KSA"},
|
92
|
-
"score1"=>nil,
|
93
|
-
"score2"=>nil,
|
94
|
-
"score1i"=>nil,
|
95
|
-
"score2i"=>nil,
|
96
|
-
"group"=>"Group A",
|
97
|
-
"stadium"=>{"key"=>"luzhniki", "name"=>"Luzhniki Stadium"},
|
98
|
-
"city"=>"Moscow",
|
99
|
-
"timezone"=>"UTC+3"}]}
|
100
|
-
=end
|
101
|
-
|
102
|
-
assert_equal 'RUS', h['matches'][0]['team1']['code']
|
103
|
-
assert_equal 'KSA', h['matches'][0]['team2']['code']
|
104
|
-
assert_equal 5, h['matches'][0]['score1']
|
105
|
-
assert_equal 0, h['matches'][0]['score2']
|
106
|
-
end
|
107
|
-
|
108
|
-
|
109
|
-
def test_world_2018_round_2
|
110
|
-
h = @client.round( 2 )
|
111
|
-
|
112
|
-
## pp h
|
113
|
-
=begin
|
114
|
-
{"name"=>"Matchday 2",
|
115
|
-
"matches"=>
|
116
|
-
[{"num"=>2,
|
117
|
-
"date"=>"2018-06-15",
|
118
|
-
"time"=>"17:00",
|
119
|
-
"team1"=>{"name"=>"Egypt", "code"=>"EGY"},
|
120
|
-
"team2"=>{"name"=>"Uruguay", "code"=>"URU"},
|
121
|
-
"score1"=>nil,
|
122
|
-
"score2"=>nil,
|
123
|
-
"score1i"=>nil,
|
124
|
-
"score2i"=>nil,
|
125
|
-
"group"=>"Group A",
|
126
|
-
"stadium"=>{"key"=>"ekaterinburg", "name"=>"Ekaterinburg Arena"},
|
127
|
-
"city"=>"Ekaterinburg",
|
128
|
-
"timezone"=>"UTC+5"},
|
129
|
-
{"num"=>3,
|
130
|
-
"date"=>"2018-06-15",
|
131
|
-
"time"=>"21:00",
|
132
|
-
"team1"=>{"name"=>"Portugal", "code"=>"POR"},
|
133
|
-
"team2"=>{"name"=>"Spain", "code"=>"ESP"},
|
134
|
-
"score1"=>nil,
|
135
|
-
"score2"=>nil,
|
136
|
-
"score1i"=>nil,
|
137
|
-
"score2i"=>nil,
|
138
|
-
"group"=>"Group B",
|
139
|
-
"stadium"=>{"key"=>"fisht", "name"=>"Fisht Stadium"},
|
140
|
-
"city"=>"Sochi",
|
141
|
-
"timezone"=>"UTC+3"},
|
142
|
-
{"num"=>4,
|
143
|
-
"date"=>"2018-06-15",
|
144
|
-
"time"=>"18:00",
|
145
|
-
"team1"=>{"name"=>"Morocco", "code"=>"MAR"},
|
146
|
-
"team2"=>{"name"=>"Iran", "code"=>"IRN"},
|
147
|
-
"score1"=>nil,
|
148
|
-
"score2"=>nil,
|
149
|
-
"score1i"=>nil,
|
150
|
-
"score2i"=>nil,
|
151
|
-
"group"=>"Group B",
|
152
|
-
"stadium"=>{"key"=>"saintpetersburg", "name"=>"Saint Petersburg Stadium"},
|
153
|
-
"city"=>"Saint Petersburg",
|
154
|
-
"timezone"=>"UTC+3"}]}
|
155
|
-
=end
|
156
|
-
|
157
|
-
assert_equal 'EGY', h['matches'][0]['team1']['code']
|
158
|
-
assert_equal 'URU', h['matches'][0]['team2']['code']
|
159
|
-
assert_equal 0, h['matches'][0]['score1']
|
160
|
-
assert_equal 1, h['matches'][0]['score2']
|
161
|
-
end
|
162
|
-
|
163
|
-
|
164
|
-
end # class TestClientWorldCup
|