stockroll 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3dc6678fdbb06fe8356c3f8b9331ef29adb58f61
4
+ data.tar.gz: b692ef3c18b9f405a536f7096afac406de22eca1
5
+ SHA512:
6
+ metadata.gz: 251b4bfec0947e0c39b1859ff8ec078f1d5d74375fa0730aa308d8ad9f86d11c0372c3a783288faacec208d4e4fff7bd375ec014e7748c80590b888b1ef71a77
7
+ data.tar.gz: c54864d4be3db21c4cdc5549e82c2cbd6a21aeb6269b35834ff6c5e4d31cd03ff04174c619e2a063adeaddf546b5fd71a7dacd3ba844f77d10a639ea84d57505
@@ -0,0 +1,19 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ coverage
8
+ doc
9
+ pkg
10
+ *.swp
11
+ *.patch
12
+ *.gem
13
+ *.sh
14
+ .DS_Store
15
+ .bundle/*
16
+ #Gemfile.lock
17
+ tmp/*
18
+ log/*
19
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in stockroll.gemspec
4
+ gemspec
@@ -0,0 +1,46 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ stockroll (0.0.2)
5
+ colorize (~> 0.6.0)
6
+ curses (~> 1.0.0)
7
+ em-http-request (~> 1.1.2)
8
+ thor (~> 0.18.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ addressable (2.3.5)
14
+ colorize (0.6.0)
15
+ cookiejar (0.3.1)
16
+ curses (1.0.0)
17
+ diff-lcs (1.2.5)
18
+ em-http-request (1.1.2)
19
+ addressable (>= 2.3.4)
20
+ cookiejar
21
+ em-socksify (>= 0.3)
22
+ eventmachine (>= 1.0.3)
23
+ http_parser.rb (>= 0.6.0)
24
+ em-socksify (0.3.0)
25
+ eventmachine (>= 1.0.0.beta.4)
26
+ eventmachine (1.0.3)
27
+ http_parser.rb (0.6.0)
28
+ rake (10.1.1)
29
+ rspec (2.14.1)
30
+ rspec-core (~> 2.14.0)
31
+ rspec-expectations (~> 2.14.0)
32
+ rspec-mocks (~> 2.14.0)
33
+ rspec-core (2.14.7)
34
+ rspec-expectations (2.14.5)
35
+ diff-lcs (>= 1.1.3, < 2.0)
36
+ rspec-mocks (2.14.6)
37
+ thor (0.18.1)
38
+
39
+ PLATFORMS
40
+ ruby
41
+
42
+ DEPENDENCIES
43
+ bundler (~> 1.3)
44
+ rake
45
+ rspec
46
+ stockroll!
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Raymond Jiang
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,40 @@
1
+ # Stockroll
2
+ ### To show real-time stock quotes
3
+
4
+ ![screenshot](/screenshot.png)
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'stockroll'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install stockroll
19
+
20
+ ## Usage
21
+
22
+ 1. Very simple to use, only type 'stock' in your console and let's fun.
23
+
24
+ 2. Type 'stock --help' to view all commands.
25
+
26
+ 3. Type 'stock add your_stock_code_xxx' , add stock code to display.
27
+
28
+ 4. Type 'stock delete your_stock_code_xxx', delete a existed stock code.
29
+
30
+ 5. Type 'stock clear' to clear all existed stock codes.
31
+
32
+ 6. Type 'q' or 'Q' to quit stock.
33
+
34
+ ## Contributing
35
+
36
+ 1. Fork it
37
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
38
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
39
+ 4. Push to the branch (`git push origin my-new-feature`)
40
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'stockroll/commands'
3
+
4
+ Stockroll::Commands.start
@@ -0,0 +1,5 @@
1
+ require "stockroll/version"
2
+
3
+ module Stockroll
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,126 @@
1
+ require "thor"
2
+ require 'find'
3
+ require 'erb'
4
+ require 'colorize'
5
+ require 'stockroll/utils'
6
+
7
+ module Stockroll
8
+ class Commands < Thor
9
+ include Thor::Actions
10
+ CONF_FILE_PATH = File.expand_path("~/.stock_roll_codes_config",__FILE__)
11
+
12
+ desc "start", "start stock roll"
13
+ def start
14
+ codes = self.get_stock_codes
15
+ if codes.nil? or codes.strip.size == 0
16
+ isOk, cs = self.init_config
17
+ Stockroll::Utils.run(cs) if isOk
18
+ else
19
+ Stockroll::Utils.run(codes)
20
+ end
21
+ end
22
+
23
+ desc "add", "add a stock code, if you want add multiple CODE please separated by commas."
24
+ def add(codes)
25
+ is_valid , err_msg = self.check_codes(codes)
26
+ if is_valid
27
+ self.add_codes(codes)
28
+ puts "Info: add code successfully.".yellow
29
+ else
30
+ err_msg.each do |msg|
31
+ puts msg.red
32
+ end
33
+ end
34
+ end
35
+
36
+ desc "delete", "delete a stock code"
37
+ def delete(code)
38
+ self.remove_code(code)
39
+ puts "Info: delete is ok.".yellow
40
+ end
41
+
42
+ desc "clear", "clear all stock codes"
43
+ def clear()
44
+ self.remove_all_codes()
45
+ puts "Info: clear all codes is successed.".yellow
46
+ end
47
+
48
+ default_task :start
49
+
50
+ protected
51
+ def get_stock_codes
52
+ return nil unless File.exists?(CONF_FILE_PATH)
53
+ return IO.read(CONF_FILE_PATH)
54
+ end
55
+ def add_codes(codes)
56
+ raise 'Please input stock codes.' if codes.nil? or codes.strip.size == 0
57
+ codes = codes.gsub(/(^\s+)|(\s+$)/,'')
58
+ unless File.exists?(CONF_FILE_PATH)
59
+ File.open(CONF_FILE_PATH,'w') do |f|
60
+ f.write(codes)
61
+ end
62
+ else
63
+ content = self.get_stock_codes
64
+ if content.nil? or content.strip.size == 0
65
+ File.open(CONF_FILE_PATH,'w') do |f|
66
+ f.write(codes)
67
+ end
68
+ else
69
+ old_codes = content.split(',')
70
+ added_codes = codes.split(',')
71
+ new_codes = old_codes.concat(added_codes).uniq
72
+ File.open(CONF_FILE_PATH,'w') do |f|
73
+ f.write(new_codes.join(','))
74
+ end
75
+ end
76
+
77
+ end
78
+ end
79
+ def remove_code(code)
80
+ old_codes = self.get_stock_codes
81
+ unless old_codes.nil?
82
+ n = []
83
+ old_codes.split(',').each do |c|
84
+ if c.strip != code.strip
85
+ n << c
86
+ end
87
+ end
88
+ File.open(CONF_FILE_PATH,'w') do |f|
89
+ f.write(n.join(','))
90
+ end
91
+ end
92
+ end
93
+ def remove_all_codes()
94
+ File.open(CONF_FILE_PATH,'w') do |f|
95
+ f.write('')
96
+ end
97
+ end
98
+ def check_codes(codes)
99
+ is_valid = true
100
+ err_msg = []
101
+ c_a = codes.split(',')
102
+ c_a.each do |c|
103
+ unless Stockroll::Utils.is_valid_stock_code(c)
104
+ err_msg << "Error: invalid stock code: #{c}"
105
+ is_valid = false
106
+ end
107
+ end
108
+ [is_valid, err_msg]
109
+ end
110
+ def init_config
111
+ print "Please input your stock codes: ".yellow
112
+ cs = gets.chomp
113
+ is_valid, err_msg = self.check_codes(cs)
114
+ unless is_valid
115
+ err_msg.each do |msg|
116
+ puts msg.red
117
+ end
118
+ [false, '']
119
+ else
120
+ self.add_codes(cs)
121
+ [true, cs]
122
+ end
123
+ end
124
+ end
125
+
126
+ end
@@ -0,0 +1,144 @@
1
+
2
+ require 'net/http'
3
+ require 'colorize'
4
+ require 'em-http-request'
5
+ require "curses"
6
+
7
+ include Curses
8
+
9
+ module Stockroll
10
+ class Utils
11
+ ROOT_URL = "http://hq.sinajs.cn/list="
12
+ class << self
13
+ def is_valid_stock_code(code)
14
+ uri = URI("#{ROOT_URL}#{code}")
15
+ res = Net::HTTP.get(uri).force_encoding("GBK").encode("UTF-8")
16
+ val = res.split('=')[1]
17
+ if val =~ /([^\"\n;]+)/
18
+ if !$1.nil? and $1.strip.size > 0
19
+ true
20
+ else
21
+ false
22
+ end
23
+ else
24
+ false
25
+ end
26
+ end
27
+ def run(codes)
28
+ codes = codes.split(',')
29
+ Curses.noecho
30
+ Curses.init_screen
31
+ Curses.start_color
32
+ Curses.init_pair(COLOR_RED,COLOR_RED,COLOR_BLACK)
33
+ Curses.init_pair(COLOR_BLUE,COLOR_BLUE,COLOR_BLACK)
34
+ Curses.init_pair(COLOR_GREEN,COLOR_GREEN,COLOR_BLACK)
35
+ Curses.init_pair(COLOR_YELLOW,COLOR_YELLOW,COLOR_BLACK)
36
+ 47.times do |i|
37
+ Curses.setpos(0,i)
38
+ Curses.addstr('#')
39
+ end
40
+ curs_set(0)
41
+ Curses.setpos(1,0)
42
+ Curses.addstr('Loading...')
43
+
44
+ another_th = Thread.new {
45
+ EventMachine.run do
46
+
47
+ do_work = proc{
48
+
49
+ codes.each_with_index do |code,index|
50
+ http = EventMachine::HttpRequest.new("#{ROOT_URL}#{code}").get
51
+ http.errback { p 'Uh oh'; }
52
+ http.callback {
53
+ res = http.response.encode('utf-8')
54
+ val = res.split('=')[1]
55
+ if val =~ /([^\"\n;]+)/
56
+ captures = $1
57
+ if index == 0
58
+ ypos = 1
59
+ else
60
+ ypos = (index * 2) + 1
61
+ end
62
+
63
+ if captures.strip != ''
64
+ ar = captures.split(',')
65
+ Curses.setpos(ypos,0)
66
+ Curses.attron(A_BOLD|A_UNDERLINE) {
67
+ Curses.addstr(ar[0])
68
+ clrtoeol() #clear line
69
+ }
70
+
71
+ Curses.setpos(ypos,11)
72
+ Curses.attron(A_NORMAL|A_DIM) {
73
+ Curses.addstr(code)
74
+ }
75
+
76
+ Curses.setpos(ypos,22)
77
+ Curses.attron(A_NORMAL) {
78
+ Curses.addstr(ar[3])
79
+ }
80
+
81
+ Curses.setpos(ypos,32)
82
+ if ar[3].to_f == 0
83
+ diff = 0.00
84
+ else
85
+ diff = (ar[3].to_f - ar[2].to_f).round(2)
86
+ end
87
+ prefix = ' '
88
+ if diff >= 0
89
+ if diff == 0
90
+ Curses.attron(A_BOLD) {
91
+ Curses.addstr("#{prefix}#{diff.abs}")
92
+ Curses.addstr(" ")
93
+ Curses.addstr("0.00%")
94
+
95
+ }
96
+ else
97
+ prefix = '+'
98
+ Curses.attron(color_pair(COLOR_RED)|A_BOLD) {
99
+ Curses.addstr("#{prefix}#{diff.abs}")
100
+ Curses.addstr(" ")
101
+ Curses.addstr("#{prefix}#{((diff.abs/ar[2].to_f)*100).round(2)}%")
102
+
103
+ }
104
+ end
105
+ else
106
+ prefix = '-'
107
+ Curses.attron(color_pair(COLOR_GREEN)|A_BOLD) {
108
+ Curses.addstr("#{prefix}#{diff.abs}")
109
+ Curses.addstr(" ")
110
+ Curses.addstr("#{prefix}#{((diff.abs/ar[2].to_f)*100).round(2)}%")
111
+ }
112
+ end
113
+ Curses.refresh
114
+ end
115
+
116
+ end
117
+
118
+ }
119
+ end
120
+ }
121
+
122
+ EM::PeriodicTimer.new(10) do
123
+ do_work.call()
124
+ end
125
+ do_work.call()
126
+
127
+ end
128
+
129
+ }
130
+ while TRUE
131
+ c = getch
132
+ case c
133
+ when /q/i
134
+ EM.stop if EM
135
+ another_th.exit()
136
+ Curses.close_screen
137
+ exit(0)
138
+
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,3 @@
1
+ module Stockroll
2
+ VERSION = "0.0.2"
3
+ end
Binary file
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+
6
+ require "stockroll"
7
+
8
+
9
+ RSpec.configure do |config|
10
+ # Use color in STDOUT
11
+ config.color_enabled = true
12
+
13
+ # Use color not only in STDOUT but also in pagers and files
14
+ config.tty = true
15
+
16
+ # Use the specified formatter
17
+ config.formatter = :documentation # :progress, :html, :textmate
18
+ end
@@ -0,0 +1,36 @@
1
+ # run rspec
2
+ require "spec_helper"
3
+ require 'stockroll/commands'
4
+ require 'stockroll/utils'
5
+
6
+ describe Stockroll do
7
+
8
+ it 'stock code is valid' do
9
+ Stockroll::Utils.is_valid_stock_code('shabc').should == false
10
+ Stockroll::Utils.is_valid_stock_code('sz000100').should == true
11
+ end
12
+ describe "Stock Config Operation" do
13
+ path = Stockroll::Commands::CONF_FILE_PATH
14
+ before(:each) do
15
+ File.open(path,'w'){|f| f.write('')} if File.exists?(path)
16
+ end
17
+ it 'read and write stock code is fine' do
18
+ cmd = Stockroll::Commands.new
19
+ cmd.send :add_codes, "sz001"
20
+ cmd.send :add_codes, "sz001,sz002"
21
+ cmd.send :add_codes, "sz003"
22
+ (cmd.send :get_stock_codes).should == "sz001,sz002,sz003"
23
+ end
24
+ it 'remove stock code is fine' do
25
+ cmd = Stockroll::Commands.new
26
+ cmd.send :add_codes, "sz001"
27
+ cmd.send :add_codes, "sz001,sz002"
28
+ cmd.send :remove_code, "sz002"
29
+ (cmd.send :get_stock_codes).should == "sz001"
30
+ end
31
+ after(:each) do
32
+ File.open(path,'w'){|f| f.write('')} if File.exists?(path)
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'stockroll/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "stockroll"
8
+ spec.version = Stockroll::VERSION
9
+ spec.authors = ["Robot Jiang"]
10
+ spec.email = ["robot.z.jiang@gmail.com"]
11
+ spec.description = %q{To show real-time stock quotes.}
12
+ spec.summary = %q{To show real-time stock quotes.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = ['stock']#spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_dependency "thor" , "~> 0.18.1"
25
+ spec.add_dependency "colorize" , "~> 0.6.0"
26
+ spec.add_dependency "em-http-request" , "~> 1.1.2"
27
+ spec.add_dependency "curses" , "~> 1.0.0"
28
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stockroll
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Robot Jiang
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: thor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.18.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.18.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: colorize
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.6.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.6.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: em-http-request
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.1.2
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 1.1.2
97
+ - !ruby/object:Gem::Dependency
98
+ name: curses
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 1.0.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 1.0.0
111
+ description: To show real-time stock quotes.
112
+ email:
113
+ - robot.z.jiang@gmail.com
114
+ executables:
115
+ - stock
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - Gemfile
121
+ - Gemfile.lock
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - bin/stock
126
+ - lib/stockroll.rb
127
+ - lib/stockroll/commands.rb
128
+ - lib/stockroll/utils.rb
129
+ - lib/stockroll/version.rb
130
+ - screenshot.png
131
+ - spec/spec_helper.rb
132
+ - spec/stock_spec.rb
133
+ - stockroll.gemspec
134
+ homepage: ''
135
+ licenses:
136
+ - MIT
137
+ metadata: {}
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ requirements: []
153
+ rubyforge_project:
154
+ rubygems_version: 2.1.11
155
+ signing_key:
156
+ specification_version: 4
157
+ summary: To show real-time stock quotes.
158
+ test_files:
159
+ - spec/spec_helper.rb
160
+ - spec/stock_spec.rb