uniform_invoice_lottery 0.0.1 → 0.0.2

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: 728eb49fd681530951104795ff66b88907e8954d
4
- data.tar.gz: c8bba26b3f7e5bc1676cb94f36905f28877709b1
3
+ metadata.gz: 29c221b98f7a65111488e3762aaae586cbdd34a7
4
+ data.tar.gz: 994775084bdb02197c5f1a22228a5c1c6e85a7f7
5
5
  SHA512:
6
- metadata.gz: 4f5e24b8c7a903895930dd89038c117a240b3a76d714c1f6fde2cbae5d9ec979bd9690bf8a047e0d1a1ca0491c2c415557fc9006a57b8e5fbddd8af8cbb48ddd
7
- data.tar.gz: af439acaac9f51da3d5520bb8aba1301bd7ca61ec3ade5123633de05e9b756215e64f878177b6bb7712d16b7f3f3e0e01fe711debb2405c33b6d519c8a44c221
6
+ metadata.gz: 2312270fed9aa807ffc53bcbdc35b223fadede3e2376fb2c55bfc8bd6e86d216ae7cb4dde37b32e5a5f710817c18f610f72dadfbbeddf0bcb0c69cf29f2ce6fb
7
+ data.tar.gz: 93cb94ebd48260d7dce4c11b12f0c4617c1bd09568ca3c5213dae0e8f4b29e693f19903d02530656358397ea93ce4e1d1d4a0dae595df4d8d912407584f27b78
data/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  一個統一發票兌獎的 Gem,還有自動更新功能,還真不賴。自己說。
4
4
 
5
- 還沒弄上 rubygems.org。
6
5
 
7
6
  ## Installation
8
7
 
@@ -24,6 +23,7 @@ Or install it yourself as:
24
23
 
25
24
  回傳號碼結果字串,例如:
26
25
  ```ruby
26
+ require 'uniform_invoice_lottery'
27
27
  UniformInvoiceLottery.check '82930261', time: Time.new(2015, 7, 26)
28
28
  ```
29
29
 
data/lib/record.yaml CHANGED
@@ -1,55 +1,94 @@
1
1
  ---
2
- last_updated_at: '2015-07-26 15:58:30 +0800'
2
+ last_updated_at: '2016-03-18 00:38:16 +0800'
3
3
  records:
4
+ - year: 104
5
+ start_month: 11
6
+ end_month: 12
7
+ special_prize: '91605081'
8
+ grand_prize: '38187237'
9
+ first_prizes:
10
+ - '93749881'
11
+ - '29592686'
12
+ - '68783835'
13
+ additional_sixth_prizes:
14
+ - '076'
15
+ - '313'
16
+ - '056'
17
+ - year: 104
18
+ start_month: 9
19
+ end_month: 10
20
+ special_prize: '07332260'
21
+ grand_prize: '20119263'
22
+ first_prizes:
23
+ - '76833937'
24
+ - '28338875'
25
+ - '83689131'
26
+ additional_sixth_prizes:
27
+ - 096
28
+ - '819'
29
+ - '105'
30
+ - year: 104
31
+ start_month: 7
32
+ end_month: 8
33
+ special_prize: '54719495'
34
+ grand_prize: '52704456'
35
+ first_prizes:
36
+ - '95358086'
37
+ - '35867930'
38
+ - '14013695'
39
+ additional_sixth_prizes:
40
+ - '270'
41
+ - '432'
42
+ - '326'
4
43
  - year: 104
5
44
  start_month: 5
6
45
  end_month: 6
7
- so_special_price: '82930261'
8
- special_price: '43540459'
9
- head_prices:
46
+ special_prize: '82930261'
47
+ grand_prize: '43540459'
48
+ first_prizes:
10
49
  - '82267055'
11
50
  - '72762106'
12
51
  - 06820335
13
- additional_sixth_prices:
52
+ additional_sixth_prizes:
14
53
  - '420'
15
54
  - '523'
16
55
  - '554'
17
56
  - year: 104
18
57
  start_month: 3
19
58
  end_month: 4
20
- so_special_price: '46492032'
21
- special_price: '66224881'
22
- head_prices:
59
+ special_prize: '46492032'
60
+ grand_prize: '66224881'
61
+ first_prizes:
23
62
  - 06216938
24
63
  - 04296940
25
64
  - '86442491'
26
- additional_sixth_prices:
65
+ additional_sixth_prizes:
27
66
  - '306'
28
67
  - '403'
29
68
  - '867'
30
69
  - year: 104
31
70
  start_month: 1
32
71
  end_month: 2
