cineworld_uk 1.0.5 → 2.0.0

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +64 -0
  4. data/README.md +2 -1
  5. data/cineworld_uk.gemspec +3 -3
  6. data/lib/cineworld_uk/cinema.rb +60 -69
  7. data/lib/cineworld_uk/film.rb +25 -7
  8. data/lib/cineworld_uk/internal/film_with_screenings_parser.rb +29 -71
  9. data/lib/cineworld_uk/internal/name_parser.rb +20 -18
  10. data/lib/cineworld_uk/internal/screening_parser.rb +132 -0
  11. data/lib/cineworld_uk/internal/titleize.rb +19 -19
  12. data/lib/cineworld_uk/internal/website.rb +33 -0
  13. data/lib/cineworld_uk/internal/whatson_parser.rb +44 -0
  14. data/lib/cineworld_uk/screening.rb +65 -20
  15. data/lib/cineworld_uk/version.rb +2 -2
  16. data/lib/cineworld_uk.rb +4 -0
  17. data/test/fixture_updater.rb +64 -0
  18. data/test/fixtures/cinemas.html +134 -41
  19. data/test/fixtures/{cinemas/bury-st-edmunds.html → information/brighton.html} +488 -437
  20. data/test/fixtures/{cinemas → information}/bristol.html +463 -410
  21. data/test/fixtures/whatson/brighton/film_first.html +775 -0
  22. data/test/fixtures/whatson/brighton/film_last.html +52 -0
  23. data/test/fixtures/whatson/brighton/film_second.html +645 -0
  24. data/test/fixtures/whatson/brighton.html +3564 -2690
  25. data/test/fixtures/whatson/glasgow-imax-at-gsc/film_first.html +140 -0
  26. data/test/fixtures/whatson/the-o2-greenwich/film_first.html +1242 -0
  27. data/test/lib/cineworld_uk/cinema_test.rb +104 -301
  28. data/test/lib/cineworld_uk/film_test.rb +49 -2
  29. data/test/lib/cineworld_uk/internal/film_with_screenings_parser_test.rb +83 -81
  30. data/test/lib/cineworld_uk/internal/titleize_test.rb +12 -5
  31. data/test/lib/cineworld_uk/internal/website_test.rb +57 -0
  32. data/test/lib/cineworld_uk/internal/whatson_parser_test.rb +58 -0
  33. data/test/lib/cineworld_uk/screening_test.rb +155 -23
  34. data/test/lib/cineworld_uk/version_test.rb +1 -1
  35. data/test/test_helper.rb +3 -1
  36. metadata +30 -33
  37. data/test/fixtures/cinemas/brighton.html +0 -8
  38. data/test/fixtures/cinemas/chelsea.html +0 -1030
  39. data/test/fixtures/cinemas/glasgow-imax-at-gsc.html +0 -916
  40. data/test/fixtures/cinemas/the-o2-grenwich.html +0 -1191
  41. data/test/fixtures/whatson/brighton/gravity.html +0 -2129
  42. data/test/fixtures/whatson/glasgow-imax-at-gsc/the-hunger-games-catching-fire.html +0 -498
  43. data/test/fixtures/whatson/glasgow-imax-at-gsc-cinema.html +0 -3160
  44. data/test/fixtures/whatson/the-o2-greenwich/gravity.html +0 -784
  45. data/test/fixtures/whatson/the-o2-greenwich/the-hobbit-desolation-of-smaug.html +0 -764
  46. data/test/fixtures/whatson/the-o2-greenwich.html +0 -6854
  47. data/test/fixtures/whatson/wandsworth.html +0 -13729
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0c228d909dc018b2ffa88f58841c53df17355f4c
4
- data.tar.gz: 65837db94438ac24f9e8460f1765495835a482fc
3
+ metadata.gz: edcee9dcbbce90d73acbbb0ccc5650811bb7f931
4
+ data.tar.gz: 8454e532aa948af962692ce9d1add716b79dd405
5
5
  SHA512:
