Skip to content
Snippets Groups Projects
Commit e9160e80 authored by Andreas Gärtner's avatar Andreas Gärtner
Browse files

Added implementation for delayed pi-round change. Task #15346

The delayed pi-round change can now be triggered via a simple api call.
After the api call a timed task will be started, which executes the
necessary steps for a round change. 
parent 88fcf222
Branches
Tags
No related merge requests found
Showing
with 270 additions and 1 deletion
......@@ -84,6 +84,19 @@ public class LecturerQuestionController extends AbstractController {
}
}
@RequestMapping(value = "/{questionId}/startNewPiRound", method = RequestMethod.GET)
public void startSecondPiRound(
@PathVariable final String questionId,
@RequestParam(value = "time", defaultValue = "0", required = false) final int time
) {
if(time == 0) {
questionService.startNewPiRound(questionId, null);
} else {
questionService.startNewPiRoundDelayed(questionId, time);
}
}
@RequestMapping(value = "/{questionId}/publish", method = RequestMethod.POST)
public void publishQuestion(
@PathVariable final String questionId,
......
......@@ -33,6 +33,8 @@ import de.thm.arsnova.events.NewFeedbackEvent;
import de.thm.arsnova.events.NewInterposedQuestionEvent;
import de.thm.arsnova.events.NewQuestionEvent;
import de.thm.arsnova.events.NovaEventVisitor;
import de.thm.arsnova.events.PiRoundDelayedStartEvent;
import de.thm.arsnova.events.PiRoundEndEvent;
import de.thm.arsnova.events.StatusSessionEvent;
/**
......@@ -81,4 +83,10 @@ public class CacheBuster implements ICacheBuster, NovaEventVisitor {
@Override
public void visit(ChangeLearningProgress changeLearningProgress) {}
@Override
public void visit(PiRoundDelayedStartEvent piRoundDelayedStartEvent) {}
@Override
public void visit(PiRoundEndEvent piRoundEndEvent) {}
}
......@@ -37,6 +37,8 @@ import de.thm.arsnova.events.NewFeedbackEvent;
import de.thm.arsnova.events.NewInterposedQuestionEvent;
import de.thm.arsnova.events.NewQuestionEvent;
import de.thm.arsnova.events.NovaEventVisitor;
import de.thm.arsnova.events.PiRoundDelayedStartEvent;
import de.thm.arsnova.events.PiRoundEndEvent;
import de.thm.arsnova.events.StatusSessionEvent;
@Component
......@@ -121,4 +123,10 @@ public class LearningProgressFactory implements NovaEventVisitor, ILearningProgr
this.publisher = publisher;
}
@Override
public void visit(PiRoundDelayedStartEvent piRoundDelayedStartEvent) {}
@Override
public void visit(PiRoundEndEvent piRoundEndEvent) {}
}
......@@ -17,6 +17,7 @@
*/
package de.thm.arsnova.entities;
import java.util.HashMap;
import java.util.List;
public class Question {
......@@ -38,6 +39,9 @@ public class Question {
private int number;
private int duration;
private int piRound;
private long piRoundEndTime;
private long piRoundStartTime;
private boolean piRoundActive;
private boolean showStatistic; // sic
private boolean showAnswer;
private boolean abstention;
......@@ -195,6 +199,30 @@ public class Question {
this.piRound = piRound;
}
public long getPiRoundEndTime() {
return piRoundEndTime;
}
public void setPiRoundEndTime(long piRoundEndTime) {
this.piRoundEndTime = piRoundEndTime;
}
public long getPiRoundStartTime() {
return piRoundStartTime;
}
public void setPiRoundStartTime(long piRoundStartTime) {
this.piRoundStartTime = piRoundStartTime;
}
public boolean isPiRoundActive() {
return piRoundActive;
}
public void setPiRoundActive(boolean piRoundActive) {
this.piRoundActive = piRoundActive;
}
public boolean isShowStatistic() {
return showStatistic;
}
......
......@@ -45,4 +45,8 @@ public interface NovaEventVisitor {
void visit(ChangeLearningProgress changeLearningProgress);
void visit(PiRoundDelayedStartEvent piRoundDelayedStartEvent);
void visit(PiRoundEndEvent piRoundEndEvent);
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2015 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 java.util.Date;
import java.util.HashMap;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Session;
public class PiRoundDelayedStartEvent extends SessionEvent {
private static final long serialVersionUID = 1L;
private final String questionId;
private final Long startTime;
private final Long endTime;
public PiRoundDelayedStartEvent(Object source, Session session, Question question) {
super(source, session);
this.questionId = question.get_id();
this.startTime = question.getPiRoundStartTime();
this.endTime = question.getPiRoundEndTime();
}
@Override
public void accept(NovaEventVisitor visitor) {
visitor.visit(this);
}
public String getQuestionId() {
return questionId;
}
public Long getStartTime() {
return startTime;
}
public Long getEndTime() {
return endTime;
}
public HashMap<String, String> getPiRoundInformations() {
HashMap<String, String> map = new HashMap<String, String>();
map.put("id", getQuestionId());
map.put("endTime", getEndTime().toString());
map.put("startTime", getStartTime().toString());
map.put("actualTime", String.valueOf(new Date().getTime()));
return map;
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2015 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.Question;
import de.thm.arsnova.entities.Session;
public class PiRoundEndEvent extends SessionEvent {
private static final long serialVersionUID = 1L;
private final String questionId;
public PiRoundEndEvent(Object source, Session session, Question question) {
super(source, session);
questionId = question.get_id();
}
@Override
public void accept(NovaEventVisitor visitor) {
visitor.visit(this);
}
public String getQuestionId() {
return questionId;
}
}
......@@ -41,6 +41,12 @@ public interface IQuestionService {
void deleteAllQuestions(String sessionKeyword);
void startNewPiRound(String questionId, User user);
void startNewPiRoundDelayed(String questionId, int time);
public void cancelDelayedPiRoundChange(final String questionId);
List<String> getUnAnsweredQuestionIds(String sessionKey);
Answer getMyAnswer(String questionId);
......@@ -69,6 +75,8 @@ public interface IQuestionService {
Question update(Question question);
Question update(Question question, User user);
void deleteAnswers(String questionId);
Answer saveAnswer(String questionId, de.thm.arsnova.entities.transport.Answer answer);
......
......@@ -21,9 +21,12 @@ import java.util.AbstractMap;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import de.thm.arsnova.exceptions.ForbiddenException;
......@@ -53,6 +56,8 @@ import de.thm.arsnova.events.DeleteQuestionEvent;
import de.thm.arsnova.events.NewAnswerEvent;
import de.thm.arsnova.events.NewInterposedQuestionEvent;
import de.thm.arsnova.events.NewQuestionEvent;
import de.thm.arsnova.events.PiRoundDelayedStartEvent;
import de.thm.arsnova.events.PiRoundEndEvent;
import de.thm.arsnova.exceptions.BadRequestException;
import de.thm.arsnova.exceptions.NotFoundException;
import de.thm.arsnova.exceptions.UnauthorizedException;
......@@ -73,6 +78,8 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
public static final Logger LOGGER = LoggerFactory.getLogger(QuestionService.class);
private HashMap<String, Timer> timerList = new HashMap<String, Timer>();
public void setDatabaseDao(final IDatabaseDao databaseDao) {
this.databaseDao = databaseDao;
}
......@@ -190,6 +197,61 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
this.publisher.publishEvent(event);
}
public void startNewPiRound(final String questionId, User user) {
if(null == user) {
user = userService.getCurrentUser();
}
cancelDelayedPiRoundChange(questionId);
final Question question = databaseDao.getQuestion(questionId);
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
question.setPiRound(question.getPiRound() + 1);
question.setActive(false);
update(question, user);
this.publisher.publishEvent(new PiRoundEndEvent(this, session, question));
}
@Override
@PreAuthorize("isAuthenticated() and hasPermission(#questionId, 'question', 'owner')")
public void startNewPiRoundDelayed(final String questionId, final int time) {
final Timer timer = new Timer();
final Date date = new Date();
final Date endDate = new Date(date.getTime() + (time * 1000));
final IQuestionService questionService = this;
final User user = userService.getCurrentUser();
final Question question = databaseDao.getQuestion(questionId);
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
cancelDelayedPiRoundChange(questionId);
timer.schedule(new TimerTask() {
public void run() {
questionService.startNewPiRound(questionId, user);
}
}, endDate);
timerList.put(questionId, timer);
question.setPiRoundActive(true);
question.setPiRoundStartTime(date.getTime());
question.setPiRoundEndTime(endDate.getTime());
update(question);
this.publisher.publishEvent(new PiRoundDelayedStartEvent(this, session, question));
}
public void cancelDelayedPiRoundChange(final String questionId) {
Timer timer = timerList.get(questionId);
if(null != timer) {
timer.cancel();
timerList.remove(questionId);
timer.purge();
}
}
private Session getSessionWithAuthCheck(final String sessionKeyword) {
final User user = userService.getCurrentUser();
final Session session = databaseDao.getSessionFromKeyword(sessionKeyword);
......@@ -425,12 +487,18 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
@Override
@PreAuthorize("isAuthenticated()")
public Question update(final Question question) {
final User user = userService.getCurrentUser();
return update(question, user);
}
@Override
@PreAuthorize("isAuthenticated()")
public Question update(final Question question, User user) {
final Question oldQuestion = databaseDao.getQuestion(question.get_id());
if (null == oldQuestion) {
throw new NotFoundException();
}
final User user = userService.getCurrentUser();
final Session session = databaseDao.getSessionFromKeyword(question.getSessionKeyword());
if (user == null || session == null || !session.isCreator(user)) {
throw new UnauthorizedException();
......
......@@ -62,6 +62,8 @@ import de.thm.arsnova.events.NewFeedbackEvent;
import de.thm.arsnova.events.NewInterposedQuestionEvent;
import de.thm.arsnova.events.NewQuestionEvent;
import de.thm.arsnova.events.NovaEventVisitor;
import de.thm.arsnova.events.PiRoundDelayedStartEvent;
import de.thm.arsnova.events.PiRoundEndEvent;
import de.thm.arsnova.events.StatusSessionEvent;
import de.thm.arsnova.exceptions.UnauthorizedException;
import de.thm.arsnova.exceptions.NoContentException;
......@@ -474,6 +476,22 @@ public class ARSnovaSocketIOServer implements ARSnovaSocket, NovaEventVisitor {
broadcastInSession(sessionKey, "countPreparationQuestionAnswers", questionService.countPreparationQuestionAnswersInternal(sessionKey));
}
@Async
@Override
public void visit(PiRoundDelayedStartEvent event) {
final String sessionKey = event.getSession().getKeyword();
broadcastInSession(sessionKey, "startDelayedPiRound", event.getPiRoundInformations());
}
@Async
@Override
public void visit(PiRoundEndEvent event) {
final String sessionKey = event.getSession().getKeyword();
broadcastInSession(sessionKey, "endPiRound", event.getQuestionId());
}
@Override
public void visit(DeleteQuestionEvent deleteQuestionEvent) {
// TODO Auto-generated method stub
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment