velibe 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 77f7f5b9baaec5d5a804ff15b0a344df335be84b
4
- data.tar.gz: d2bfd4d5d77d941a68033ee17cf63b98faac404d
3
+ metadata.gz: ae617e07c50693971153c7825691b81e1816898d
4
+ data.tar.gz: 2de7a804bd6db847fd50026885ddac4cd9a4d53e
5
5
  SHA512:
6
- metadata.gz: a721e24aa50e2928b6fc60296142fa6c79d2aeaf653760f116d8307f1ecd3672c7ed1a8555bb90d32bbd84910e3968191eea59587e56507350ca94097e388075
7
- data.tar.gz: 0781a73c8ae7f37ce033996c5bcdeaf1e4226feba15bb8c8bc99eeb90119d9af5ddb2e0199f4c92f9a36ad428caa47bc7c03765590ebfdc77d0aa424d1afdc14
6
+ metadata.gz: cd72fc4d01a67a5578fadc1e9644c56cbde7c048aa1a7033e415d524822b93eae7500bc423d49b0b7095712ad6e870e377417e28326bcb4628f253632364b604
7
+ data.tar.gz: 1f384f4d42df814426149a781d5b59b22c6c554f9f7f0b37d155ca16814fbc833107f6c92c14f17606306101e7d4bbf1bf88fdae4505244f8f522d9a39e26107
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --format documentation
2
2
  --color
