[Added] Tests and some more functionality to the Services
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package com.ninjaws.quiz.services;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import com.ninjaws.quiz.models.QuizSettings;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@Service
|
||||
public class ApiService {
|
||||
|
||||
// @Autowired
|
||||
// private ObjectMapper objectMapper;
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
private final String apiUrl = "https://opentdb.com/api.php";
|
||||
|
||||
// private String sessionToken = "";
|
||||
|
||||
@Autowired
|
||||
public ApiService(RestTemplate restTemplate) {
|
||||
this.restTemplate = restTemplate;
|
||||
// try {
|
||||
// sessionToken = requestSessionToken();
|
||||
// } catch (Exception e) {
|
||||
// // Failed to get a session token, setting default to none
|
||||
// sessionToken = "";
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
private String buildRequestString(QuizSettings quizSettings) {
|
||||
return apiUrl + quizSettings.toApiQuery();
|
||||
}
|
||||
|
||||
// private int getResponseCode(String json) throws Exception {
|
||||
// JsonNode jsonNode = objectMapper.readTree(json);
|
||||
// return jsonNode.get("response_code").asInt();
|
||||
// }
|
||||
|
||||
// public String requestSessionToken() throws Exception {
|
||||
// String sessionTokenRequestUrl = "https://opentdb.com/api_token.php?command=request";
|
||||
// ResponseEntity<String> response = restTemplate.getForEntity(sessionTokenRequestUrl, String.class);
|
||||
// JsonNode jsonNode = objectMapper.readTree(response.getBody());
|
||||
// if (jsonNode.get("response_code").asInt() == 0) {
|
||||
// sessionToken = jsonNode.get("token").asText();
|
||||
// }else {
|
||||
// // Failed to get a session token, setting default to none
|
||||
// sessionToken = "";
|
||||
// }
|
||||
// return sessionToken;
|
||||
// }
|
||||
|
||||
public String requestQuestions(@Valid QuizSettings quizSettings) {
|
||||
String url = buildRequestString(quizSettings);
|
||||
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
|
||||
String jsonData = response.getBody();
|
||||
|
||||
// try {
|
||||
// int responseCode = getResponseCode(jsonData);
|
||||
// /** When the code has expired or you've ran out of questions, update the token and try again */
|
||||
// if(responseCode == 3 || responseCode == 4) {
|
||||
// requestSessionToken();
|
||||
// requestQuestions(quizSettings);
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// // Failed to get a responseCode, meaning the request failed completely (they always send a response_code)
|
||||
// }
|
||||
return jsonData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.ninjaws.quiz.services;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.ninjaws.quiz.models.Answers;
|
||||
import com.ninjaws.quiz.models.ApiResponse;
|
||||
import com.ninjaws.quiz.models.Question;
|
||||
import com.ninjaws.quiz.models.QuizSettings;
|
||||
import com.ninjaws.quiz.models.Request;
|
||||
import com.ninjaws.quiz.models.Session;
|
||||
|
||||
|
||||
@Service
|
||||
public class QuizService {
|
||||
|
||||
@Autowired
|
||||
private ApiService apiService;
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* Stores all active sessions
|
||||
* Gets added to when a user requests data
|
||||
* Gets removed from when a user requests their score (by sending their answers)
|
||||
*/
|
||||
// private final Map<String,Session> sessions = new ConcurrentHashMap<>();
|
||||
private final Cache<String,Session> sessions;
|
||||
|
||||
/**
|
||||
* Stores all user requests for data
|
||||
* Executes them in order, one every 5 seconds (the limit of the external API)
|
||||
* Removes them from the Queue when the request was succesful
|
||||
*/
|
||||
private final BlockingQueue<Request> requests = new LinkedBlockingQueue<>();
|
||||
|
||||
|
||||
public QuizService() {
|
||||
sessions = (Caffeine.newBuilder()
|
||||
.expireAfterWrite(1,TimeUnit.HOURS)
|
||||
.build());
|
||||
}
|
||||
|
||||
public QuizService(Cache<String, Session> cache) {
|
||||
sessions = cache;
|
||||
}
|
||||
|
||||
public QuizSettings jsonToQuizSettings(String json){
|
||||
QuizSettings quizSettings = new QuizSettings();
|
||||
return quizSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actions:
|
||||
* - Creates a session with sessionId
|
||||
* - Adds session to the cache
|
||||
* - Creates a request and adds it to the queue
|
||||
* @param quizSettings The values set by the user, determining the kind of quiz they want
|
||||
* @return The sessionId
|
||||
*/
|
||||
public String createSession(QuizSettings quizSettings) {
|
||||
Session session = new Session();
|
||||
try {
|
||||
requests.put(new Request(session.getId(), quizSettings));
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
return session.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Actions:
|
||||
* - Looks up the session in the cache
|
||||
* - Checks if the data from the request is stored
|
||||
* @param sessionId
|
||||
* @return The data if it's available, Optional.empty() if not, and an Exception if the session is invalid
|
||||
*/
|
||||
public Optional<Session> checkSession(String sessionId) throws IllegalArgumentException {
|
||||
Session session = sessions.getIfPresent(sessionId);
|
||||
|
||||
if(session == null) {
|
||||
throw new IllegalArgumentException("Invalid session ID: " + sessionId);
|
||||
}
|
||||
|
||||
if (session.getQuestions() == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
System.out.print(session.getQuestions().get(0).getIncorrectAnswers().get(0));
|
||||
return Optional.of(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* Every 5 seconds:
|
||||
* - Take the top request from the queue (removes it)
|
||||
* - Perform the request
|
||||
* - Wait for the data
|
||||
* - Find the matching session from the cache
|
||||
* - Add the data to the session in the cache
|
||||
*/
|
||||
@Scheduled(fixedDelay = 5000)
|
||||
protected void processQueue() {
|
||||
System.out.print("Schedule!");
|
||||
Request request = requests.poll();
|
||||
if (request != null) {
|
||||
System.out.print("----------------An item!");
|
||||
String json = apiService.requestQuestions(request.getQuizSettings());
|
||||
System.out.print(json);
|
||||
try {
|
||||
List<Question> questions = extractQuestions(json);
|
||||
Session session = sessions.getIfPresent(request.getSessionId());
|
||||
session.setQuestions(questions);
|
||||
sessions.put(request.getSessionId(), session);
|
||||
} catch (IOException e) {
|
||||
//TODO: Log this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Question> extractQuestions(String json) throws IOException {
|
||||
return objectMapper.readValue(json, ApiResponse.class).getResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives: sessionId and answers
|
||||
*
|
||||
* Actions:
|
||||
* - retrieves session from cache
|
||||
* - Deletes session from cache
|
||||
* - Matches answers answers to correctAnswers
|
||||
* - Calculates score
|
||||
* Returns: calculated score
|
||||
* */
|
||||
public String getScore(Answers answers) {
|
||||
Session session = sessions.getIfPresent(answers.getSessionId());
|
||||
sessions.invalidate(session.getId());
|
||||
return calculateScore(session, answers);
|
||||
}
|
||||
|
||||
private String calculateScore(Session session, Answers answers) {
|
||||
System.out.print(session);
|
||||
System.out.print(answers);
|
||||
return "You did great!";
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user