contrib/benitlux: intro the admin server interface with daily notification
[nit.git] / contrib / benitlux / src / benitlux_model.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Database and data model to be used by servers and clients
18 module benitlux_model
19
20 import serialization
21 import md5
22
23 # A beer, with a name and description
24 class Beer
25 auto_serializable
26
27 # Database id
28 var id: Int
29
30 # Name of the beer
31 var name: String
32
33 # Description on the Web site
34 var desc: String
35
36 redef fun to_s do return "<{name}: {desc}>"
37 end
38
39 # A collection of beer-related events
40 class BeerEvents
41 auto_serializable
42
43 # New beers on the menu
44 var new_beers = new Array[Beer]
45
46 # Beers that have left the menu
47 var gone_beers = new Array[Beer]
48
49 # Beers that are on the menu today, and yesterday
50 var fix_beers = new Array[Beer]
51
52 # Get a human pretty `Array[String]` version of `self`
53 fun to_email_content: Array[String]
54 do
55 var content = new Array[String]
56
57 # New beers
58 for beer in self.new_beers do
59 content.add "+ {beer.name}: {beer.desc}"
60 end
61
62 # Gone beers
63 for beer in self.gone_beers do
64 content.add "- {beer.name}: {beer.desc}"
65 end
66
67 # Fix beers
68 for beer in self.fix_beers do
69 content.add " {beer.name}: {beer.desc}"
70 end
71
72 return content
73 end
74
75 # Get a pretty and short version of `self`
76 fun to_email_title: String
77 do
78 # New beers
79 var new_beers_name = new Array[String]
80 for beer in self.new_beers do new_beers_name.add beer.name
81
82 if not new_beers_name.is_empty then
83 return " (+ {new_beers_name.join(", ")})"
84 end
85
86 return ""
87 end
88 end
89
90 # Basic user public information
91 class User
92 serialize
93
94 # ID of this user in the DB
95 var id: Int
96
97 # Visible user name
98 var name: String
99
100 redef fun to_s do return "<{class_name} {id} '{name}'>"
101 end
102
103 # User public information in reference to a user (medium details level)
104 class UserAndFollowing
105 serialize
106
107 # Basic user information
108 var user: User
109
110 # Favorite beers as a string
111 var favs: String
112
113 # Is the reference user following `user`?
114 var following: Bool
115
116 # Is the reference user followed by `user`?
117 var followed: Bool
118
119 # Time of the last check in, if `followed`
120 var last_check_in: nullable String = null
121 end
122
123 # Review by `author` on a `beer`
124 class Review
125 serialize
126
127 # Basic author information
128 var author: User
129
130 # Basic beer information
131 var beer: Beer
132
133 # Rating out of 5
134 var rating: Int
135
136 # Text content of this review, may be empty
137 var text: String
138 end
139
140 # Statistics of the reviews on `beer`
141 class BeerStats
142 serialize
143
144 # Basic beer information
145 var beer: Beer
146
147 # Average rating out of 5
148 var average: Float
149
150 # Number of reviews used for these statistics
151 var count: Int
152 end
153
154 # Beer information in reference to a user (medium detail level)
155 class BeerAndRatings
156 serialize
157
158 # Basic beer information
159 var beer: Beer
160
161 # Global statistics on `beer`
162 var global: nullable BeerStats
163
164 # Statistics on `beer` among followed users only
165 var followed: nullable BeerStats
166
167 # Rating left by the referenced user, if any
168 var user_rating: nullable Int
169
170 # Do we predict this `beer` to go quickly?
171 var will_go_fast: Bool
172
173 # Data of appearance of this batch TODO
174 var batch: String
175
176 # Is this beer new since the last work day?
177 var is_new: Bool
178
179 # Has this beer been here since the last work day?
180 var is_fix: Bool
181
182 # Has this beer left the menu since the last work day?
183 var is_gone: Bool
184
185 # Noteworthy comments on this beer, often relative to a user
186 var badges: nullable Array[BeerBadge] = null is writable
187 end
188
189 # Noteworthy comment on a beer
190 abstract class BeerBadge
191 serialize
192 end
193
194 # A beer is the favorite of `users`
195 class FavoriteBeerBadge
196 super BeerBadge
197 serialize
198
199 # Name of the user fan of the beer
200 var users = new Array[String]
201 end
202
203 # A beer is similar to `beers`
204 class SimilarBeerBadge
205 super BeerBadge
206 serialize
207
208 # Names of the similar beers
209 var beers = new Array[String]
210 end
211
212 # This beer is the best on the menu
213 class BestBeerBadge
214 super BeerBadge
215 serialize
216 end
217
218 # Result of a login or signup request upon success
219 class LoginResult
220 serialize
221
222 # Basic user information
223 var user: User
224
225 # Reference token
226 var token: String
227 end
228
229 # Report pushed to followed_followers when a user checks in or out
230 class CheckinReport
231 serialize
232
233 # Users currently in
234 var users = new Array[User]
235 end
236
237 # Daily menu notifications
238 class DailyNotification
239 serialize
240
241 # All beers on the menu today
242 var beers: Array[BeerAndRatings]
243 end
244
245 # Server or API usage error
246 class BenitluxError
247 super Error
248 serialize
249
250 # Error message that can be shown to the user
251 var user_message: nullable String
252 end
253
254 # Client sent an invalid token
255 class BenitluxTokenError
256 super BenitluxError
257 serialize
258 end
259
260 redef class Text
261 # Is `self` a valid user name?
262 fun name_is_ok: Bool
263 do
264 if length < 4 or length > 16 then return false
265
266 for c in chars do
267 if c.is_whitespace or c.code_point == 0xFFFD then return false
268 end
269
270 return true
271 end
272
273 # Is `self` a valid password?
274 fun pass_is_ok: Bool do return length >= 6
275
276 # Hashed Benitlux password
277 fun pass_hash: String do return (to_s+benitlux_salt).md5
278 end
279
280 # Salt used on passwords
281 #
282 # Should be refined by user modules.
283 fun benitlux_salt: String do return "Vive le ben!"