33
- so_special_price: '60538935'
34
- special_price: '50887710'
35
- head_prices:
72
+ special_prize: '60538935'
73
+ grand_prize: '50887710'
74
+ first_prizes:
36
75
  - '63856949'
37
76
  - '39459262'
38
77
  - '61944942'
39
- additional_sixth_prices:
78
+ additional_sixth_prizes:
40
79
  - '022'
41
80
  - '355'
42
81
  - 038
43
82
  - year: 103
44
83
  start_month: 11
45
84
  end_month: 12
46
- so_special_price: '33516538'
47
- special_price: '18290129'
48
- head_prices:
85
+ special_prize: '33516538'
86
+ grand_prize: '18290129'
87
+ first_prizes:
49
88
  - '43772058'
50
89
  - '44517895'
51
90
  - '45226602'
52
- additional_sixth_prices:
91
+ additional_sixth_prizes:
53
92
  - '901'
54
93
  - '659'
55
94
  - '034'
@@ -57,13 +96,13 @@ records:
57
96
  - year: 103
58
97
  start_month: 9
59
98
  end_month: 10
60
- so_special_price: '22267127'
61
- special_price: '31075480'
62
- head_prices:
99
+ special_prize: '22267127'
100
+ grand_prize: '31075480'
101
+ first_prizes:
63
102
  - '35396804'
64
103
  - '15352117'
65
104
  - '54709991'
66
- additional_sixth_prices:
105
+ additional_sixth_prizes:
67
106
  - '114'
68
107
  - 068
69
108
  - '476'
@@ -71,13 +110,13 @@ records:
71
110
  - year: 103
72
111
  start_month: 7
73
112
  end_month: 8
74
- so_special_price: '16256820'
75
- special_price: '33378146'
76
- head_prices:
113
+ special_prize: '16256820'
114
+ grand_prize: '33378146'
115
+ first_prizes:
77
116
  - '92040881'
78
117
  - '99971012'
79
118
  - '70124883'
80
- additional_sixth_prices:
119
+ additional_sixth_prizes:
81
120
  - '998'
82
121
  - '741'
83
122
  - '833'
@@ -85,104 +124,71 @@ records:
85
124
  - year: 103
86
125
  start_month: 5
87
126
  end_month: 6
88
- so_special_price: '94761178'
89
- special_price: '71959593'
90
- head_prices:
127
+ special_prize: '94761178'
128
+ grand_prize: '71959593'
129
+ first_prizes:
91
130
  - '36665808'
92
131
  - '54185273'
93
132
  - '18953944'
94
- additional_sixth_prices:
133
+ additional_sixth_prizes:
95
134
  - '347'
96
135
  - '790'
97
136
  - year: 103
98
137
  start_month: 3
99
138
  end_month: 4
100
- so_special_price: '54544448'
101
- special_price: '70349798'
102
- head_prices:
139
+ special_prize: '54544448'
140
+ grand_prize: '70349798'
141
+ first_prizes:
103
142
  - '76086228'
104
143
  - '38205733'
105
144
  - '17173614'
106
- additional_sixth_prices:
145
+ additional_sixth_prizes:
107
146
  - '692'
108
147
  - '326'
109
148
  - year: 103
110
149
  start_month: 1
111
150
  end_month: 2
112
- so_special_price: '34231966'
113
- special_price: '57287066'
114
- head_prices:
151
+ special_prize: '34231966'
152
+ grand_prize: '57287066'
153
+ first_prizes:
115
154
  - '29828540'
116
155
  - '85564445'
117
156
  - '39775689'
118
- additional_sixth_prices:
157
+ additional_sixth_prizes:
119
158
  - '478'
120
159
  - '219'
121
160
  - year: 102
122
161
  start_month: 11
123
162
  end_month: 12
124
- so_special_price: '79599463'
125
- special_price: '65421688'
126
- head_prices:
163
+ special_prize: '79599463'
164
+ grand_prize: '65421688'
165
+ first_prizes:
127
166
  - '10823414'
128
167
  - '52261288'
129
168
  - '59201577'
130
- additional_sixth_prices:
169
+ additional_sixth_prizes:
131
170
  - 048
132
171
  - '913'
133
172
  - year: 102
134
173
  start_month: 9
135
174
  end_month: 10
136
- so_special_price: '46486534'
137
- special_price: 06509701
138
- head_prices:
175
+ special_prize: '46486534'
176
+ grand_prize: 06509701
177
+ first_prizes:
139
178
  - '73803836'
140
179
  - '48342247'
141
180
  - '12784009'
142
- additional_sixth_prices:
181
+ additional_sixth_prizes:
143
182
  - '316'
144
183
  - '226'
145
184
  - year: 102
146
185
  start_month: 7
147
186
  end_month: 8
148
- so_special_price: '71895847'
149
- special_price: 04949941
150
- head_prices:
187
+ special_prize: '71895847'
188
+ grand_prize: 04949941
189
+ first_prizes:
151
190
  - 04532693
152
191
  - '52951166'
153
192
  - '82155062'
154
- additional_sixth_prices:
193
+ additional_sixth_prizes:
155
194
  - '715'
156
- - year: 102
157
- start_month: 5
158
- end_month: 6
159
- so_special_price: '40148354'
160
- special_price: '64348046'
161
- head_prices:
162
- - '64782404'
163
- - '88904036'
164
- - '17250629'
165
- additional_sixth_prices:
166
- - '516'
167
- - year: 102
168
- start_month: 3
169
- end_month: 4
170
- so_special_price: '13393774'
171
- special_price: '25894576'
172
- head_prices:
173
- - '43792479'
174
- - 01973003
175
- - '71347425'
176
- additional_sixth_prices:
177
- - '997'
178
- - year: 102
179
- start_month: 1
180
- end_month: 2
181
- so_special_price: '18623268'
182
- special_price: '23322026'
183
- head_prices:
184
- - '55296725'
185
- - '65713406'
186
- - '44395947'
187
- additional_sixth_prices:
188
- - '436'
@@ -1,26 +1,18 @@
1
- require "uniform_invoice_lottery/version"
2
- require "uniform_invoice_lottery/data_crawler"
3
- require "uniform_invoice_lottery/lottery_checker"
4
- require "uniform_invoice_lottery/exceptions"
5
-
6
1
  module UniformInvoiceLottery
7
2
  ROOT_DIR = File.expand_path('..', __FILE__)
8
- PRICE = {
9
- "特別獎" => 10_000_000,
10
- "特獎" => 2_000_000,
11
- "頭獎" => 200_000,
12
- "二獎" => 40_000,
13
- "三獎" => 10_000,
14
- "四獎" => 4_000,
15
- "五獎" => 1_000,
16
- "六獎" => 200,
17
- "增開六獎" => 200,
18
- "下次再來,兩個月後又是一條好漢" => 0,
19
- }
3
+
4
+ require "uniform_invoice_lottery/version"
5
+ require "uniform_invoice_lottery/support"
6
+ require "uniform_invoice_lottery/exceptions"
7
+ require "uniform_invoice_lottery/prizes"
8
+ require "uniform_invoice_lottery/lottery_crawler"
9
+ require "uniform_invoice_lottery/lottery_check_service"
10
+
11
+ LotteryCrawler.update_lottery
20
12
 
21
13
  class << self
22
14
  def check invoice_code, opts={}
23
- LotteryChecker.check(invoice_code, opts)
15
+ LotteryCheckService.new.check(invoice_code, opts)
24
16
  end
25
17
  end
26
18
  end
@@ -2,4 +2,5 @@ module UniformInvoiceLottery
2
2
  class Error < StandardError; end
3
3
 
4
4
  class InvalidLotteryMonthError < StandardError; end
5
+ class InvalidArgumentsError < StandardError; end
5
6
  end
@@ -0,0 +1,57 @@
1
+ module UniformInvoiceLottery
2
+ class LotteryCheckService
3
+ include Support
4
+
5
+ def check invoice_code, opts={}
6
+
7
+ LotteryCrawler.update_lottery
8
+
9
+ record = load_record(opts)
10
+
11
+ return NullPrize.new if record.nil? # might raise an error
12
+
13
+ record.each{|k, v| instance_variable_set("@#{k}", v) }
14
+
15
+ return NullPrize.new if @special_prize.nil? || @grand_prize.nil? || @first_prizes.nil? || @additional_sixth_prizes.nil?
16
+ return SpecialPrize.new if invoice_code == @special_prize
17
+ return GrandPrize.new if invoice_code == @grand_prize
18
+
19
+ @first_prizes.each{|head| return FirstPrize.new if invoice_code == head }
20
+ @first_prizes.each{|head| return SecondPrize.new if invoice_code[1..-1] == head[1..-1] }
21
+ @first_prizes.each{|head| return ThirdPrize.new if invoice_code[2..-1] == head[2..-1] }
22
+ @first_prizes.each{|head| return FourthPrize.new if invoice_code[3..-1] == head[3..-1] }
23
+ @first_prizes.each{|head| return FifthPrize.new if invoice_code[4..-1] == head[4..-1] }
24
+ @first_prizes.each{|head| return SixthPrize.new if invoice_code[5..-1] == head[5..-1] }
25
+
26
+ @additional_sixth_prizes.each{|six| return AdditionalSixthPrize.new if invoice_code[-3..-1] == six}
27
+
28
+ return NullPrize.new
29
+ end
30
+
31
+ private
32
+
33
+ def load_record opts
34
+ if opts.is_a? Hash
35
+ options = %i(time year month day)
36
+ opts = Hash[opts.map{|k, v| [k.to_sym, v]}]
37
+
38
+ # white list filtering
39
+ opts = Hash[options.zip(opts.values_at(*options))]
40
+ end
41
+
42
+ @time = (
43
+ opts[:year] &&
44
+ opts[:month] &&
45
+ opts[:day] &&
46
+ Time.new(opts[:year], opts[:month], opts[:day])
47
+ ) || opts[:time] ||Time.now
48
+ start_month, end_month, year = get_lottery_date(get_draw_month(@time), @time.year)
49
+
50
+ record = LotteryCrawler.find_record_by(
51
+ year: year,
52
+ start_month: start_month,
53
+ end_month: end_month
54
+ )
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,134 @@
1
+ require 'nokogiri'
2
+ require 'httpclient'
3
+ require 'json'
4
+ require 'yaml'
5
+
6
+ module UniformInvoiceLottery
7
+ class LotteryCrawler
8
+ include Support
9
+ attr_accessor :records, :last_updated_at
10
+
11
+ class << self
12
+ def update_lottery
13
+ if !crawler.record_loaded?
14
+ crawler.load_record
15
+ end
16
+
17
+ if !crawler.latest?
18
+ crawler.fetch_lottery
19
+ crawler.save_record
20
+ end
21
+ end
22
+
23
+ def crawler
24
+ @@instance ||= self.new
25
+ end
26
+
27
+ def find_record_by year: nil, start_month: nil, end_month: nil
28
+ if !(year && start_month && end_month)
29
+ raise InvalidArgumentsError
30
+ end
31
+
32
+ return crawler.records.find{|rec| rec["year"] == year && rec["start_month"] == start_month && rec["end_month"] == end_month }
33
+ end
34
+ end
35
+
36
+ # instance methods
37
+ def fetch_lottery
38
+ # if no record found
39
+ @doc = Nokogiri::HTML(http_client.get_content "http://www.etax.nat.gov.tw/etwmain/front/ETW183W1")
40
+ # lottery_lists = [
41
+ # ["ETW183W2?id=14c4f826ecb00000aae8b5c3346d4493", "104年01月、02月"],
42
+ # ["ETW183W2?id=14b1f79bc5700000a9ef78b1708be70d", "103年11月、12月"],
43
+ # ["ETW183W2?id=149e58cdb5a00000d2d54a98932994cb", "103年09月、10月"],
44
+ # ...
45
+ # ]
46
+ lottery_lists = @doc.css('table#fbonly a').map{|node| [node[:href], node.text]}.select{|arr| !!arr[1].match(/(?<year>\d+)年(?<m1>\d+)月、(?<m2>\d+)月/)}
47
+
48
+ threads = []
49
+ @records = []
50
+
51
+ lottery_lists.each do |lot|
52
+ threads << Thread.new do
53
+ doc = Nokogiri::HTML(http_client.get_content("http://www.etax.nat.gov.tw/#{lot[0]}").to_s.force_encoding('utf-8'))
54
+ rows = doc.css('table tr')
55
+
56
+ m = doc.css('h4').text.match(/(?<year>\d+)年(?<m1>\d+)月、(?<m2>\d+)月/)
57
+ year = m[:year].to_i
58
+ start_month = m[:m1].to_i
59
+ end_month = m[:m2].to_i
60
+
61
+ prizes = doc.css('span.t18Red').map(&:text)
62
+
63
+ special_prize = prizes[0]
64
+ grand_prize = prizes[1]
65
+ first_prizes = prizes[2].split('、')
66
+ additional_sixth_prizes = prizes[3].split('、')
67
+
68
+ @records << {
69
+ "year" => year,
70
+ "start_month" => start_month,
71
+ "end_month" => end_month,
72
+ "special_prize" => special_prize,
73
+ "grand_prize" => grand_prize,
74
+ "first_prizes" => first_prizes,
75
+ "additional_sixth_prizes" => additional_sixth_prizes,
76
+ }
77
+ end # Thread.new do
78
+ end # lottery_lists.each
79
+
80
+ threads.map(&:join)
81
+
82
+ sort_record!
83
+ @records
84
+ end # crawl_lottery_data
85
+
86
+ def load_record dir=ROOT_DIR
87
+ filepath = File.join(dir, 'record.yaml')
88
+ return false if !File.exists?(filepath)
89
+
90
+ data = YAML.load(File.read(File.join(dir, 'record.yaml')))
91
+
92
+ @last_updated_at = Time.parse data["last_updated_at"]
93
+ @records = data["records"]
94
+
95
+ true
96
+ end
97
+
98
+ def save_record dir=ROOT_DIR
99
+ data = {
100
+ "last_updated_at" => Time.now.to_s,
101
+ "records" => @records
102
+ }
103
+ File.write(File.join(dir, 'record.yaml'), data.to_yaml)
104
+ end
105
+
106
+ def latest?
107
+ start_month, end_month, year = get_lottery_date
108
+
109
+ # 最近年分不是空的就是最新
110
+ return (
111
+ @last_updated_at && @records && !@records.empty? && !@records.find{ |rec|
112
+ rec["year"] == year && rec["start_month"] == start_month && rec["end_month"] == end_month
113
+ }.nil?)
114
+ end
115
+
116
+ def record_loaded?
117
+ !@records.nil?
118
+ end
119
+
120
+ private
121
+
122
+ def http_client
123
+ @client ||= HTTPClient.new
124
+ end
125
+
126
+ def td_xpath(th)
127
+ return "\/\/th\[.=\"#{th}\"\]\/ancestor::tr\/td"
128
+ end
129
+
130
+ def sort_record!
131
+ @records = @records.sort_by{ |rec| "#{rec["year"]}#{rec["end_month"].to_s.rjust(2, "0")}".to_i }.reverse!
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,75 @@
1
+ module UniformInvoiceLottery
2
+ class Prize
3
+ def title
4
+ self.class.const_get(:TITLE)
5
+ end
6
+
7
+ def amount
8
+ self.class.const_get(:AMOUNT)
9
+ end
10
+
11
+ def priority
12
+ self.class.const_get(:PRIORITY)
13
+ end
14
+ end
15
+
16
+ class SpecialPrize < Prize
17
+ TITLE = "特別獎"
18
+ AMOUNT = 10_000_000
19
+ PRIORITY = 1
20
+ end
21
+
22
+ class GrandPrize < Prize
23
+ TITLE = "特獎"
24
+ AMOUNT = 2_000_000
25
+ PRIORITY = 2
26
+ end
27
+
28
+ class FirstPrize < Prize
29
+ TITLE = "頭獎"
30
+ AMOUNT = 200_000
31
+ PRIORITY = 3
32
+ end
33
+
34
+ class SecondPrize < Prize
35
+ TITLE = "二獎"
36
+ AMOUNT = 40_000
37
+ PRIORITY = 4
38
+ end
39
+
40
+ class ThirdPrize < Prize
41
+ TITLE = "三獎"
42
+ AMOUNT = 10_000
43
+ PRIORITY = 5
44
+ end
45
+
46
+ class FourthPrize < Prize
47
+ TITLE = "四獎"
48
+ AMOUNT = 4000
49
+ PRIORITY = 6
50
+ end
51
+
52
+ class FifthPrize < Prize
53
+ TITLE = "五獎"
54
+ AMOUNT = 1000
55
+ PRIORITY = 7
56
+ end
57
+
58
+ class SixthPrize < Prize
59
+ TITLE = "六獎"
60
+ AMOUNT = 200
61
+ PRIORITY = 8
62
+ end
63
+
64
+ class AdditionalSixthPrize < Prize
65
+ TITLE = "增開六獎"
66
+ AMOUNT = 200
67
+ PRIORITY = 9
68
+ end
69
+
70
+ class NullPrize < Prize
71
+ TITLE = "沒中"
72
+ AMOUNT = 0
73
+ PRIORITY = 999
74
+ end
75
+ end
@@ -0,0 +1,32 @@
1
+ module UniformInvoiceLottery
2
+ module Support
3
+
4
+ # 計算開獎月份
5
+ def get_draw_month time=Time.now
6
+ if time.month % 2 == 1
7
+ if time.day >= 25 # 奇數月開獎後那幾天
8
+ return time.month
9
+ else
10
+ return time.month-2 < 0 ? (time.month-2 + 12) : time.month-2
11
+ end
12
+ else # 偶數月,一律是在前一個月
13
+ return time.month-1
14
+ end
15
+ end
16
+
17
+ # 回傳開獎月份數組
18
+ def get_lottery_months draw_month=get_draw_month
19
+ # draw_month = get_draw_month(draw_month) if draw_month % 2 == 0
20
+ raise InvalidLotteryMonthError, "奇數月開獎" if draw_month % 2 == 0
21
+ return (draw_month-2 + 12)%12, (draw_month-2 + 12)%12 + 1
22
+ end
23
+
24
+ def get_lottery_date draw_month=get_draw_month, year=Time.now.year
25
+ raise InvalidLotteryMonthError, "奇數月開獎" if draw_month % 2 == 0
26
+ start_month, end_month = (draw_month-2 + 12)%12, (draw_month-2 + 12)%12 + 1
27
+ year -= 1 if [start_month, end_month] == [11, 12] # 前一年的開獎
28
+ return start_month, end_month, year-1911
29
+ end
30
+
31
+ end
32
+ end
@@ -1,3 +1,3 @@
1
1
  module UniformInvoiceLottery
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -1,36 +1,36 @@
1
- require 'spec_helper'
2
- require 'uniform_invoice_lottery'
3
-
4
- describe UniformInvoiceLottery::DataCrawler do
5
-
6
- let(:data_crawler) {
7
- UniformInvoiceLottery::DataCrawler
8
- }
9
-
10
- describe "test DataCrawler module" do
11
- it "should have DataCrawler sub module" do
12
- records = data_crawler.records
13
-
14
- expect(records.class).to eq(Array)
15
-
16
- unless records.empty?
17
- expect(records.first.class).to eq(Hash)
18
- %w(year start_month end_month so_special_price special_price head_prices additional_sixth_prices).each {|k|
19
- expect(records.first).to have_key(k)
20
- }
21
- end
22
- end
23
-
24
- it "should calculate correct lottery month" do
25
- expect(data_crawler.get_draw_month( Time.new(2015, 1, 15) )).to eq(11)
26
- expect(data_crawler.get_draw_month( Time.new(2015, 1, 25) )).to eq( 1)
27
- expect(data_crawler.get_draw_month( Time.new(2015, 2, 28) )).to eq( 1)
28
-
29
- expect(data_crawler.get_lottery_months(3)).to eq([1,2])
30
- expect(data_crawler.get_lottery_months(1)).to eq([11,12])
31
- # 奇數月開獎的說
32
- expect{ data_crawler.get_lottery_months(2) }.to raise_error(UniformInvoiceLottery::InvalidLotteryMonthError)
33
- end
34
- end
35
-
36
- end
1
+ # require 'spec_helper'
2
+ # require 'uniform_invoice_lottery'
3
+
4
+ # describe UniformInvoiceLottery::DataCrawler do
5
+
6
+ # let(:data_crawler) {
7
+ # UniformInvoiceLottery::DataCrawler
8
+ # }
9
+
10
+ # describe "test DataCrawler module" do
11
+ # it "should have DataCrawler sub module" do
12
+ # records = data_crawler.records
13
+
14
+ # expect(records.class).to eq(Array)
15
+
16
+ # unless records.empty?
17
+ # expect(records.first.class).to eq(Hash)
18
+ # %w(year start_month end_month so_special_price special_price head_prices additional_sixth_prices).each {|k|
19
+ # expect(records.first).to have_key(k)
20
+ # }
21
+ # end
22
+ # end
23
+
24
+ # it "should calculate correct lottery month" do
25
+ # expect(data_crawler.get_draw_month( Time.new(2015, 1, 15) )).to eq(11)
26
+ # expect(data_crawler.get_draw_month( Time.new(2015, 1, 25) )).to eq( 1)
27
+ # expect(data_crawler.get_draw_month( Time.new(2015, 2, 28) )).to eq( 1)
28
+
29
+ # expect(data_crawler.get_lottery_months(3)).to eq([1,2])
30
+ # expect(data_crawler.get_lottery_months(1)).to eq([11,12])
31
+ # # 奇數月開獎的說
32
+ # expect{ data_crawler.get_lottery_months(2) }.to raise_error(UniformInvoiceLottery::InvalidLotteryMonthError)
33
+ # end
34
+ # end
35
+
36
+ # end
@@ -3,6 +3,6 @@ require 'uniform_invoice_lottery'
3
3
 
