1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.quiz.web;
35
36 import fr.paris.lutece.plugins.quiz.business.QuestionGroup;
37 import fr.paris.lutece.plugins.quiz.business.QuestionGroupHome;
38 import fr.paris.lutece.plugins.quiz.business.Quiz;
39 import fr.paris.lutece.plugins.quiz.business.images.QuizImage;
40 import fr.paris.lutece.plugins.quiz.business.images.QuizImageHome;
41 import fr.paris.lutece.plugins.quiz.service.QuizService;
42 import fr.paris.lutece.portal.service.i18n.I18nService;
43 import fr.paris.lutece.portal.service.message.SiteMessageException;
44 import fr.paris.lutece.portal.service.plugin.Plugin;
45 import fr.paris.lutece.portal.service.plugin.PluginService;
46 import fr.paris.lutece.portal.service.spring.SpringContextService;
47 import fr.paris.lutece.portal.service.template.AppTemplateService;
48 import fr.paris.lutece.portal.service.util.AppLogService;
49 import fr.paris.lutece.portal.web.xpages.XPage;
50 import fr.paris.lutece.portal.web.xpages.XPageApplication;
51 import fr.paris.lutece.util.html.HtmlTemplate;
52
53 import java.io.IOException;
54 import java.io.OutputStream;
55 import java.text.MessageFormat;
56 import java.util.HashMap;
57 import java.util.Locale;
58 import java.util.Map;
59
60 import javax.servlet.http.HttpServletRequest;
61 import javax.servlet.http.HttpServletResponse;
62 import javax.servlet.http.HttpSession;
63
64 import org.apache.commons.lang.StringUtils;
65
66
67
68
69
70 public class QuizApp implements XPageApplication
71 {
72 private static final String TEMPLATE_QUIZ_LIST = "skin/plugins/quiz/quiz_list.html";
73 private static final String TEMPLATE_QUIZ_RESULTS = "skin/plugins/quiz/quiz_results.html";
74 private static final String TEMPLATE_QUIZ_RESULTS_STEP = "skin/plugins/quiz/quiz_results_step.html";
75 private static final String TEMPLATE_QUIZ_ERROR = "skin/plugins/quiz/quiz_error.html";
76 private static final String TEMPLATE_QUESTIONS_LIST = "skin/plugins/quiz/quiz.html";
77 private static final String TEMPLATE_QUESTIONS_LIST_STEP = "skin/plugins/quiz/quiz_step.html";
78
79 private static final String PROPERTY_QUIZ_LIST_PAGE_PATH = "quiz.xpage.pageQuizListPath";
80 private static final String PROPERTY_QUIZ_LIST_PAGE_TITLE = "quiz.xpage.pageQuizListTitle";
81 private static final String PROPERTY_QUIZ_PAGE_PATH = "quiz.xpage.pageQuizPath";
82 private static final String PROPERTY_QUIZ_PAGE_TITLE = "quiz.xpage.pageQuizTitle";
83 private static final String PROPERTY_QUIZ_RESULTS_PAGE_PATH = "quiz.xpage.pageQuizResultsPath";
84 private static final String PROPERTY_QUIZ_RESULTS_PAGE_TITLE = "quiz.xpage.pageQuizResultsTitle";
85 private static final String PROPERTY_QUIZ_ERROR_PAGE_PATH = "quiz.xpage.pageQuizErrorPath";
86 private static final String PROPERTY_QUIZ_ERROR_PAGE_TITLE = "quiz.xpage.pageQuizErrorTitle";
87 private static final String PROPERTY_MSG_MANY_GOOD_ANSWERS = "quiz.message.results.manyGoodAnswers";
88 private static final String PROPERTY_MSG_ONE_GOOD_ANSWER = "quiz.message.results.oneGoodAnswer";
89 private static final String PROPERTY_MSG_NO_GOOD_ANSWER = "quiz.message.results.noGoodAnswer";
90
91 private static final String PARAMETER_RESULTS = "results";
92 private static final String PARAMETER_ID_QUIZ = "quiz_id";
93 private static final String PARAMETER_OLD_STEP = "old_step";
94 private static final String PARAMETER_ID_IMAGE = "id_image";
95 private static final String ACTION_NEXT_STEP = "nextStep";
96 private static final String ACTION_BACK_FROM_ERROR = "backFromError";
97
98 private static final String SESSION_KEY_QUIZ_STEP = "quiz.savedQuizResult";
99
100 private static final String MARK_ERROR = "error";
101 private static final String MARK_ID_QUIZ = "quiz_id";
102 private static final String MARK_HAS_NEXT_STEP = "hasNextStep";
103 private static final String MARK_SCORE = "score";
104 private static final String MARK_QUESTIONS_COUNT = "questions_count";
105 private static final String MARK_SCORE_MESSAGE = "score_message";
106 private static final String MARK_GROUP = "group";
107 private static final String MARK_IS_LAST_GROUP = "is_last_group";
108
109 private QuizService _quizService = SpringContextService.getBean( QuizService.BEAN_QUIZ_SERVICE );
110
111
112
113
114
115
116 public static void doDownloadQuizImage( HttpServletRequest request, HttpServletResponse response )
117 {
118 String strIdImage = request.getParameter( PARAMETER_ID_IMAGE );
119 if ( StringUtils.isNotEmpty( strIdImage ) && StringUtils.isNumeric( strIdImage ) )
120 {
121 OutputStream out = null;
122 try
123 {
124 Plugin plugin = PluginService.getPlugin( QuizService.PLUGIN_NAME );
125 int nIdImage = Integer.parseInt( strIdImage );
126 byte[] bArrayResult = {};
127 String strContentType = StringUtils.EMPTY;
128 QuizImage quizImage = QuizImageHome.getImage( nIdImage, plugin );
129
130 if ( quizImage != null && quizImage.getContent( ) != null )
131 {
132 bArrayResult = quizImage.getContent( );
133 strContentType = quizImage.getContentType( );
134 }
135
136 response.setHeader( "Cache-Control", "no-cache" );
137 response.setDateHeader( "Expires", 0 );
138 response.setContentLength( bArrayResult.length );
139 response.setContentType( strContentType );
140
141
142 out = response.getOutputStream( );
143 out.write( bArrayResult );
144 }
145 catch ( IOException e )
146 {
147 AppLogService.error( e.getMessage( ), e );
148 }
149 finally
150 {
151 if ( out != null )
152 {
153 try
154 {
155 out.flush( );
156 out.close( );
157 }
158 catch ( IOException e )
159 {
160 AppLogService.error( e.getMessage( ), e );
161 }
162 }
163 }
164 }
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178 @SuppressWarnings( "unchecked" )
179 public XPage getPage( HttpServletRequest request, int nMode, Plugin plugin ) throws SiteMessageException
180 {
181 String strIdQuiz = request.getParameter( PARAMETER_ID_QUIZ );
182 String strAction = request.getParameter( QuizService.PARAMETER_ACTION );
183 XPage page = null;
184
185 if ( StringUtils.isNotEmpty( strIdQuiz ) && StringUtils.isNumeric( strIdQuiz ) )
186 {
187 int nIdQuiz = Integer.parseInt( strIdQuiz );
188
189 Quiz quiz = _quizService.findQuizById( nIdQuiz );
190 if ( !quiz.isEnabled( ) )
191 {
192 return getQuizList( request.getLocale( ) );
193 }
194
195 if ( quiz.getDisplayStepByStep( ) )
196 {
197
198 String strOldStep = request.getParameter( PARAMETER_OLD_STEP );
199 int nOldStepId;
200 if ( StringUtils.isNotEmpty( strOldStep ) && StringUtils.isNumeric( strOldStep ) )
201 {
202 nOldStepId = Integer.parseInt( strOldStep );
203 }
204 else
205 {
206 request.getSession( ).setAttribute( MARK_SCORE, 0 );
207 request.getSession( ).setAttribute( MARK_QUESTIONS_COUNT, 0 );
208
209 nOldStepId = 0;
210 }
211
212 if ( !StringUtils.equals( ACTION_BACK_FROM_ERROR, strAction ) )
213 {
214 if ( nOldStepId > 0 )
215 {
216
217 Map<String, String[]> mapResponsesCurrentStep = null;
218 if ( !StringUtils.equals( ACTION_NEXT_STEP, strAction ) )
219 {
220 mapResponsesCurrentStep = saveAndValidateQuizAnswers( quiz, nOldStepId,
221 request.getParameterMap( ), request.getLocale( ), plugin, request.getSession( true ) );
222
223 String[] strError = mapResponsesCurrentStep.get( QuizService.KEY_ERROR );
224
225 if ( strError != null && strError.length > 0 )
226 {
227 return getErrorPage( quiz.getIdQuiz( ), strError[0], nOldStepId, request.getLocale( ) );
228 }
229 }
230
231
232 if ( quiz.getDisplayResultAfterEachStep( ) && StringUtils.equals( strAction, PARAMETER_RESULTS ) )
233 {
234 page = getQuizStepResults( quiz, nOldStepId, request.getLocale( ), mapResponsesCurrentStep,
235 request.getSession( ), plugin );
236 }
237 }
238 else
239 {
240
241 resetUserAnswers( request.getSession( ) );
242 }
243 }
244
245 if ( page == null )
246 {
247
248 page = getQuizNextStep( quiz, nOldStepId, request );
249 if ( page == null )
250 {
251 page = getQuizResults( quiz, request.getLocale( ), getUserAnswers( request.getSession( ) ),
252 plugin );
253 }
254 }
255 }
256 else
257 {
258 if ( strAction != null && strAction.equals( PARAMETER_RESULTS ) )
259 {
260 page = getQuizResults( quiz, request.getLocale( ), request.getParameterMap( ), plugin );
261 }
262 else
263 {
264 page = getQuizPage( nIdQuiz, request.getLocale( ) );
265 }
266 }
267 }
268 else
269 {
270 page = getQuizList( request.getLocale( ) );
271 }
272
273 return page;
274 }
275
276
277
278
279
280
281 protected XPage getQuizList( Locale locale )
282 {
283 XPage page = new XPage( );
284 Map<String, Object> model = _quizService.getQuizList( );
285 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_QUIZ_LIST, locale, model );
286 page.setContent( template.getHtml( ) );
287 page.setTitle( I18nService.getLocalizedString( PROPERTY_QUIZ_LIST_PAGE_TITLE, locale ) );
288 page.setPathLabel( I18nService.getLocalizedString( PROPERTY_QUIZ_LIST_PAGE_PATH, locale ) );
289
290 return page;
291 }
292
293
294
295
296
297
298
299 protected XPage getQuizPage( int nQuizId, Locale locale )
300 {
301 XPage page = new XPage( );
302 Map<String, Object> model = _quizService.getQuiz( nQuizId );
303 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_QUESTIONS_LIST, locale, model );
304 page.setContent( template.getHtml( ) );
305
306 setQuizProperties( (Quiz) model.get( QuizService.KEY_QUIZ ), page, model, locale );
307
308 return page;
309 }
310
311
312
313
314
315
316
317
318
319 protected XPage getQuizNextStep( Quiz quiz, int nOldStepId, HttpServletRequest request )
320 {
321 XPage page = new XPage( );
322 Map<String, Object> model = _quizService.getQuizNextStep( quiz, nOldStepId );
323
324 if ( model == null )
325 {
326 return null;
327 }
328
329 Quiz quizModel = (Quiz) ( _quizService.getQuiz( quiz.getIdQuiz( ) ).get( QuizService.KEY_QUIZ ) );
330
331 QuestionGroup group = (QuestionGroup) model.get( MARK_GROUP );
332
333 boolean bDisplayScore = group.getDisplayScore( );
334 Plugin plugin = PluginService.getPlugin( QuizService.PLUGIN_NAME );
335 int nTotalQuestion = (Integer) request.getSession( ).getAttribute( MARK_QUESTIONS_COUNT );
336 int nIdLastQuizGroup = QuestionGroupHome.findLastByQuiz( quiz.getIdQuiz( ), plugin );
337 if ( !bDisplayScore )
338 {
339
340 if ( !QuestionGroupHome.hasGroupDisplayScore( group.getIdQuiz( ), plugin ) )
341 {
342 int nSizeQuiz = quizModel.getQuestions( ).size( );
343 bDisplayScore = nTotalQuestion == nSizeQuiz && nIdLastQuizGroup == group.getIdGroup( );
344 }
345 }
346
347 if ( bDisplayScore )
348 {
349
350 int nScore = (Integer) request.getSession( ).getAttribute( MARK_SCORE );
351
352 String strMessage = I18nService.getLocalizedString( PROPERTY_MSG_MANY_GOOD_ANSWERS, request.getLocale( ) );
353
354 switch ( nScore )
355 {
356 case 0:
357 strMessage = I18nService.getLocalizedString( PROPERTY_MSG_NO_GOOD_ANSWER, request.getLocale( ) );
358
359 break;
360
361 case 1:
362 strMessage = I18nService.getLocalizedString( PROPERTY_MSG_ONE_GOOD_ANSWER, request.getLocale( ) );
363
364 break;
365
366 default:
367 break;
368 }
369
370 Object[] args = { nScore, nTotalQuestion };
371 String strScoreMessage = MessageFormat.format( strMessage, args );
372 model.put( MARK_SCORE_MESSAGE, strScoreMessage );
373 _quizService.processEndOfQuiz( quiz, "" + nScore, getUserAnswers( request.getSession( ) ) );
374 resetUserAnswers( request.getSession( ) );
375 }
376
377 model.put( MARK_IS_LAST_GROUP, nIdLastQuizGroup == group.getIdGroup( ) );
378
379 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_QUESTIONS_LIST_STEP, request.getLocale( ),
380 model );
381 page.setContent( template.getHtml( ) );
382
383 setQuizProperties( quiz, page, model, request.getLocale( ) );
384
385 return page;
386 }
387
388
389
390
391
392
393
394
395
396 protected XPage getQuizResults( Quiz quiz, Locale locale, Map<String, String[]> mapParameters, Plugin plugin )
397 {
398 XPage page = new XPage( );
399
400 Map<String, Object> model;
401
402 if ( "PROFIL".equals( quiz.getTypeQuiz( ) ) )
403 {
404 model = _quizService.calculateQuizProfile( quiz.getIdQuiz( ), mapParameters, locale );
405 }
406 else
407 {
408 model = _quizService.getResults( quiz.getIdQuiz( ), mapParameters, locale );
409 }
410
411 String strError = (String) model.get( QuizService.KEY_ERROR );
412
413 if ( strError != null )
414 {
415 return getErrorPage( quiz.getIdQuiz( ), strError, 0, locale );
416 }
417
418 _quizService.processEndOfQuiz( quiz, "" + model.get( MARK_SCORE ), mapParameters );
419
420 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_QUIZ_RESULTS, locale, model );
421
422 page.setContent( template.getHtml( ) );
423
424 setQuizResultProperties( quiz, page, model, locale );
425
426 return page;
427 }
428
429
430
431
432
433
434
435
436
437
438
439 protected XPage getQuizStepResults( Quiz quiz, int nIdStep, Locale locale,
440 Map<String, String[]> mapResponsesCurrentStep, HttpSession session, Plugin plugin )
441 {
442 XPage page = new XPage( );
443
444 Map<String, Object> model;
445 if ( "PROFIL".equals( quiz.getTypeQuiz( ) ) )
446 {
447 model = _quizService.calculateQuizStepProfile( quiz, nIdStep, mapResponsesCurrentStep, locale, plugin );
448 }
449 else
450 {
451 model = _quizService.getStepResults( quiz, nIdStep, mapResponsesCurrentStep, locale, plugin );
452
453 if ( model != null )
454 {
455 int nNewScore = (Integer) model.get( MARK_SCORE );
456 int nOldScore = (Integer) session.getAttribute( MARK_SCORE );
457 int nScore = nNewScore + nOldScore;
458
459 int nTotalNewQuestion = (Integer) model.get( MARK_QUESTIONS_COUNT );
460 int nTotalOldQuestion = (Integer) session.getAttribute( MARK_QUESTIONS_COUNT );
461 int nTotalQuestion = nTotalNewQuestion + nTotalOldQuestion;
462
463 session.setAttribute( MARK_SCORE, nScore );
464 session.setAttribute( MARK_QUESTIONS_COUNT, nTotalQuestion );
465
466 String strMessage = I18nService.getLocalizedString( PROPERTY_MSG_MANY_GOOD_ANSWERS, locale );
467
468 switch ( nScore )
469 {
470 case 0:
471 strMessage = I18nService.getLocalizedString( PROPERTY_MSG_NO_GOOD_ANSWER, locale );
472
473 break;
474
475 case 1:
476 strMessage = I18nService.getLocalizedString( PROPERTY_MSG_ONE_GOOD_ANSWER, locale );
477
478 break;
479
480 default:
481 break;
482 }
483
484 Object[] args = { nScore, nTotalQuestion };
485 String strScoreMessage = MessageFormat.format( strMessage, args );
486 model.put( MARK_SCORE, nScore );
487 model.put( MARK_SCORE_MESSAGE, strScoreMessage );
488
489 }
490 }
491
492 if ( model == null )
493 {
494 return null;
495 }
496
497 model.put( PARAMETER_OLD_STEP, nIdStep );
498
499
500 if ( QuestionGroupHome.getGroupByPosition( quiz.getIdQuiz( ), nIdStep + 1, plugin ) == null )
501 {
502 model.put( MARK_HAS_NEXT_STEP, Boolean.FALSE );
503 _quizService.processEndOfQuiz( quiz, "" + model.get( MARK_SCORE ), getUserAnswers( session ) );
504 }
505 else
506 {
507 model.put( MARK_HAS_NEXT_STEP, Boolean.TRUE );
508 }
509
510 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_QUIZ_RESULTS_STEP, locale, model );
511
512 page.setContent( template.getHtml( ) );
513
514 setQuizResultProperties( quiz, page, model, locale );
515
516 return page;
517 }
518
519
520
521
522
523
524
525
526
527
528 protected XPage getErrorPage( int nIdQuiz, String strError, int nStepToRedirect, Locale locale )
529 {
530 XPage page = new XPage( );
531 Map<String, Object> model = new HashMap<String, Object>( );
532 model.put( MARK_ERROR, strError );
533 model.put( MARK_ID_QUIZ, Integer.toString( nIdQuiz ) );
534 if ( nStepToRedirect > 1 )
535 {
536 model.put( PARAMETER_OLD_STEP, nStepToRedirect - 1 );
537 }
538
539 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_QUIZ_ERROR, locale, model );
540
541 page.setContent( template.getHtml( ) );
542
543 String strPath = I18nService.getLocalizedString( PROPERTY_QUIZ_ERROR_PAGE_PATH, locale );
544 String strTitle = I18nService.getLocalizedString( PROPERTY_QUIZ_ERROR_PAGE_TITLE, locale );
545 page.setPathLabel( strPath );
546 page.setTitle( strTitle );
547
548 return page;
549 }
550
551
552
553
554
555
556
557
558
559
560
561
562 @SuppressWarnings( "unchecked" )
563 private Map<String, String[]> saveAndValidateQuizAnswers( Quiz quiz, int nIdStep,
564 Map<String, String[]> mapParameters, Locale locale, Plugin plugin, HttpSession session )
565 {
566 Map<String, String[]> mapUserAnswers = _quizService.getUserAnswersForGroup( quiz.getIdQuiz( ), nIdStep,
567 mapParameters, locale, plugin );
568 Map<String, String[]> mapOldAnswers = (Map<String, String[]>) session.getAttribute( SESSION_KEY_QUIZ_STEP );
569 if ( mapOldAnswers != null )
570 {
571 mapOldAnswers.putAll( mapUserAnswers );
572 }
573 else
574 {
575 session.setAttribute( SESSION_KEY_QUIZ_STEP, mapUserAnswers );
576 }
577 return mapUserAnswers;
578 }
579
580
581
582
583
584
585 @SuppressWarnings( "unchecked" )
586 private Map<String, String[]> getUserAnswers( HttpSession session )
587 {
588 return (Map<String, String[]>) session.getAttribute( SESSION_KEY_QUIZ_STEP );
589 }
590
591
592
593
594
595
596
597
598 private void setQuizProperties( Quiz quiz, XPage page, Map<String, Object> model, Locale locale )
599 {
600 String strPath = I18nService.getLocalizedString( PROPERTY_QUIZ_PAGE_PATH, locale );
601 String strTitle = I18nService.getLocalizedString( PROPERTY_QUIZ_PAGE_TITLE, locale );
602 Object[] args = { quiz.getName( ) };
603 page.setPathLabel( MessageFormat.format( strPath, args ) );
604 page.setTitle( MessageFormat.format( strTitle, args ) );
605 }
606
607
608
609
610
611 private void resetUserAnswers( HttpSession session )
612 {
613 session.removeAttribute( SESSION_KEY_QUIZ_STEP );
614 }
615
616
617
618
619
620
621
622
623 private void setQuizResultProperties( Quiz quiz, XPage page, Map<String, Object> model, Locale locale )
624 {
625 String strPath = I18nService.getLocalizedString( PROPERTY_QUIZ_RESULTS_PAGE_PATH, locale );
626 String strTitle = I18nService.getLocalizedString( PROPERTY_QUIZ_RESULTS_PAGE_TITLE, locale );
627 Object[] args = { quiz.getName( ) };
628 page.setPathLabel( MessageFormat.format( strPath, args ) );
629 page.setTitle( MessageFormat.format( strTitle, args ) );
630 }
631 }