6
- metadata.gz: 02646d623f4f7d13a8f3927283be7d17a9dbe0e8f8e2e3c3d1b31d40075858e28b6fb7b2aae321b72b3c1a25ab608f3821369bb2f608ebde31b75d1baa798130
7
- data.tar.gz: 6cabf2784246c4d1816537221abd885ba19bbbca46335a6d5b1830e7da23e99914ae057e46c13d4182184fa0c6330fc07da06a3ed9f45578f231e898cac0a7d6
6
+ metadata.gz: 55369938b4df8ad874982a708dccb985b48f1514d2a6210e24371bcdf66f575dde627456cb4567fda757d37759bb9b0d7d6cccb8e2ed1865e2f70d7134ebefcf
7
+ data.tar.gz: 9d79dc209c5091269612dc732388d5160876defdaeef29ec7820656e5c1c3f32203144194dd5cfbc44b85ef5a1c041456a2a7974ff132941e79e9a894f6a3fd7
data/.travis.yml CHANGED
@@ -2,4 +2,4 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
- - 2.1.0
5
+ - 2.1.2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,67 @@
1
+ ## 2.0.0 _25th July 2014_
2
+
3
+ Bugfix
4
+
5
+ - Cineworld changed their markup
6
+
7
+ Features
8
+
9
+ - Less logic in the Cinema class. Moved to `Film` and `Screening`.
10
+ - Introduce `Internal::Website` class for all website comms
11
+ - Rewrite Parsers and tests to be less exact but less fragile
12
+ - Screening now uses the `FilmWithScreeningsParser`
13
+ - Build `WhatsonParser` to break into 'films with screenings'
14
+ - `FilmWithScreenings` then uses `ScreeningParser` class to get individual screening info
15
+ - `ruby test/fixture_updator.rb` produces new fixtures from the live website
16
+ - it will break a few tests when run and committed but most should be ok
17
+ - documentation
18
+
19
+ Under the hood
20
+
21
+ - Remove dependancy on HTTParty
22
+ - Travis gets Ruby 2.1.2
23
+ - General Rubocop improvements
24
+
25
+ ## 1.0.6 _28th Feb 2014_
26
+
27
+ Bugfix
28
+
29
+ - UTF encoding in Titleize internal class for ruby 1.9.3
30
+
31
+ ## 1.0.5 _28th Feb 2014_
32
+
33
+ Bugfix
34
+
35
+ - Vestigal require of titleize gem
36
+
37
+ ## 1.0.4 _27th Feb 2014_
38
+
39
+ Under the hood
40
+
41
+ - Standardizing film names using modified titlecase from `titlecase` gem
42
+ - Film name parsing now moved to seperate class
43
+ - rake console task added
44
+ - MRI 2.1.0 support on Travis CI
45
+
46
+ ## 1.0.3, _16th Jan 2014_
47
+
48
+ Additional methods
49
+
50
+ - cinema#full_name including cinema brand
51
+ - tidy up cinema naming to use colons
52
+
53
+ ## 1.0.2, _3rd Jan 2014_
54
+
55
+ Under the hood
56
+
57
+ - deal with HFR screenings, bloody hobbitses
58
+
59
+ ## 1.0.1, _3rd Jan 2014_
60
+
61
+ External interface
62
+
63
+ - screening#variant for spelling win, #varient maintained for compatability
64
+
1
65
  ## 1.0.0, _6th Dec 2013_
2
66
 
3
67
  First ready-for-public release
data/README.md CHANGED
@@ -2,9 +2,10 @@
2
2
 
