2c09795808b83ac8b8ea34543b4cb9762a034ff0
1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Window to list beers and other beer-related views
20 # View about a beer, with its name, description and rating
25 autoinit beer_info
, parent
28 var beer_info
: BeerAndRatings
30 # Buttons to realize the rating buttons
31 var star_buttons
= new Array[StarButton]
33 # Layout of the first line with the name and `star_buttons`
34 var top_line_layout
= new HorizontalLayout(parent
=self)
38 var lbl_name
= new Label(parent
=top_line_layout
, text
=beer_info
.beer
.name
)
41 var desc
= beer_info
.beer
.desc
42 if beer_info
.is_new
then desc
+= " (New)".t
43 var lbl_desc
= new Label(parent
=self, text
=desc
)
45 var lbl_stats
= new Label(parent
=self, text
=beer_info
.rating_text
)
48 var badges
= beer_info
.badges
49 if badges
!= null then
50 var lbl_comment
= new Label(parent
=self, text
=badges
.join
(" "))
51 lbl_comment
.size
= 0.5
54 var rating
= beer_info
.user_rating
or else 0
58 # Prepare and display the rating controls
59 fun setup_stars
(rating
: Int)
61 var l_stars
= new HorizontalLayout(parent
=top_line_layout
)
64 var but
= new StarButton(beer_info
.beer
, i
, i
<= rating
, parent
=l_stars
)
66 but
.observers
.add
self
71 redef fun on_event
(event
)
73 assert event
isa ButtonPressEvent
75 var sender
= event
.sender
76 if sender
isa StarButton then
77 on_review sender
.rating
82 fun on_review
(rating
: Int)
84 var beer_id
= beer_info
.beer
.id
85 (new ReviewAction(app
.window
, "rest/review?token={app.token}&beer={beer_id}&rating={rating}")).start
89 for but
in star_buttons
do
96 # Beers pane listing the available beers
100 private var layout
= new VerticalLayout(parent
=self)
101 private var list_beers
= new ListLayout(parent
=layout
)
105 if debug
then print
"BenitluxWindow::init"
110 # Send HTTP request to list beers
111 fun action_list_beers
112 do (new ListBeersAction(self, "rest/list?token={app.token}")).start
118 # View to describe and rate a eer
122 autoinit beer
, init_rating
, parent
, enabled
127 # Previous rating, 0 for none
130 redef fun parent
=(layout
) do end
132 redef fun enabled
=(value
) do end
135 # Button with a star, filled or not, for rating beers
139 autoinit beer
, rating
, on
, parent
, enabled
141 # Info on the beer to rate
147 # Set if the star is filled
148 fun on
=(on
: Bool) is autoinit
do text
= if on
then "★" else "☆"
151 redef class BeerAndRatings
152 # Text version of the ratings
153 fun rating_text
: String
155 var txt
= new Array[String]
158 if global
!= null and global
.count
> 0 then
159 txt
.add
"%0★ %1 reviews".t
.format
(global
.average
.to_precision
(1), global
.count
)
160 else txt
.add
"No reviews yet".t
163 if local
!= null and local
.count
> 0 then
164 txt
.add
", friends: %0☆ %1 reviews".t
.format
(local
.average
.to_precision
(1), local
.count
)
172 # Capitalize first letter for a prettier display
176 if desc
.length
== 0 then return desc
178 var first_letter
= desc
.first
.to_upper
179 return first_letter
.to_s
+ desc
.substring_from
(1)
183 # Comparator of beers
187 redef type COMPARED: BeerAndRatings
189 redef fun compare
(a
, b
) do return value_of
(a
) <=> value_of
(b
)
191 private fun value_of
(beer
: COMPARED): Float
196 var rating
= beer
.user_rating
197 if rating
!= null then
199 value
+= rating
.to_f
* 4.0
202 var followed
= beer
.followed
203 if followed
!= null then
205 value
+= followed
.average
* 2.0
208 var global
= beer
.global
209 if global
!= null then
211 value
+= global
.average
214 return (max
- value
)/max
218 # Async request to submit a review
220 super WindowHttpRequest
222 redef fun on_load
(res
, status
)
224 if intercept_error
(res
) then return
228 # Async request to update the beer list
229 class ListBeersAction
230 super WindowHttpRequest
232 redef type W
: BeersWindow
234 redef fun on_load
(beers
, status
)
236 window
.layout
.remove window
.list_beers
237 window
.list_beers
= new ListLayout(parent
=window
.layout
)
239 if intercept_error
(beers
) then return
241 if not beers
isa Array[BeerAndRatings] then
242 app
.feedback
"Communication Error".t
246 # Sort beers per preference
247 var comparator
= new BeerComparator
248 comparator
.sort beers
251 for beer_and_rating
in beers
do
252 var view
= new BeerView(beer_and_rating
, parent
=window
.list_beers
)
257 redef class BestBeerBadge
258 redef fun to_s
do return "Favorite beer on the menu.".t
261 redef class FavoriteBeerBadge
262 redef fun to_s
do return "Favorite of %0.".t
.format
(users
.join
(", ", " & "))
265 redef class SimilarBeerBadge
266 redef fun to_s
do return "Similar to %0.".t
.format
(beers
.join
(", ", " & "))
270 # Pretty compressed list of this list of beer as a pseudo diff
272 # Require: `self isa Array[BeerAndRatings]`
273 fun beers_to_notification
: String
275 assert self isa Array[BeerAndRatings]
277 # Sort beers per preference
278 var comparator
= new BeerComparator
281 # Organize the notification line per line
282 # First the new beers, then the fixed one.
283 var lines
= new Array[String]
284 var fix_beers
= new Array[String]
288 lines
.add
"+ {beer.name}: {beer.desc}"
289 else fix_beers
.add beer
.name
292 # Show a few fixed beers per line
293 if fix_beers
.not_empty
then
294 var line
= new FlatBuffer
296 for i
in fix_beers
.length
.times
, beer
in fix_beers
do
298 if i
> 0 then line
.append
", "
300 var l
= line
.length
+ beer
.length
301 if l
< 42 then # Very approximate width of a notification on Android
308 line
= new FlatBuffer
316 return lines
.join
("\n")
319 # Does `self` has a new beer?
321 # Require: `self isa Array[BeerAndRatings]`
322 fun has_new_beers
: Bool
324 assert self isa Array[BeerAndRatings]
326 for beer
in self do if beer
.is_new
then return true