diff --git a/src/main/java/de/thm/arsnova/cache/CacheBuster.java b/src/main/java/de/thm/arsnova/cache/CacheBuster.java index 5291d6ee9f3def6b8c5850e5694a642d4f959e88..78e9cc75e42e94247aafc43e464de96cb4a1fe07 100644 --- a/src/main/java/de/thm/arsnova/cache/CacheBuster.java +++ b/src/main/java/de/thm/arsnova/cache/CacheBuster.java @@ -125,4 +125,7 @@ public class CacheBuster implements ICacheBuster, NovaEventVisitor { @Override public void visit(LockFeedbackEvent lockFeedbackEvent) { } + @Override + public void visit(FlipFlashcardsEvent flipFlashcardsEvent) { } + } diff --git a/src/main/java/de/thm/arsnova/controller/SessionController.java b/src/main/java/de/thm/arsnova/controller/SessionController.java index f846b836409cd9038fa4b5453050f089f53d6cf8..1c726fb5f1f4de40f41691fd08bfb1e15afdd060 100644 --- a/src/main/java/de/thm/arsnova/controller/SessionController.java +++ b/src/main/java/de/thm/arsnova/controller/SessionController.java @@ -409,6 +409,17 @@ public class SessionController extends PaginationController { ) { return sessionService.lockFeedbackInput(sessionkey, lock); } + + @RequestMapping(value = "/{sessionkey}/flipflashcards", method = RequestMethod.POST) + @ApiOperation(value = "flip all flashcards in session", + nickname = "lockFeedbackInput") + public boolean flipFlashcards( + @ApiParam(value = "session-key from current session", required = true) @PathVariable final String sessionkey, + @ApiParam(value = "flip", required = true) @RequestParam(required = true) final Boolean flip, + @ApiParam(value = "http servlet response", required = true) final HttpServletResponse response + ) { + return sessionService.flipFlashcards(sessionkey, flip); + } /* internal redirections */ diff --git a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java index 3ada67b9da35912324969fcdb75e2b0be232e319..713731b8a4c8bd2f2949ac2ee28ba1c352a7d213 100644 --- a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java +++ b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java @@ -2426,6 +2426,8 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware viewString = "sort_order/preparation_question_sort_order_by_sessionid_and_subject"; } else if ("lecture".equals(questionVariant)) { viewString = "sort_order/lecture_question_sort_order_by_sessionid_and_subject"; + } else if ("flashcard".equals(questionVariant)) { + return null; } NovaView view = new NovaView(viewString); diff --git a/src/main/java/de/thm/arsnova/domain/LearningProgressFactory.java b/src/main/java/de/thm/arsnova/domain/LearningProgressFactory.java index 3d67580f4a990f05f5fb5a488a6e29a27828e157..28d1132b209c9e0fdb4884d8917821c6b0b9bf9a 100644 --- a/src/main/java/de/thm/arsnova/domain/LearningProgressFactory.java +++ b/src/main/java/de/thm/arsnova/domain/LearningProgressFactory.java @@ -184,4 +184,7 @@ public class LearningProgressFactory implements NovaEventVisitor, ILearningProgr @Override public void visit(LockFeedbackEvent lockFeedbackEvent) { } + @Override + public void visit(FlipFlashcardsEvent flipFlashcardsEvent) { } + } diff --git a/src/main/java/de/thm/arsnova/entities/Session.java b/src/main/java/de/thm/arsnova/entities/Session.java index 6250806da1e299021019b6e852c7a67eab7f5942..e0f22a0009d436bf51cb7ffaee3cdf3992ee0661 100644 --- a/src/main/java/de/thm/arsnova/entities/Session.java +++ b/src/main/java/de/thm/arsnova/entities/Session.java @@ -57,6 +57,7 @@ public class Session implements Serializable { private String ppLevel; private String sessionType; private boolean feedbackLock; + private boolean flipFlashcards; private String _id; private String _rev; @@ -92,6 +93,7 @@ public class Session implements Serializable { copy.ppLevel = original.ppLevel; copy.sessionType = original.sessionType; copy.feedbackLock = original.feedbackLock; + copy.flipFlashcards = original.flipFlashcards; copy._id = original._id; copy._rev = original._rev; @@ -339,6 +341,15 @@ public class Session implements Serializable { public void setFeedbackLock(Boolean lock) { this.feedbackLock = lock; } + + @ApiModelProperty(required = true, value = "the flashcard flip condition") + public boolean getFlipFlashcards() { + return flipFlashcards; + } + + public void setFlipFlashcards(Boolean flip) { + this.flipFlashcards = flip; + } @Override public String toString() { diff --git a/src/main/java/de/thm/arsnova/entities/SessionFeature.java b/src/main/java/de/thm/arsnova/entities/SessionFeature.java index 131100bde53e5e11a6143f1575e2ba3ab89e31d6..e056717e95cbfa0a84c8151ed32c79e11fba4cf9 100644 --- a/src/main/java/de/thm/arsnova/entities/SessionFeature.java +++ b/src/main/java/de/thm/arsnova/entities/SessionFeature.java @@ -44,6 +44,7 @@ public class SessionFeature implements Serializable { private boolean interposed = true; private boolean pi = true; private boolean learningProgress = true; + private boolean flashcardFeature = true; private boolean slides = false; public SessionFeature(SessionFeature features) { @@ -56,6 +57,7 @@ public class SessionFeature implements Serializable { this.liveFeedback = features.liveFeedback; this.interposedFeedback = features.interposedFeedback; this.liveClicker = features.liveClicker; + this.flashcardFeature = features.flashcardFeature; this.flashcard = features.flashcard; this.total = features.total; this.lecture = features.lecture; @@ -147,6 +149,14 @@ public class SessionFeature implements Serializable { this.peerGrading = peerGrading; } + public boolean isFlashcardFeature() { + return flashcardFeature; + } + + public void setFlashcardFeature(boolean flashcardFeature) { + this.flashcardFeature = flashcardFeature; + } + public boolean isFlashcard() { return flashcard; } diff --git a/src/main/java/de/thm/arsnova/events/FlipFlashcardsEvent.java b/src/main/java/de/thm/arsnova/events/FlipFlashcardsEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..332124988aa1bf316abe2ceac2ed95352badc8ca --- /dev/null +++ b/src/main/java/de/thm/arsnova/events/FlipFlashcardsEvent.java @@ -0,0 +1,37 @@ +/* + * This file is part of ARSnova Backend. + * Copyright (C) 2012-2016 The ARSnova Team + * + * ARSnova Backend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ARSnova Backend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package de.thm.arsnova.events; + +import de.thm.arsnova.entities.Session; + +/** + * Fires whenever voting on a question is disabled. + */ +public class FlipFlashcardsEvent extends SessionEvent { + + private static final long serialVersionUID = 1L; + + public FlipFlashcardsEvent(Object source, Session session) { + super(source, session); + } + + @Override + public void accept(NovaEventVisitor visitor) { + visitor.visit(this); + } +} diff --git a/src/main/java/de/thm/arsnova/events/NovaEventVisitor.java b/src/main/java/de/thm/arsnova/events/NovaEventVisitor.java index 13fccdce39eb7faa801c6d54d855c01fcc295725..0626f7bf29dba3ba4f1074f34f06cd317b56074a 100644 --- a/src/main/java/de/thm/arsnova/events/NovaEventVisitor.java +++ b/src/main/java/de/thm/arsnova/events/NovaEventVisitor.java @@ -81,4 +81,6 @@ public interface NovaEventVisitor { void visit(FeatureChangeEvent featureChangeEvent); void visit(LockFeedbackEvent lockFeedbackEvent); + + void visit(FlipFlashcardsEvent flipFlashcardsEvent); } diff --git a/src/main/java/de/thm/arsnova/services/IQuestionService.java b/src/main/java/de/thm/arsnova/services/IQuestionService.java index 35ccb04781e4b7db89ddc84254e0152a8592fa12..f0864314749967c9b0c15066a57aad42a5fc38f4 100644 --- a/src/main/java/de/thm/arsnova/services/IQuestionService.java +++ b/src/main/java/de/thm/arsnova/services/IQuestionService.java @@ -125,6 +125,8 @@ public interface IQuestionService { int countPreparationQuestionAnswersInternal(String sessionkey); + int countFlashcardsForUserInternal(String sessionkey); + void deleteLectureQuestions(String sessionkey); void deleteFlashcards(String sessionkey); diff --git a/src/main/java/de/thm/arsnova/services/ISessionService.java b/src/main/java/de/thm/arsnova/services/ISessionService.java index 10f06e390beced23c4ff7ac7ee3009cd25cba9e0..373f78d27b5ce813c0d374e0ca735ec17d954386 100644 --- a/src/main/java/de/thm/arsnova/services/ISessionService.java +++ b/src/main/java/de/thm/arsnova/services/ISessionService.java @@ -91,4 +91,6 @@ public interface ISessionService { SessionFeature changeSessionFeatures(String sessionkey, SessionFeature features); boolean lockFeedbackInput(String sessionkey, Boolean lock); + + boolean flipFlashcards(String sessionkey, Boolean flip); } diff --git a/src/main/java/de/thm/arsnova/services/QuestionService.java b/src/main/java/de/thm/arsnova/services/QuestionService.java index c0f73137fe19f3edf42bf2f4f76b636f1fd95c32..b00252ea59528e6345e776acb71411ee20d1938d 100644 --- a/src/main/java/de/thm/arsnova/services/QuestionService.java +++ b/src/main/java/de/thm/arsnova/services/QuestionService.java @@ -918,6 +918,15 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis return databaseDao.countPreparationQuestionAnswers(getSession(sessionkey)); } + /* + * The "internal" suffix means it is called by internal services that have no authentication! + * TODO: Find a better way of doing this... + */ + @Override + public int countFlashcardsForUserInternal(final String sessionkey) { + return databaseDao.getFlashcardsForUsers(getSession(sessionkey)).size(); + } + @Override @PreAuthorize("isAuthenticated()") public void deleteLectureQuestions(final String sessionkey) { diff --git a/src/main/java/de/thm/arsnova/services/SessionService.java b/src/main/java/de/thm/arsnova/services/SessionService.java index 8894b82cc457c0178f2cd2506184f001adfd0cbf..291d35d416bbb3afb0bd4af01e4ad47dc4f0b6f0 100644 --- a/src/main/java/de/thm/arsnova/services/SessionService.java +++ b/src/main/java/de/thm/arsnova/services/SessionService.java @@ -33,6 +33,7 @@ import de.thm.arsnova.entities.transport.ImportExportSession; import de.thm.arsnova.entities.transport.LearningProgressValues; import de.thm.arsnova.events.DeleteSessionEvent; import de.thm.arsnova.events.FeatureChangeEvent; +import de.thm.arsnova.events.FlipFlashcardsEvent; import de.thm.arsnova.events.LockFeedbackEvent; import de.thm.arsnova.events.NewSessionEvent; import de.thm.arsnova.events.StatusSessionEvent; @@ -485,6 +486,18 @@ public class SessionService implements ISessionService, ApplicationEventPublishe this.publisher.publishEvent(new LockFeedbackEvent(this, session)); return databaseDao.updateSession(session).getFeedbackLock(); } + + @Override + public boolean flipFlashcards(String sessionkey, Boolean flip) { + final Session session = databaseDao.getSessionFromKeyword(sessionkey); + final User user = userService.getCurrentUser(); + if (!session.isCreator(user)) { + throw new UnauthorizedException(); + } + session.setFlipFlashcards(flip); + this.publisher.publishEvent(new FlipFlashcardsEvent(this, session)); + return databaseDao.updateSession(session).getFlipFlashcards(); + } /** * diff --git a/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java b/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java index e7b9143cc36382c97f794f4fd29ada8a3c2921d0..495040a55ec78a772e7c92ca06fd0b49c4a25493 100644 --- a/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java +++ b/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java @@ -355,6 +355,8 @@ public class ARSnovaSocketIOServer implements ARSnovaSocket, NovaEventVisitor { */ public void reportSessionDataToClient(final String sessionKey, final User user, final SocketIOClient client) { final de.thm.arsnova.entities.Session session = sessionService.getSessionInternal(sessionKey, user); + final de.thm.arsnova.entities.SessionFeature features = sessionService.getSessionFeatures(sessionKey); + client.sendEvent("unansweredLecturerQuestions", questionService.getUnAnsweredLectureQuestionIds(sessionKey, user)); client.sendEvent("unansweredPreparationQuestions", questionService.getUnAnsweredPreparationQuestionIds(sessionKey, user)); client.sendEvent("countLectureQuestionAnswers", questionService.countLectureQuestionAnswersInternal(sessionKey)); @@ -363,6 +365,12 @@ public class ARSnovaSocketIOServer implements ARSnovaSocket, NovaEventVisitor { client.sendEvent("learningProgressOptions", session.getLearningProgressOptions()); final de.thm.arsnova.entities.Feedback fb = feedbackService.getFeedback(sessionKey); client.sendEvent("feedbackData", fb.getValues()); + + if (features.isFlashcard() || features.isFlashcardFeature()) { + client.sendEvent("countFlashcards", questionService.countFlashcardsForUserInternal(sessionKey)); + client.sendEvent("flipFlashcards", session.getFlipFlashcards()); + } + try { final long averageFeedback = feedbackService.getAverageFeedbackRounded(sessionKey); client.sendEvent("feedbackDataRoundedAverage", averageFeedback); @@ -578,13 +586,24 @@ public class ARSnovaSocketIOServer implements ARSnovaSocket, NovaEventVisitor { @Override public void visit(FeatureChangeEvent event) { final String sessionKey = event.getSession().getKeyword(); - broadcastInSession(sessionKey, "featureChange", event.getSession().getFeatures()); + final de.thm.arsnova.entities.SessionFeature features = event.getSession().getFeatures(); + broadcastInSession(sessionKey, "featureChange", features); + + if (features.isFlashcard() || features.isFlashcardFeature()) { + broadcastInSession(sessionKey, "countFlashcards", questionService.countFlashcardsForUserInternal(sessionKey)); + broadcastInSession(sessionKey, "flipFlashcards", event.getSession().getFlipFlashcards()); + } } @Override public void visit(LockFeedbackEvent event) { broadcastInSession(event.getSession().getKeyword(), "lockFeedback", event.getSession().getFeedbackLock()); } + + @Override + public void visit(FlipFlashcardsEvent event) { + broadcastInSession(event.getSession().getKeyword(), "flipFlashcards", event.getSession().getFlipFlashcards()); + } @Override public void visit(DeleteQuestionEvent deleteQuestionEvent) {