Files
mindflux/src/main/java/com/example/mindflux/controller/TechtacularApiController.java
T
AliceDarkest c5009d1718
mindflux-ci / build (push) Successful in 34s
Add TechTacular fifty-fifty joker
2026-07-19 20:01:06 +02:00

88 lines
3.5 KiB
Java

package com.example.mindflux.controller;
import com.example.mindflux.dto.*;
import com.example.mindflux.service.TechtacularService;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
import java.util.HashSet;
import java.util.Set;
import jakarta.servlet.http.HttpSession;
/** Spieler-API für TechTacular: Board laden, Antwort prüfen, Runde abschließen. */
@RestController
@RequestMapping("/api/techtacular")
public class TechtacularApiController {
private static final String JOKER_USED = "techtacular.fiftyFiftyUsed";
private static final String HINTED_QUESTION_IDS = "techtacular.hintedQuestionIds";
private final TechtacularService techtacularService;
public TechtacularApiController(TechtacularService techtacularService) {
this.techtacularService = techtacularService;
}
/** exclude = komma-separierte Frage-IDs der Vorrunde, die möglichst nicht erneut kommen sollen. */
@GetMapping("/board")
public TechtacularBoardView board(@RequestParam(required = false) String exclude, HttpSession session) {
// Ein neues Board beginnt immer eine neue Runde mit genau einem Joker.
session.removeAttribute(JOKER_USED);
session.removeAttribute(HINTED_QUESTION_IDS);
return techtacularService.buildBoard(parseIds(exclude));
}
private Set<Long> parseIds(String csv) {
Set<Long> ids = new HashSet<>();
if (csv != null && !csv.isBlank()) {
for (String part : csv.split(",")) {
try {
ids.add(Long.parseLong(part.trim()));
} catch (NumberFormatException ignored) {
// ungültige IDs einfach überspringen
}
}
}
return ids;
}
@PostMapping("/answer")
public AnswerResult answer(@RequestBody AnswerRequest request, HttpSession session) {
// Das Client-Flag dient der UI und dem Finish-Payload. Ob die Punkte halbiert
// werden, entscheidet jedoch allein der serverseitige Rundenzustand.
boolean validHint = hintedQuestionIds(session).contains(request.getQuestionId());
return techtacularService.checkAnswer(request.getQuestionId(), request.getAnswerId(), validHint);
}
/** Liefert zwei eliminierbare, garantiert falsche Antworten ohne die Loesung offenzulegen. */
@GetMapping("/hint")
public FiftyFiftyHint hint(@RequestParam Long questionId, HttpSession session) {
if (Boolean.TRUE.equals(session.getAttribute(JOKER_USED))) {
return new FiftyFiftyHint(java.util.List.of());
}
FiftyFiftyHint hint = techtacularService.fiftyFifty(questionId);
if (!hint.removeAnswerIds().isEmpty()) {
session.setAttribute(JOKER_USED, true);
Set<Long> hinted = new HashSet<>();
hinted.add(questionId);
session.setAttribute(HINTED_QUESTION_IDS, hinted);
}
return hint;
}
@PostMapping("/finish")
public TechtacularResult finish(@RequestBody FinishRequest request, Principal principal, HttpSession session) {
TechtacularResult result = techtacularService.finish(principal.getName(), request, hintedQuestionIds(session));
session.removeAttribute(JOKER_USED);
session.removeAttribute(HINTED_QUESTION_IDS);
return result;
}
@SuppressWarnings("unchecked")
private Set<Long> hintedQuestionIds(HttpSession session) {
Object value = session.getAttribute(HINTED_QUESTION_IDS);
return value instanceof Set<?> ? (Set<Long>) value : Set.of();
}
}