3
+ --require spec_helper
@@ -5,11 +5,18 @@ This project adheres to [Semantic Versioning](http://semver.org/).
5
5
 
6
6
  ## [Unreleased][unreleased]
7
7
 
8
+ ## [0.2.1] - 2015-11-30
9
+ ### Added
10
+ - documentation about new commands and config
11
+ ### Fixed
12
+ - access to token in config file
13
+ - display of wrong station number
14
+
8
15
  ## [0.2.0] - 2015-11-29
9
16
  ### Added
10
17
  - favorites storage with a `.velibe.yaml`
11
18
  - commands to *display*, *add* and *reset* favorites
12
- - CI setup (see badge on README)
19
+ - CI setup (see badge on README): unit test, coverage, travis and coveralls
13
20
 
14
21
  ## [0.1.0] - 2015-11-18
15
22
  ### Changed
@@ -17,7 +24,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
17
24
 
18
25
  ## [0.0.2] - 2015-11-11
19
26
  ### Added
20
- - Data and draft of sqlite dtabse for storing stations and some stats
27
+ - Data and draft of sqlite database for storing stations and some stats
21
28
  ### Fixed
22
29
  - naming convention
23
30
  ### Changed
@@ -27,7 +34,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
27
34
  ## [0.0.1] - 2015-07-04
28
35
  - Initial Release
29
36
 
30
- [unreleased]: https://github.com/AdrieanKhisbe/velibe/compare/v0.2.0...HEAD
37
+ [unreleased]: https://github.com/AdrieanKhisbe/velibe/compare/v0.2.1...HEAD
38
+ [0.2.1]: https://github.com/AdrieanKhisbe/velibe/compare/v0.2.0...v0.2.1
31
39
  [0.2.0]: https://github.com/AdrieanKhisbe/velibe/compare/v0.1.0...v0.2.0
32
40
  [0.1.0]: https://github.com/AdrieanKhisbe/velibe/compare/v0.0.2...v0.1.0
33
41
  [0.0.2]: https://github.com/AdrieanKhisbe/velibe/compare/v0.0.1...v0.0.2
data/README.md CHANGED
@@ -7,6 +7,7 @@ VeLibe
7
7
  [![Build Status](https://travis-ci.org/AdrieanKhisbe/velibe.svg)](https://travis-ci.org/AdrieanKhisbe/velibe)
8
8
  [![Coverage Status](https://coveralls.io/repos/AdrieanKhisbe/velibe/badge.svg?branch=master&service=github)](https://coveralls.io/github/AdrieanKhisbe/velibe?branch=master)
9
9
  [![Code Climate](https://codeclimate.com/github/AdrieanKhisbe/velibe/badges/gpa.svg)](https://codeclimate.com/github/AdrieanKhisbe/velibe)
10
+ [![Dependency Status](https://gemnasium.com/AdrieanKhisbe/velibe.svg)](https://gemnasium.com/AdrieanKhisbe/velibe)
10
11
 
11
12
  CLI tool included to help you see if there is bikes around.
12
13
 
@@ -17,7 +18,7 @@ address, and some stat collection is planed and might be implemented soon.
17
18
 
18
19
  Just install the gem, and you'll have access to this wonderful tool :D
19
20
 
20
- $ gem install Velibe
21
+ $ gem install velibe
21
22
 
22
23
  The cli relies on the JcDecaux API. You need an api token to be able to use it.
23
24
  You can see the official site to get one [there]
@@ -25,14 +26,36 @@ You can see the official site to get one [there]
25
26
  You'll need to create an [account](https://developer.jcdecaux.com/#/account),
26
27
  and an acces token will be then granted
27
28
 
28
- This token is to be stored in the `VELIBE_TOKEN` variable environment.
29
+ This token is to be stored in the `VELIBE_TOKEN` variable environment, or in the yaml config
30
+ file under the `token` key.
29
31
 
30
32
  ## Usage
31
33
 
32
34
  Basic usage of the commandline is to query the API to see
33
35
  the status of some specific station:
34
36
 
35
- $ velibe 10042 18012
37
+ $ velibe 10042 18012 13020
38
+ Velibe >> Stations 10042, 18012, 13020:
39
+ > Station 10042 - poissonnière - enghien: 15 Velo(s) libre(s) pour 17 places libres
40
+ > Station 18012 - doudeauville stephenson: 1 Velo(s) libre(s) pour 33 places libres
41
+ > Station 13020 - mendes france: 25 Velo(s) libre(s) pour 17 places libres
36
42
 
37
-
43
+ Velibe handle storing of favorites stations, those would be the one
44
+ that will be querried when no argument is provided.
38
45
 
46
+ You can control favorites with the `favorite` subcommand (which can be shorten
47
+ to `fav` or `f`.
48
+ This accept different subcommands:
49
+
50
+ - `a`/`add <sta1> <sta2>` : add stations to favorites
51
+ - `reset`/`setup [--force|-f]` : setup the config version, or reset it.
52
+ you will need to add the *force flag* to erase existing config
53
+ - if none is provided, just output current favorites.
54
+
55
+ Configuration is stored in `~/.velib.yaml` which you can also edit by hand
56
+ and eventually version in you *dotfiles* repo.
57
+
58
+ $ cat ~/.velib.yaml
59
+ ---
60
+ favorites: [10035, 19003, 19004, 10031]
61
+ token: <this-is-your-token-string>
data/bin/velibe CHANGED
@@ -5,15 +5,16 @@
5
5
  require 'velibe'
6
6
 
7
7
  case ARGV[0]
8
- when /f(av(orite)?)?$/
9
- # handle favorites
8
+ when /f(av(orite)?)?$/ # handle favorites
9
+ stations = ARGV[2..-1] || []
10
+ force = ARGV[2..-1].any? { |s| /-(f|-force)/ }
11
+
10
12
  case ARGV[1]
11
13
  when /a(dd)?/
12
- stations = ARGV[2..-1]
13
- # TODO: check if all number
14
+ stations, wrong_arg = stations.partition { |n| n =~ /\d+/ }
15
+ puts "BEWARE: '#{wrong_arg.join(', ')}' are not stations number and where ignored" unless wrong_arg.empty?
14
16
  Velibe.add_favorite(stations)
15
17
  when /setup|reset/
16
- force = ARGV[2..-1].any? { |s| /-(f|-force)/ }
17
18
  if Velibe.reset_favorites(force)
18
19
  puts 'Favorites Stations were reset'
19
20
  else
@@ -23,7 +24,13 @@ case ARGV[0]
23
24
  Velibe.print_favorites
24
25
  end
25
26
 
26
- else
27
- # TODO: check if all number
28
- Velibe.print_stations(ARGV)
27
+ when /setup/ # setup database
28
+ force = ARGV[1] =~ /-(f|-force)/
29
+ Velibe.setup_station_database(force)
30
+ Velibe.reset_favorites(force)
31
+
32
+ else # just Query stations
33
+ stations, wrong_arg = ARGV.partition { |n| n =~ /\d+/ } # LATER: check station really exist
34
+ puts "BEWARE: '#{wrong_arg.join(', ')}' are not stations number and were ignored" unless wrong_arg.empty?
35
+ Velibe.print_stations(stations)
29
36
  end
@@ -43,13 +43,18 @@ module Velibe
43
43
  end
44
44
  end
45
45
 
46
+ # FIXME: text display from there
46
47
  def self.reset_favorites(force = false)
47
48
  KvStore.reset_favorite_stations if force or KvStore.favorite_stations.empty?
49
+ # FIXME: ensure backup!! [store in history array]
48
50
  end
49
51
 
50
52
  def self.add_favorite(stations)
51
53
  KvStore.add_favorite_station(*stations)
52
54
  end
53
55
 
56
+ def self.setup_station_database(force = false)
57
+ Database.create if not Database.exist? or force
58
+ end
54
59
 
55
60
  end
@@ -1,11 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require 'http'
3
3
  require 'json'
4
+ require 'velibe/db/kv_store' # TODO: refactor injection?
4
5
 
5
6
  module Velibe
6
7
  class ApiVelib
7
8
 
8
- API_KEY = ENV['VELIBE_TOKEN'] || KvStore.token || raise('No token provided')
9
+ API_KEY = ENV['VELIBE_TOKEN'] || Velibe::KvStore.token || raise('No token provided')
9
10
 
10
11
  API_HOST = 'https://api.jcdecaux.com'
11
12
  API_PARAM = { contract: 'paris', apiKey: API_KEY }
@@ -5,22 +5,23 @@ require 'pathname'
5
5
  require 'sqlite3'
6
6
  require 'active_record'
7
7
  require 'csv'
8
+ require 'velibe/db/models'
8
9
 
9
10
  module Velibe
10
11
 
11
12
  module Database
12
- NAME = '~/.velib.db' # TODO: more generic
13
- PATH = Pathname.new(NAME).expand_path # .to_s?
14
- DATA_CSV = '../../data/Paris.csv'
13
+ DB_NAME = '~/.velib.db' # TODO: more generic + config
14
+ DB_PATH = Pathname.new(DB_NAME).expand_path # .to_s?
15
+ DATA_CSV = '../../../data/Paris.csv'
16
+ DATA_CSV_FILE = File.join(File.dirname(File.expand_path(__FILE__)), DATA_CSV)
15
17
  # §see: http://stackoverflow.com/questions/7828066/accessing-files-packaged-into-a-ruby-gem
16
18
 
17
19
  def self.exist?
18
- PATH.exist? # §check
20
+ DB_PATH.exist? # §check
19
21
  end
20
22
 
21
23
  def self.active_connect
22
- ActiveRecord::Base.establish_connection(adapter: 'sqlite3',
23
- database: PATH.to_s)
24
+ ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: DB_PATH.to_s
24
25
  end
25
26
 
26
27
  def self.create
@@ -35,15 +36,13 @@ module Velibe
35
36
  end
36
37
 
37
38
  def self.connexion
38
- return SQlite3::Database.new(PATH.to_s)
39
+ return SQlite3::Database.new(DB_PATH.to_s)
39
40
  # §see:options
40
41
  # §maybe: delete? [not that working?]
41
42
  end
42
- # §todo: version block?
43
43
 
44
44
  def self.prune
45
- #§later: check no connected?
46
- FileUtils.rm(PATH) if exist?
45
+ FileUtils.rm(DB_PATH) if self.exist?
47
46
  end
48
47
 
49
48
  #
@@ -52,41 +51,38 @@ module Velibe
52
51
 
53
52
  create_table :stations do |t|
54
53
  t.integer :number
55
- t.string :name
56
- t.string :address
57
- t.float :latitude
58
- t.float :longitude
59
- t.index :number # ¤note: must be declared before
54
+ t.string :name
55
+ t.string :address
56
+ t.float :latitude
57
+ t.float :longitude
58
+ t.index :number # ¤note: must be declared before
60
59
  end
61
60
 
62
61
  create_table :statuses do |t|
63
62
  t.integer :station_id
64
63
  t.boolean :status
65
- t.integer :bike_stands
66
- t.integer :available_bikes
67
- t.integer :available_bike_stands
64
+ t.integer :bike_stands
65
+ t.integer :available_bikes
66
+ t.integer :available_bike_stands
68
67
  t.timestamp :last_update
69
- # t.timestamps
70
68
  end
71
69
 
72
- todo: create others
70
+ # §todo: create others
73
71
 
74
72
  end
75
73
  end
76
74
 
77
75
  def self.populate
78
76
  # MAYBE: Use fast cv
79
- csv_file = File.join(File.dirname(File.expand_path(__FILE__)), DATA_CSV) # TODO: extract
80
- # ¤see: stopwatch > ???
77
+ # ¤see: stopwatch > to bench creation. >> (but overkill since just one step operation)
81
78
  puts 'Populate Database from csv Station description'
82
79
  # ¤note: transaction for faster insert
83
80
  ActiveRecord::Base.transaction do
84
- CSV.foreach(csv_file, headers: true, converters: :numeric) do |row|
81
+ CSV.foreach(DATA_CSV_FILE, headers: true, converters: :numeric) do |row|
85
82
  # §TODO: converter
86
83
  # header_converters: :underscore -> tried but get: NoMethodError: undefined method `arity' for nil:NilClass
87
- Models::Station.create(number: row['Number'], name: row['Name'], address: row['Address'],
88
- latitude: row['Latitude'], longitude: row['Longitude'])
89
- # ¤note: inspect send back a hash
84
+ Station.create(number: row['Number'], name: row['Name'], address: row['Address'],
85
+ latitude: row['Latitude'], longitude: row['Longitude'])
90
86
  end
91
87
  end
92
88
  end
@@ -1,61 +1,61 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # §todo: new Station will go in module
4
- # Todo: put in sub file?
5
-
6
- class StationStatus
7
- attr_reader :name, :available_bikes, :available_bike_stands
8
-
9
- def initialize (name, available_bikes, available_bike_stands)
10
- # Maybe: enhance with bike_stand, and last_update
11
- @name= name
12
- @available_bikes = available_bikes
13
- @available_bike_stands= available_bike_stands
14
- # TODO: creation Timestamp
15
- end
16
-
17
- def to_s
18
- "Station #{@name}: #{@available_bikes} Velo(s) libre(s) pour #{@available_bike_stands} places libres"
19
- end
20
-
21
- def to_csv(sep = ';')
22
- [@name, @available_bikes, @available_bike_stands].join(sep)
23
- end
24
-
25
- # FIXME: replace comment with doc
26
- # TODO: maybe extract in Trajet: + method: velo dispo, stand dispo
27
- def can_leave?
28
- @available_bikes > 0 and not @available_bikes.nil? # test si nil quand pas de velo
29
- end
30
- # MAYBE REPLACE VALUE: 0 no, 1 un peu, 2 attention
31
- def can_go?
32
- @available_bike_stands > 0 and not @available_bike_stands # test si nil quand pas de velo
33
- end
34
-
35
- def can_go_to?(station)
36
- self.can_leave? and station.can_go?
37
- end
38
-
39
- # TODO rename
40
- def self.string_from_hash(json)
41
- StationStatus.from_hash(json).to_s
42
- end
43
-
44
- def self.from_hash(json)
45
- # TODO: sanity check of jzon
46
- name = json[:name].capitalize #RAISE EROR if neede
47
- available_bikes = json[:available_bikes]
48
- available_bike_stands = json[:available_bike_stands]
49
- # T
50
- self.new(name, available_bikes, available_bike_stands)
51
- end
3
+ module Velibe
4
+ class StationStatus
5
+ attr_reader :name, :available_bikes, :available_bike_stands
6
+
7
+ def initialize (name, available_bikes, available_bike_stands)
8
+ # Maybe: enhance with bike_stand, and last_update
9
+ @name= name
10
+ @available_bikes = available_bikes
11
+ @available_bike_stands= available_bike_stands
12
+ # TODO: creation Timestamp
13
+ end
14
+
15
+ def to_s
16
+ "Station #{@name}: #{@available_bikes} Velo(s) libre(s) pour #{@available_bike_stands} places libres"
17
+ end
18
+
19
+ def to_csv(sep = ';')
20
+ [@name, @available_bikes, @available_bike_stands].join(sep)
21
+ end
22
+
23
+ # FIXME: replace comment with doc
24
+ # TODO: maybe extract in Trajet: + method: velo dispo, stand dispo
25
+ def can_leave?
26
+ @available_bikes > 0 and not @available_bikes.nil? # test si nil quand pas de velo
27
+ end
28
+
29
+ # MAYBE REPLACE VALUE: 0 no, 1 un peu, 2 attention
30
+ def can_go?
31
+ @available_bike_stands > 0 and not @available_bike_stands # test si nil quand pas de velo
32
+ end
33
+
34
+ def can_go_to?(station)
35
+ self.can_leave? and station.can_go?
36
+ end
37
+
38
+ def self.string_from_json(json)
39
+ StationStatus.from_hash(json).to_s
40
+ end
41
+
42
+ def self.from_hash(json)
43
+ # TODO: sanity check of jzon
44
+ name = json[:name].capitalize #RAISE EROR if neede
45
+ available_bikes = json[:available_bikes]
46
+ available_bike_stands = json[:available_bike_stands]
47
+ # T
48
+ self.new(name, available_bikes, available_bike_stands)
49
+ end
50
+
51
+ # MAYBE Might belong in formater?
52
+ def self.print_from_json(json_string, prefix='')
53
+ data = JSON.parse(json_string, symbolize_names: true)
54
+ status = StationStatus.from_hash(data)
55
+ puts "#{prefix}#{status}"
56
+ status
57
+ end
52
58
 
53
- # MAYBE Might belong in formater?
54
- def self.print_from_json(json_string, prefix='')
55
- data = JSON.parse(json_string, symbolize_names: true)
56
- status = StationStatus.from_hash(data)
57
- puts "#{prefix}#{status}"
58
- status
59
59
  end
60
60
 
61
61
  end
@@ -1,3 +1,3 @@
1
1
  module Velibe
2
- VERSION = '0.2.0'
2
+ VERSION = '0.2.1'
3
3
  end
@@ -1,19 +1,21 @@
1
+ velibe_lib = File.expand_path('../../lib', __FILE__)
1
2
 
2
- if ENV["TRAVIS"]
3
- require "simplecov"
4
- require "coveralls"
3
+ if ENV['TRAVIS']
4
+ require 'simplecov'
5
+ require 'coveralls'
5
6
 
6
7
  SimpleCov.formatter = Coveralls::SimpleCov::Formatter
7
8
  SimpleCov.start do
8
9
  # No need to report coverage metrics for the test code
9
- add_filter "test"
10
+ add_filter 'test'
10
11
  end
11
12
 
12
13
  # Eager load the entire lib directory so that SimpleCov is able to report
13
14
  # accurate code coverage metrics.
14
- velibe_lib = File.expand_path("../../lib", __FILE__)
15
15
  at_exit { Dir["#{velibe_lib}/**/*.rb"].each { |rb| require(rb) } }
16
+ else
17
+
18
+ $LOAD_PATH.unshift velibe_lib
19
+ require 'velibe'
16
20
  end
17
21
 
18
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
19
- require 'velibe'
@@ -1,13 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
3
 
4
- describe StationStatus do
4
+ describe Velibe::StationStatus do
5
5
 
6
6
  describe '#new' do
7
7
 
8
8
  context 'Can create Status with proper values' do
9
9
 
10
- let(:status) { StationStatus.new 'AB', available_bikes= 2, available_bike_stands=4 }
10
+ let(:status) { Velibe::StationStatus.new 'AB', available_bikes= 2, available_bike_stands=4 }
11
11
 
12
12
  it 'has proper name' do
13
13
  expect(status.name).to eq 'AB'
@@ -26,7 +26,7 @@ describe StationStatus do
26
26
 
27
27
  context 'handle valid input values' do
28
28
  let(:data) { { name: 'station', available_bikes: 2, available_bike_stands:4 } }
29
- let(:status) { StationStatus.from_hash(data) }
29
+ let(:status) { Velibe::StationStatus.from_hash(data) }
30
30
  it 'capitalize station name' do expect(status.name).to eq 'Station' end
31
31
  it { expect(status.available_bikes).to eq 2 }
32
32
 
@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_dependency 'http', '~> 0.9.8'
22
- spec.add_dependency 'sqlite3'
23
- spec.add_dependency 'activerecord'
22
+ spec.add_dependency 'sqlite3', '~> 1.3'
23
+ spec.add_dependency 'activerecord', '~> 4'
24
24
  spec.add_dependency 'moneta', '~> 0.8'
25
25
 
26
26
  spec.add_development_dependency 'bundler', '~> 1.6'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: velibe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adriean Khisbe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-29 00:00:00.000000000 Z
11
+ date: 2015-11-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http
@@ -28,30 +28,30 @@ dependencies:
28
28
  name: sqlite3
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '1.3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '1.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: activerecord
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '4'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '4'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: moneta
57
57
  requirement: !ruby/object:Gem::Requirement