4
4
  describe UniformInvoiceLottery do
5
5
  it "can check lottery" do
6
- expect(UniformInvoiceLottery.check('82930261', time: Time.new(2015, 7, 26))).to eq("特別獎")
6
+ expect(UniformInvoiceLottery.check('82930261', time: Time.new(2015, 7, 26)).title).to eq("特別獎")
7
7
  end
8
8
  end
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["yukaihuang1993@hotmail.com"]
11
11
  spec.summary = %q{一個統一發票的查詢、兌獎 gem}
12
12
  spec.description = %q{一個統一發票的查詢、兌獎 gem}
13
- spec.homepage = ""
13
+ spec.homepage = "https://github.com/Yukaii/uniform-invoice-lottery"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uniform_invoice_lottery
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yukai Huang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-07 00:00:00.000000000 Z
11
+ date: 2016-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -208,15 +208,17 @@ files:
208
208
  - Rakefile
209
209
  - lib/record.yaml
210
210
  - lib/uniform_invoice_lottery.rb
211
- - lib/uniform_invoice_lottery/data_crawler.rb
212
211
  - lib/uniform_invoice_lottery/exceptions.rb
213
- - lib/uniform_invoice_lottery/lottery_checker.rb
212
+ - lib/uniform_invoice_lottery/lottery_check_service.rb
213
+ - lib/uniform_invoice_lottery/lottery_crawler.rb
214
+ - lib/uniform_invoice_lottery/prizes.rb
215
+ - lib/uniform_invoice_lottery/support.rb
214
216
  - lib/uniform_invoice_lottery/version.rb
215
217
  - spec/data_crawler_spec.rb
216
218
  - spec/spec_helper.rb
217
219
  - spec/uniform_invoice_lottery_spec.rb
218
220
  - uniform_invoice_lottery.gemspec
219
- homepage: ''
221
+ homepage: https://github.com/Yukaii/uniform-invoice-lottery
220
222
  licenses:
221
223
  - MIT
222
224
  metadata: {}
@@ -244,3 +246,4 @@ test_files:
244
246
  - spec/data_crawler_spec.rb
245
247
  - spec/spec_helper.rb
246
248
  - spec/uniform_invoice_lottery_spec.rb
249
+ has_rdoc:
@@ -1,149 +0,0 @@
1
- require 'nokogiri'
2
- require 'httpclient'
3
- require 'json'
4
- require 'yaml'
5
-
6
- module UniformInvoiceLottery
7
- module DataCrawler
8
-
9
- class Crawler
10
- attr_accessor :records, :last_updated_at
11
-
12
- def crawl_lottery_data
13
- # not record found
14
- @doc = Nokogiri::HTML(client.get_content "http://www.etax.nat.gov.tw/etwmain/front/ETW183W1")
15
- # lottery_lists = [
16
- # ["ETW183W2?id=14c4f826ecb00000aae8b5c3346d4493", "104年01月、02月"],
17
- # ["ETW183W2?id=14b1f79bc5700000a9ef78b1708be70d", "103年11月、12月"],
18
- # ["ETW183W2?id=149e58cdb5a00000d2d54a98932994cb", "103年09月、10月"],
19
- # ...
20
- # ]
21
- lottery_lists = @doc.css('#searchForm a').map{|node| [node[:href], node.text]}.select{|arr| !!arr[1].match(/(?<year>\d+)年(?<m1>\d+)月、(?<m2>\d+)月/)}
22
-
23
- threads = []
24
-
25
- lottery_lists.each do |lot|
26
- threads << Thread.new do
27
- doc = Nokogiri::HTML(client.get_content("http://www.etax.nat.gov.tw/etwmain/front/#{lot[0]}").to_s.force_encoding('utf-8'))
28
- rows = doc.css('table.table_b tr')
29
-
30
- m = doc.css('h4').text.match(/(?<year>\d+)年(?<m1>\d+)月、(?<m2>\d+)月/)
31
- year = m[:year].to_i
32
- start_month = m[:m1].to_i
33
- end_month = m[:m2].to_i
34
- so_special_price = rows.xpath(td_xpath "特別獎" ).text.strip
35
- special_price = rows.xpath(td_xpath "特獎" ).text.strip
36
- head_prices = rows.xpath(td_xpath "頭獎" ).text.strip.split('、')
37
- additional_sixth_prices = rows.xpath(td_xpath "增開六獎" ).text.strip.split('、')
38
-
39
- records << {
40
- "year" => year,
41
- "start_month" => start_month,
42
- "end_month" => end_month,
43
- "so_special_price" => so_special_price,
44
- "special_price" => special_price,
45
- "head_prices" => head_prices,
46
- "additional_sixth_prices" => additional_sixth_prices,
47
- }
48
- end # Thread.new do
49
- end # lottery_lists.each
50
-
51
- threads.map(&:join)
52
-
53
- sort_record!
54
- records
55
- end # crawl_lottery_data
56
-
57
- def sort_record!
58
- @records = @records.sort_by{ |rec| "#{rec["year"]}#{rec["end_month"].to_s.rjust(2, "0")}".to_i }.reverse!
59
- end
60
-
61
- def td_xpath(th)
62
- return "\/\/th\[.=\"#{th}\"\]\/ancestor::tr\/td"
63
- end
64
-
65
- def records
66
- @records ||= []
67
- end
68
-
69
- private
70
- def client
71
- @client ||= HTTPClient.new
72
- end
73
- end
74
-
75
- class << self
76
-
77
- def refresh
78
- crawler.crawl_lottery_data
79
- save_record
80
- crawler.records
81
- end
82
-
83
- def records
84
- load
85
- crawler.records
86
- end
87
-
88
- def get_draw_month time=Time.now
89
- if time.month % 2 == 1
90
- if time.day >= 25 # 奇數月開獎後那幾天
91
- return time.month
92
- else
93
- return time.month-2 < 0 ? (time.month-2 + 12) : time.month-2
94
- end
95
- else # 偶數月
96
- return time.month-1
97
- end
98
- end
99
-
100
- def get_lottery_months draw_month=get_draw_month
101
- # draw_month = get_draw_month(draw_month) if draw_month % 2 == 0
102
- raise InvalidLotteryMonthError, "奇數月開獎" if draw_month % 2 == 0
103
- return (draw_month-2 + 12)%12, (draw_month-2 + 12)%12 + 1
104
- end
105
-
106
- private
107
-
108
- def load
109
- if load_record
110
-
111
- srt_month, end_month = get_lottery_months
112
- year = Time.now.year - 1911
113
- return if crawler.last_updated_at && crawler.records && !crawler.records.empty? &&
114
- !crawler.records.find{ |rec|
115
- rec["year"] == year && rec["start_month"] == srt_month && rec["end_month"] == end_month
116
- }.nil?
117
- end
118
-
119
- crawler.crawl_lottery_data
120
- save_record
121
- end
122
-
123
- def load_record dir=ROOT_DIR
124
- filepath = File.join(dir, 'record.yaml')
125
- return false if !File.exists?(filepath)
126
-
127
- data = YAML.load(File.read(File.join(dir, 'record.yaml')))
128
-
129
- crawler.last_updated_at = Time.parse data["last_updated_at"]
130
- crawler.records = data["records"]
131
-
132
- true
133
- end
134
-
135
- def save_record dir=ROOT_DIR
136
- data = {
137
- "last_updated_at" => Time.now.to_s,
138
- "records" => crawler.records
139
- }
140
- File.write(File.join(dir, 'record.yaml'), data.to_yaml)
141
- end
142
-
143
- def crawler
144
- @@crawler ||= Crawler.new
145
- end
146
-
147
- end # end class << self
148
- end
149
- end
@@ -1,45 +0,0 @@
1
- module UniformInvoiceLottery
2
- module LotteryChecker
3
- class << self
4
- def check invoice_code, opts={}
5
-
6
- # option handling
7
- if opts.is_a? Hash
8
- options = %i(time year month day)
9
- opts = Hash[opts.map{|k, v| [k.to_sym, v]}]
10
-
11
- # white list =w=
12
- opts = Hash[options.zip(opts.values_at(*options))]
13
-
14
- opts.each{|k, v| instance_variable_set("@#{k}", v) }
15
- end
16
-
17
- @time ||= Time.new(@year, @month, @day) if @year && @month && @day
18
- @time ||= Time.now
19
-
20
- @start_month, @end_month = DataCrawler.get_lottery_months(DataCrawler.get_draw_month(@time))
21
-
22
- record = DataCrawler.records.find{|rec| rec["year"] == @time.year-1911 && rec["start_month"] == @start_month && rec["end_month"] == @end_month }
23
-
24
- return "Lottery Data not Found" if record.nil?
25
-
26
- record.each{|k, v| instance_variable_set("@#{k}", v) }
27
-
28
- return "錯誤" if @so_special_price.nil? || @special_price.nil? || @head_prices.nil? || @additional_sixth_prices.nil?
29
- return "特別獎" if invoice_code == @so_special_price
30
- return "特獎" if invoice_code == @special_price
31
-
32
- @head_prices.each{|head| return "頭獎" if invoice_code == head }
33
- @head_prices.each{|head| return "二獎" if invoice_code[1..-1] == head[1..-1] }
34
- @head_prices.each{|head| return "三獎" if invoice_code[2..-1] == head[2..-1] }
35
- @head_prices.each{|head| return "四獎" if invoice_code[3..-1] == head[3..-1] }
36
- @head_prices.each{|head| return "五獎" if invoice_code[4..-1] == head[4..-1] }
37
- @head_prices.each{|head| return "六獎" if invoice_code[5..-1] == head[5..-1] }
38
-
39
- @additional_sixth_prices.each{|six| return "增開六獎" if invoice_code[-3..-1] == six}
40
-
41
- return "下次再來,兩個月後又是一條好漢"
42
- end
43
- end
44
- end
45
- end