3
3
  A simple gem to parse the [Cineworld UK website](http://cineworld.co.uk) and spit out useful formatted info.
4
4
 
5
- [![Gem Version](https://badge.fury.io/rb/cineword_uk.png)](http://badge.fury.io/rb/cineworld_uk)
5
+ [![Gem Version](https://badge.fury.io/rb/cineworld_uk.svg)](http://badge.fury.io/rb/cineworld_uk)
6
6
  [![Code Climate](https://codeclimate.com/github/andycroll/cineworld_uk.png)](https://codeclimate.com/github/andycroll/cineworld_uk)
7
7
  [![Build Status](https://travis-ci.org/andycroll/cineworld_uk.png?branch=master)](https://travis-ci.org/andycroll/cineworld_uk)
8
+ [![Inline docs](http://inch-ci.org/github/andycroll/cineworld_uk.png)](http://inch-ci.org/github/andycroll/cineworld_uk)
8
9
 
9
10
  ## Installation
10
11
 
data/cineworld_uk.gemspec CHANGED
@@ -18,11 +18,11 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "rake"
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'minitest-reporters'
23
+ spec.add_development_dependency 'rake'
23
24
  spec.add_development_dependency 'webmock'
24
25
 
25
- spec.add_runtime_dependency 'httparty'
26
26
  spec.add_runtime_dependency 'nokogiri'
27
27
  spec.add_runtime_dependency 'tzinfo'
28
28
  spec.add_runtime_dependency 'tzinfo-data'
@@ -1,11 +1,9 @@
1
1
  module CineworldUk
2
-
3
2
  # The object representing a cinema on the Cineworld UK website
4
3
  class Cinema
5
-
6
4
  # @return [String] the brand of the cinema
7
5
  attr_reader :brand
8
- # @return [Integer] the numeric id of the cinema on the Odeon website
6
+ # @return [Integer] the numeric id of the cinema on the Cineworld website
9
7
  attr_reader :id
10
8
  # @return [String] the name of the cinema
11
9
  attr_reader :name
@@ -20,8 +18,8 @@ module CineworldUk
20
18
  def initialize(id, name)
21
19
  @brand = 'Cineworld'
22
20
  @id = id.to_i
23
- @name = name.gsub('London - ','').gsub(' - ', ': ')
24
- @slug = @name.downcase.gsub(/[^0-9a-z ]/,'').gsub(/\s+/, '-')
21
+ @name = name.gsub('London - ', '').gsub(' - ', ': ')
22
+ @slug = @name.downcase.gsub(/[^0-9a-z ]/, '').gsub(/\s+/, '-')
25
23
  @url = "http://www.cineworld.co.uk/cinemas/#{@id}/information"
26
24
  end
27
25
 
@@ -29,32 +27,39 @@ module CineworldUk
29
27
  # @return [Array<CineworldUk::Cinema>]
30
28
  # @example
31
29
  # CineworldUk::Cinema.all
32
- # #=> [<CineworldUk::Cinema brand="Cineworld" name="Brighton" slug="brighton" id=3 url="...">, <CineworldUk::Cinema brand="Cineworld" name="The O2, Greenwich" slug="the-o2-greenwich" url="...">, ...]
30
+ # #=> [<CineworldUk::Cinema>, <CineworldUk::Cinema>, ...]
33
31
  def self.all
34
- parsed_cinemas.css('#cinemaId option[value]').map do |option|
32
+ cinemas_doc.css('#cinemaId option[value]').map do |option|
35
33
  new option['value'], option.text
36
34
  end[1..-1]
37
35
  end
38
36
 
39
37
  # Find a single cinema
40
- # @param [Integer, String] id the cinema id of the format 3/'3' as used on the cineworld.co.uk website
38
+ # @param [Integer, String] id the cinema id as used on the website
41
39
  # @return [CineworldUk::Cinema, nil]
42
40
  # @example
43
41
  # CineworldUk::Cinema.find('3')
44
- # #=> <CineworldUk::Cinema brand="Cineworld" name="Brighton" slug="brighton" id=3 url="...">
42
+ # #=> <CineworldUk::Cinema brand="Cineworld"
43
+ # name="Brighton"
44
+ # slug="brighton"
45
+ # id=3
46
+ # url="...">
45
47
  def self.find(id)
46
- id = id.to_i
47
- return nil unless id > 0
48
-
49
- all.select { |cinema| cinema.id == id }[0]
48
+ all.select { |cinema| cinema.id == id.to_i }[0]
50
49
  end
51
50
 
52
51
  # Address of the cinema
53
52
  # @return [Hash] of different address parts
54
53
  # @example
55
- # cinema = CineworldUk::Cinema.find('Dukes_At_Komedia')
54
+ # cinema = CineworldUk::Cinema.find(3)
56
55
  # cinema.adr
57
- # #=> { street_address: '44-47 Gardner Street', extended_address: 'North Laine', locality: 'Brighton', postal_code: 'BN1 1UN', country_name: 'United Kingdom' }
56
+ # #=> {
57
+ # street_address: '44-47 Gardner Street',
58
+ # extended_address: 'North Laine',
59
+ # locality: 'Brighton',
60
+ # postal_code: 'BN1 1UN',
61
+ # country_name: 'United Kingdom'
62
+ # }
58
63
  # @note Uses the standard method naming as at http://microformats.org/wiki/adr
59
64
  def adr
60
65
  {
@@ -80,20 +85,17 @@ module CineworldUk
80
85
  # #=> nil
81
86
  # @note Uses the standard method naming as at http://microformats.org/wiki/adr
82
87
  def extended_address
83
- remaining_address * ', ' unless remaining_address.empty?
88
+ remaining_address * ', ' unless remaining_address.empty?
84
89
  end
85
90
 
86
91
  # Films with showings scheduled at this cinema
87
- # @return [Array<OdeonUk::Film>]
92
+ # @return [Array<CineworldUk::Film>]
88
93
  # @example
89
- # cinema = OdeonUk::Cinema.find('71')
94
+ # cinema = CineworldUk::Cinema.find('71')
90
95
  # cinema.films
91
- # #=> [<OdeonUk::Film name="Iron Man 3">, <OdeonUk::Film name="Star Trek Into Darkness">]
96
+ # #=> [<CineworldUk::Film>, <CineworldUk::Film>, ...]
92
97
  def films
93
- film_nodes.map do |node|
94
- parser = CineworldUk::Internal::FilmWithScreeningsParser.new node.to_s
95
- parser.film_name.length > 0 ? CineworldUk::Film.new(parser.film_name) : nil
96
- end.compact.uniq
98
+ Film.at(id)
97
99
  end
98
100
 
99
101
  # The name of the cinema including the brand
@@ -114,7 +116,11 @@ module CineworldUk
114
116
  # #=> 'Brighton'
115
117
  # @note Uses the standard method naming as at http://microformats.org/wiki/adr
116
118
  def locality
117
- adr_has_region? && !adr_in_london? ? final_address_array[-2] : final_address_array[-1]
119
+ if adr_has_region? && !adr_in_london?
120
+ adr_array[-2]
121
+ else
122
+ adr_array[-1]
123
+ end
118
124
  end
119
125
 
120
126
  # Post code of the cinema
@@ -125,7 +131,7 @@ module CineworldUk
125
131
  # #=> 'BN2 5UF'
126
132
  # @note Uses the standard method naming as at http://microformats.org/wiki/adr
127
133
  def postal_code
128
- final_line_array[-2..-1]*' '
134
+ last_adr_line_array[-2..-1] * ' '
129
135
  end
130
136
 
131
137
  # The region (county) of the cinema if provided
@@ -136,7 +142,7 @@ module CineworldUk
136
142
  # #=> 'East Sussex'
137
143
  # @note Uses the standard method naming as at http://microformats.org/wiki/adr
138
144
  def region
139
- final_line_non_postal_code if adr_has_region? && !adr_in_london?
145
+ last_adr_line_non_postal_code if adr_has_region? && !adr_in_london?
140
146
  end
141
147
 
142
148
  # All planned screenings
@@ -144,16 +150,9 @@ module CineworldUk
144
150
  # @example
145
151
  # cinema = CineworldUk::Cinema.find(3)
146
152
  # cinema.screenings
147
- # # => [<CineworldUk::Screening film_name="Iron Man 3" cinema_name="Brighton" when="..." variant="...">, <CineworldUk::Screening ...>]
153
+ # # => [<CineworldUk::Screening>, <CineworldUk::Screening>, ...]
148
154
  def screenings
149
- film_nodes.map do |node|
150
- parser = CineworldUk::Internal::FilmWithScreeningsParser.new node.to_s
151
- parser.showings.map do |screening_type, times|
152
- times.map do |array|
153
- CineworldUk::Screening.new parser.film_name, self.name, array[0], array[1], screening_type
154
- end
155
- end
156
- end.flatten
155
+ Screening.at(id)
157
156
  end
158
157
 
159
158
  # The street adress of the cinema
@@ -164,65 +163,57 @@ module CineworldUk
164
163
  # #=> 'Brighton Marina'
165
164
  # @note Uses the standard method naming as at http://microformats.org/wiki/adr
166
165
  def street_address
167
- address_parts[0]
166
+ adr_parts[0]
168
167
  end
169
168
 
170
169
  private
171
170
 
172
- def self.parsed_cinemas
173
- @parsed_cinemas ||= Nokogiri::HTML(cinemas_response)
174
- end
175
-
176
- def self.cinemas_response
177
- @cinemas_response ||= HTTParty.get('http://www.cineworld.co.uk/cinemas')
178
- end
179
-
180
- def address_parts
181
- @address_parts ||= parsed_information.css('address.marker').to_s.split('<br>')[-2].split(',').map(&:strip)
171
+ def self.cinemas_doc
172
+ @cinemas_doc ||= Nokogiri::HTML(website.cinemas)
182
173
  end
183
174
 
184
- def adr_in_london?
185
- final_line_non_postal_code == 'London'
175
+ def self.website
176
+ @website ||= CineworldUk::Internal::Website.new
186
177
  end
187
178
 
188
- def adr_has_region?
189
- final_line_non_postal_code != name
179
+ def adr_array
180
+ adr_parts[0..-2] << last_adr_line_non_postal_code
190
181
  end
191
182
 
192
- def film_nodes
193
- @film_nodes ||= parsed_whatson.css('.section.light #filter-reload > .span9').to_s.split('<hr>')
183
+ def adr_content
184
+ information_doc.css('address.marker').to_s
194
185
  end
195
186
 
196
- def final_address_array
197
- address_parts[0..-2] << final_line_non_postal_code
187
+ def adr_parts
188
+ @parts ||= adr_content.split('<br>')[-2].split(',').map(&:strip)
198
189
  end
199
190
 
200
- def final_line_array
201
- address_parts[-1].split(' ')
191
+ def adr_in_london?
192
+ last_adr_line_non_postal_code == 'London'
202
193
  end
203
194
 
204
- def final_line_non_postal_code
205
- final_line_array[0..-3]*' '
195
+ def adr_has_region?
196
+ last_adr_line_non_postal_code != name
206
197
  end
207
198
 
208
- def information_response
209
- @information_response ||= HTTParty.get("http://www.cineworld.co.uk/cinemas/#{@id}/information")
199
+ def last_adr_line_array
200
+ adr_parts[-1].split(' ')
210
201
  end
211
202
 
212
- def parsed_information
213
- @parsed_information ||= Nokogiri::HTML(information_response)
203
+ def last_adr_line_non_postal_code
204
+ last_adr_line_array[0..-3] * ' '
214
205
  end
215
206
 
216
- def parsed_whatson
217
- @parsed_whatson ||= Nokogiri::HTML(whatson_response)
207
+ def information_doc
208
+ @information_doc ||= begin
209
+ Nokogiri::HTML(CineworldUk::Internal::Website.new.information(@id))
210
+ end
218
211
  end
219
212
 
220
213
  def remaining_address
221
- final_address_array.delete_if { |e| e == street_address || e == locality || e == region }
222
- end
223
-
224
- def whatson_response
225
- @whatson_response ||= HTTParty.get("http://www.cineworld.co.uk/whatson?cinema=#{@id}")
214
+ adr_array.delete_if do |e|
215
+ e == street_address || e == locality || e == region
216
+ end
226
217
  end
227
218
  end
228
219
  end
@@ -1,5 +1,4 @@
1
1
  module CineworldUk
2
-
3
2
  # The object representing a film on the Cineworld UK website
4
3
  class Film
5
4
  include Comparable
@@ -13,14 +12,23 @@ module CineworldUk
13
12
  # @return [CineworldUk::Film]
14
13
  def initialize(name)
15
14
  @name = name
16
- @slug = name.downcase.gsub(/[^0-9a-z ]/,'').gsub(/\s+/, '-')
15
+ @slug = name.downcase.gsub(/[^0-9a-z ]/, '').gsub(/\s+/, '-')
16
+ end
17
+
18
+ # All currently listed films showing at a cinema
19
+ # @param [Integer] cinema_id id of the cinema on the website
20
+ # @return [Array<CineworldUk::Film>]
21
+ def self.at(cinema_id)
22
+ whatson_parser(cinema_id).films_with_screenings.map do |html|
23
+ new(screenings_parser(html).film_name)
24
+ end
17
25
  end
18
26
 
19
27
  # Allows sort on objects
20
28
  # @param [CineworldUk::Film] other another film object
21
29
  # @return [Integer] -1, 0 or 1
22
- def <=> other
23
- self.slug <=> other.slug
30
+ def <=>(other)
31
+ slug <=> other.slug
24
32
  end
25
33
 
26
34
  # Check an object is the same as another object.
@@ -28,20 +36,30 @@ module CineworldUk
28
36
  # @return [Boolean] True if both objects are the same exact object, or if
29
37
  # they are of the same type and share an equal slug
30
38
  # @note Guided by http://woss.name/2011/01/20/equality-comparison-and-ordering-in-ruby/
31
- def eql? other
39
+ def eql?(other)
32
40
  self.class == other.class && self == other
33
41
  end
34
42
 
35
43
  # Generates hash of slug in order to allow two records of the same type and
36
44
  # id to work with something like:
37
45
  #
38
- # [ Film.new('ABC'), Film.new('DEF') ] & [ Film.new('DEF'), Film.new('GHI') ]
46
+ # [Film.new('ABC'), Film.new('DEF')] & [Film.new('DEF'), Film.new('GHI')]
39
47
  # #=> [ Film.new('DEF') ]
40
48
  #
41
49
  # @return [Integer] hash of slug
42
50
  # @note Guided by http://woss.name/2011/01/20/equality-comparison-and-ordering-in-ruby/
43
51
  def hash
44
- self.slug.hash
52
+ slug.hash
53
+ end
54
+
55
+ private
56
+
57
+ def self.screenings_parser(html)
58
+ CineworldUk::Internal::FilmWithScreeningsParser.new(html)
59
+ end
60
+
61
+ def self.whatson_parser(id)
62
+ CineworldUk::Internal::WhatsonParser.new(id)
45
63
  end
46
64
  end
47
65
  end
@@ -1,102 +1,60 @@
1
1
  module CineworldUk
2
-
3
2
  # Internal utility classes: Do not use
4
3
  # @api private
5
4
  module Internal
6
-
7
5
  # Parses a chunk of HTML to derive movie showing data
8
6
  class FilmWithScreeningsParser
7
+ # css selector for film name
8
+ FILM_NAME_CSS = 'h3.h1 a[href*=whatson]'
9
+ # css selector for performances
10
+ PERFORMANCES_CSS = '.schedule .performances > li'
9
11
 
10
12
  # @param [String] film_html a chunk of html
11
13
  def initialize(film_html)
12
- @nokogiri_html = Nokogiri::HTML(film_html)
14
+ @film_html = film_html.to_s
15
+ end
16
+
17
+ # The cinema id
18
+ # @return [String]
19
+ def cinema_id
20
+ name_doc.to_s.match(/cinema=(\d+)/)[1].to_i
13
21
  end
14
22
 
15
23
  # The film name
16
24
  # @return [String]
17
25
  def film_name
18
- NameParser.new(original_name).standardize
26
+ name_doc.children[0].to_s
19
27
  end
20
28
 
21
- # Showings
22
- # @return [Hash]
23
- # @example
24
- # {
25
- # "2D" => [Time.utc, Time.utc]
26
- # }
27
- def showings
28
- tz = TZInfo::Timezone.get('Europe/London')
29
- @nokogiri_html.css('.schedule .performances > li').inject({}) do |result, li|
30
- key = performance_variant(li)
31
-
32
- if has_bookable_link_node?(li)
33
- time_array = performance_date_array(li) + performance_time_array(li)
34
- time = tz.local_to_utc(Time.utc(*time_array))
35
- result.merge(key => (result[key] || []) << [time, booking_url(li)])
36
- else
37
- result
38
- end
39
- end
29
+ # attributes of all the screenings
30
+ # @return [Array<Hash>]
31
+ def to_a
32
+ performances_doc.map do |node|
33
+ next unless screening_parser_hash(node)
34
+ screening_parser_hash(node).merge(film_hash)
35
+ end.compact
40
36
  end
41
37
 
42
38
  private
43
39
 
44
- def booking_url(node)
45
- 'http://www.cineworld.co.uk' + performance_link(node)['href']
46
- end
47
-
48
- def dbox?(node)
49
- node.css('.tooltip-box .icon-service-dbox').count > 0
50
- end
51
-
52
- def dimension(node)
53
- node.css('.tooltip-box .icon-service-twod, .tooltip-box .icon-service-thrd').text
54
- end
55
-
56
- def has_bookable_link_node?(node)
57
- performance_link(node) != nil
58
- end
59
-
60
- def imax?(node)
61
- node.css('.tooltip-box .icon-service-imax').count > 0
62
- end
63
-
64
- def hfr?(node)
65
- node.css('.tooltip-box .icon-service-hfr').count > 0
66
- end
67
-
68
- def original_name
69
- @original_name ||= @nokogiri_html.css('.span5 h1 a,.span7 h1 a, .span7 h1').children[0].to_s
70
- end
71
-
72
- def performance_date_array(node)
73
- if has_bookable_link_node?(node)
74
- match = performance_link_text(node).match(/date\=(\d{4})(\d{2})(\d{2})/)
75
- [match[1], match[2], match[3]]
76
- end
77
- end
78
-
79
- def performance_link(node)
80
- node.css('a.performance').first
40
+ def doc
41
+ @doc ||= Nokogiri::HTML(@film_html)
81
42
  end
82
43
 
83
- def performance_link_string(node)
84
- performance_link(node).to_s
44
+ def film_hash
45
+ @film_hash ||= { cinema_id: cinema_id, film_name: film_name }
85
46
  end
86
47
 
87
- def performance_link_text(node)
88
- has_bookable_link_node?(node) ? performance_link_string(node) : nil
48
+ def name_doc
49
+ @name_doc ||= doc.css(FILM_NAME_CSS)
89
50
  end
90
51
 
91
- def performance_time_array(node)
92
- if has_bookable_link_node?(node)
93
- match = performance_link_text(node).match(/time\=(\d{2})\:(\d{2})/)
94
- [match[1], match[2]]
95
- end
52
+ def performances_doc
53
+ @performances_doc ||= doc.css(PERFORMANCES_CSS)
96
54
  end
97
55
 
98
- def performance_variant(node)
99
- dimension(node) + "#{ ' D-BOX' if dbox?(node) }#{ ' IMAX' if imax?(node) }#{ ' HFR' if hfr?(node) }"
56
+ def screening_parser_hash(node)
57
+ ScreeningParser.new(node).to_hash
100
58
  end
101
59
  end
102
60
  end
@@ -1,14 +1,13 @@
1
1
  module CineworldUk
2
-
3
2
  # Internal utility classes: Do not use
4
3
  # @api private
5
4
  module Internal
6
-
7
5
  # Parses a string to derive a standardized movie title
8
6
  class NameParser
9
-
7
+ # @return [String] the original name
10
8
  attr_reader :original_name
11
9
 
10
+ # @param [String] name original film name
12
11
  def initialize(name)
13
12
  @original_name = name
14
13
  @name = name
@@ -17,15 +16,15 @@ module CineworldUk
17
16
  # Process the name and return the final string
18
17
  # @return [String]
19
18
  def standardize
20
- strip_and_squeeze.
21
- ampersands_into_text.
22
- into_ampersand_if_second_to_last.
23
- remove_indian_languages.
24
- remove_screening_details.
25
- replace_non_film_prefix.
26
- remove_newlines.
27
- remove_dates.
28
- title_case
19
+ strip_and_squeeze
20
+ .ampersands_into_text
21
+ .into_ampersand_if_second_to_last
22
+ .remove_indian_languages
23
+ .remove_screening_details
24
+ .replace_non_film_prefix
25
+ .remove_newlines
26
+ .remove_dates
27
+ .title_case
29
28
  to_s
30
29
  end
31
30
 
@@ -48,9 +47,9 @@ module CineworldUk
48
47
  end
49
48
 
50
49
  def remove_indian_languages
51
- languages = ['Malayalam', 'Tamil']
50
+ languages = %w(Malayalam Tamil)
52
51
 
53
- _remove(/\((#{languages*'|'})\)/i)
52
+ _remove(/\((#{languages * '|'})\)/i)
54
53
  self
55
54
  end
56
55
 
@@ -61,7 +60,7 @@ module CineworldUk
61
60
  end
62
61
 
63
62
  def remove_dates
64
- _remove(/\-? \d{1,2}\/\d{1,2}\/\d{2,4}/)
63
+ _remove(%r(-? \d{1,2}/\d{1,2}/\d{2,4}))
65
64
  self
66
65
  end
67
66
 
@@ -73,15 +72,18 @@ module CineworldUk
73
72
  def replace_non_film_prefix
74
73
  _replace 'Bolshoi Ballet Live -', 'Bolshoi:'
75
74
 
76
- @name = 'National Theatre: ' + @name.gsub(/\- NT .+ encore/, '') if @name.match /\- NT .+ encore/
75
+ if @name.match(/\- NT .+ encore/)
76
+ @name = 'National Theatre: ' + @name.gsub(/\- NT .+ encore/, '')
77
+ end
78
+
77
79
  _replace 'NT Live:', 'National Theatre:'
78
80
 
79
81
  _replace 'MET Opera -', 'Met Opera:'
80
82
  _replace 'Royal Ballet Live:', 'Royal Ballet:'
81
83
 
82
84
  # fill out Royal Opera House
83
- if pure_name_match = @name.match(/Royal Opera Live\: (.+) \-.+/)
84
- @name = 'Royal Opera House: ' + pure_name_match[1]
85
+ @name.match(/Royal Opera Live\: (.+) \-.+/) do |match|
86
+ @name = 'Royal Opera House: ' + match[1]
85
87
  end
86
88
  _replace 'Royal Opera Live:', 'Royal Opera House:'
87
89