Skip to content
59 changes: 54 additions & 5 deletions src/main/java/com/patina/codebloom/api/duel/DuelController.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.patina.codebloom.api.duel;

import java.time.OffsetDateTime;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -8,9 +10,19 @@
import org.springframework.web.server.ResponseStatusException;

import com.patina.codebloom.common.components.DuelManager;
import com.patina.codebloom.common.db.models.lobby.Lobby;
import com.patina.codebloom.common.db.models.lobby.LobbyStatus;
import com.patina.codebloom.common.db.models.lobby.player.LobbyPlayer;
import com.patina.codebloom.common.db.models.user.User;
import com.patina.codebloom.common.db.repos.lobby.LobbyRepository;
import com.patina.codebloom.common.db.repos.lobby.player.LobbyPlayerRepository;
import com.patina.codebloom.common.dto.ApiResponder;
import com.patina.codebloom.common.dto.Empty;
import com.patina.codebloom.common.env.Env;
import com.patina.codebloom.common.security.AuthenticationObject;
import com.patina.codebloom.common.security.annotation.Protected;
import com.patina.codebloom.common.time.StandardizedOffsetDateTime;
import com.patina.codebloom.common.utils.duel.PartyCodeGenerator;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
Expand All @@ -24,10 +36,15 @@ public class DuelController {

private final Env env;
private final DuelManager duelManager;
private final LobbyRepository lobbyRepository;
private final LobbyPlayerRepository lobbyPlayerRepository;

public DuelController(final Env env, final DuelManager duelManager) {
public DuelController(final Env env, final DuelManager duelManager, final LobbyRepository lobbyRepository,
final LobbyPlayerRepository lobbyPlayerRepository) {
this.env = env;
this.duelManager = duelManager;
this.lobbyRepository = lobbyRepository;
this.lobbyPlayerRepository = lobbyPlayerRepository;
}

@Operation(summary = "Join party", description = "WIP")
Expand All @@ -52,14 +69,46 @@ public ResponseEntity<ApiResponder<Empty>> leaveParty() {
return ResponseEntity.ok(ApiResponder.success("ok", Empty.of()));
}

@Operation(summary = "Create party", description = "WIP")
@ApiResponse(responseCode = "403", description = "Endpoint is currently non-functional")
@Operation(summary = "Create party", description = "Create a new lobby and become the host")
@ApiResponse(responseCode = "200", description = "Lobby created successfully")
@ApiResponse(responseCode = "400", description = "Player is already in a lobby")
@ApiResponse(responseCode = "401", description = "User not authenticated")
@PostMapping("/party/create")
public ResponseEntity<ApiResponder<Empty>> createParty() {
public ResponseEntity<ApiResponder<Empty>> createParty(@Protected final AuthenticationObject authenticationObject) {
if (env.isProd()) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Endpoint is currently non-functional");
}

return ResponseEntity.ok(ApiResponder.success("ok", Empty.of()));
User user = authenticationObject.getUser();
String playerId = user.getId();

LobbyPlayer existingLobbyPlayer = lobbyPlayerRepository.findLobbyPlayerByPlayerId(playerId);
if (existingLobbyPlayer != null) {
return ResponseEntity.badRequest()
.body(ApiResponder.failure("You are already in a lobby. Please leave your current lobby before creating a new one."));
}

String joinCode = PartyCodeGenerator.generateCode();
OffsetDateTime expiresAt = StandardizedOffsetDateTime.now().plusMinutes(30);

Lobby lobby = Lobby.builder()
.joinCode(joinCode)
.status(LobbyStatus.AVAILABLE)
.expiresAt(expiresAt)
.playerCount(1)
.winnerId(null)
.build();

lobbyRepository.createLobby(lobby);

LobbyPlayer lobbyPlayer = LobbyPlayer.builder()
.lobbyId(lobby.getId())
.playerId(playerId)
.points(0)
.build();

lobbyPlayerRepository.createLobbyPlayer(lobbyPlayer);

return ResponseEntity.ok(ApiResponder.success("Lobby created successfully! Share the join code: " + lobby.getJoinCode(), Empty.of()));
}
}
47 changes: 47 additions & 0 deletions src/main/java/com/patina/codebloom/api/duel/dto/LobbyDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.patina.codebloom.api.duel.dto;

import java.time.OffsetDateTime;

import com.patina.codebloom.common.db.models.lobby.Lobby;
import com.patina.codebloom.common.db.models.lobby.LobbyStatus;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.jackson.Jacksonized;

@Getter
@Builder
@Jacksonized
@ToString
@EqualsAndHashCode
public class LobbyDto {
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private String id;
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private String joinCode;
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private LobbyStatus status;
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private OffsetDateTime expiresAt;
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private OffsetDateTime createdAt;
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private int playerCount;
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, nullable = true)
private String winnerId;

public static LobbyDto fromLobby(final Lobby lobby) {
return LobbyDto.builder()
.id(lobby.getId())
.joinCode(lobby.getJoinCode())
.status(lobby.getStatus())
.expiresAt(lobby.getExpiresAt())
.createdAt(lobby.getCreatedAt())
.playerCount(lobby.getPlayerCount())
.winnerId(lobby.getWinnerId())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.patina.codebloom.common.utils.duel;

import java.security.SecureRandom;

public class PartyCodeGenerator {
private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private static final int CODE_LENGTH = 6;
private static final SecureRandom RANDOM = new SecureRandom();

/**
* Generates a random party code
*
* @return A random party code (e.g., "ABC123")
*/
public static String generateCode() {
StringBuilder codeBuilder = new StringBuilder(CODE_LENGTH);
for (int i = 0; i < CODE_LENGTH; i++) {
codeBuilder.append(CHARACTERS.charAt(RANDOM.nextInt(CHARACTERS.length())));
}
return codeBuilder.toString();
}
}
Loading
Loading