diff --git a/sth-backend/pom.xml b/sth-backend/pom.xml index 18c77c9ea9cf0c8259571608b1266915f5f3a305..539b22fe07c9d786494a8053c653dd92db1b1414 100644 --- a/sth-backend/pom.xml +++ b/sth-backend/pom.xml @@ -21,6 +21,11 @@ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>5.8.0</version> + </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> @@ -61,8 +66,13 @@ <artifactId>spring-boot-starter-data-mongodb</artifactId> <version>3.2.0</version> </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> - </dependencies> + </dependencies> <build> <plugins> diff --git a/sth-backend/src/main/java/hdm/mi/sthbackend/controller/TournamentController.java b/sth-backend/src/main/java/hdm/mi/sthbackend/controller/TournamentController.java index 8a9061515631b474a37d4a4e71030425db6e6426..16288fb200ca4a661143d645b926f0c04658e343 100644 --- a/sth-backend/src/main/java/hdm/mi/sthbackend/controller/TournamentController.java +++ b/sth-backend/src/main/java/hdm/mi/sthbackend/controller/TournamentController.java @@ -7,6 +7,7 @@ import hdm.mi.sthbackend.dto.TeamDTO; import hdm.mi.sthbackend.dto.TournamentDTO; import hdm.mi.sthbackend.exeptions.*; import hdm.mi.sthbackend.model.Match; +import hdm.mi.sthbackend.model.Tournament; import hdm.mi.sthbackend.service.TournamentService; import hdm.mi.sthbackend.types.TeamMatchScore; import hdm.mi.sthbackend.types.TeamName; @@ -56,6 +57,10 @@ public class TournamentController { @PathVariable UUID teamId) throws TournamentIdNotFoundException, TeamIdNotFoundException { return service.deleteAndRemoveTeamFromTournament(tournamentId, teamId); } + @PatchMapping("tournaments/{tournamentId}/matches/{matchId}/teams/{teamId}/assignTeamToMatch") + public Tournament assignTeamToMatch(@PathVariable UUID tournamentId, @PathVariable UUID matchId, @PathVariable UUID teamId, @RequestBody int bracketRound, @RequestBody TeamMatchScore score) throws TournamentIdNotFoundException, MatchIdNotFoundException { + return service.assignTeamToMatch(tournamentId, bracketRound, matchId, teamId, score.getScore()); + } @PostMapping("/teams/{teamId}/addPlayer") public PlayerDTO addPlayerToTeam(@PathVariable UUID teamId, @@ -79,10 +84,6 @@ public class TournamentController { /** * Match Endpoints */ - @PatchMapping("matches/{matchId}/teams/{teamId}/assignTeamToMatch") - public MatchDTO assignTeamToMatch(@PathVariable UUID matchId, @PathVariable UUID teamId, @RequestBody TeamMatchScore score) throws MatchIdNotFoundException { - return service.assignTeamToMatch(matchId, teamId, score.getScore()); - } @PatchMapping("matches/{matchId}/teams/{teamId}/updateScore") public MatchDTO updateScore(@PathVariable UUID matchId, @PathVariable UUID teamId, @RequestBody TeamMatchScore newScore) throws MatchIdNotFoundException, TeamIdNotFoundException { @@ -99,17 +100,17 @@ public class TournamentController { * Tournament Endpoints */ @GetMapping("/tournaments/{tournamentId}") - public TournamentDTO findTournamentById(@PathVariable UUID tournamentId) throws TournamentIdNotFoundException { + public Tournament findTournamentById(@PathVariable UUID tournamentId) throws TournamentIdNotFoundException { return service.getTournament(tournamentId); } @PostMapping("/tournaments") - public TournamentDTO createTournament(@RequestBody TournamentName params) { - return service.createTournament(params.getName()); + public Tournament createTournament(@RequestBody Tournament tournament) { + return service.createTournament(tournament); } @DeleteMapping("/tournaments/{tournamentId}") - public TournamentDTO deleteTournament(@PathVariable UUID tournamentId) throws TournamentIdNotFoundException { + public Tournament deleteTournament(@PathVariable UUID tournamentId) throws TournamentIdNotFoundException { return service.deleteTournament(tournamentId); } diff --git a/sth-backend/src/main/java/hdm/mi/sthbackend/exeptions/BracketAlreadyInitializedException.java b/sth-backend/src/main/java/hdm/mi/sthbackend/exeptions/BracketAlreadyInitializedException.java new file mode 100644 index 0000000000000000000000000000000000000000..e5f0de9a9fc71d68bd722b2c178ffe8c3b79f9c3 --- /dev/null +++ b/sth-backend/src/main/java/hdm/mi/sthbackend/exeptions/BracketAlreadyInitializedException.java @@ -0,0 +1,15 @@ +package hdm.mi.sthbackend.exeptions; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.UUID; + +public class BracketAlreadyInitializedException extends Exception{ + private final Logger log = LogManager.getLogger("BracketAlreadyInitializedException"); + + public BracketAlreadyInitializedException(UUID tournamentId){ + super(String.format("Bracket of %s (tournamentId) already initialized", tournamentId.toString())); + } + +} diff --git a/sth-backend/src/main/java/hdm/mi/sthbackend/exeptions/InsufficientTeamsException.java b/sth-backend/src/main/java/hdm/mi/sthbackend/exeptions/InsufficientTeamsException.java new file mode 100644 index 0000000000000000000000000000000000000000..34c6cdc4e7a9702d6747dafd8227bc29c7f48bf2 --- /dev/null +++ b/sth-backend/src/main/java/hdm/mi/sthbackend/exeptions/InsufficientTeamsException.java @@ -0,0 +1,15 @@ +package hdm.mi.sthbackend.exeptions; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.UUID; + +public class InsufficientTeamsException extends Exception{ + private final Logger log = LogManager.getLogger("InsufficientTeamsException"); + + public InsufficientTeamsException(UUID tournamentId){ + super(String.format("Insufficient Teams in %s.", tournamentId.toString())); + } + +} diff --git a/sth-backend/src/main/java/hdm/mi/sthbackend/mapper/ModelToDTOMapper.java b/sth-backend/src/main/java/hdm/mi/sthbackend/mapper/ModelToDTOMapper.java index 897da408c9b9c5fe212796953adc7f53b8e762cf..b9418ca1d3d15337aefda1c141263998bc091a90 100644 --- a/sth-backend/src/main/java/hdm/mi/sthbackend/mapper/ModelToDTOMapper.java +++ b/sth-backend/src/main/java/hdm/mi/sthbackend/mapper/ModelToDTOMapper.java @@ -46,41 +46,42 @@ public class ModelToDTOMapper { this.playerRepository = playerRepository; } - public TournamentDTO mapToTournamentDTO(Tournament tournament) { - Map<UUID, Match> matches = new HashMap<>(); - tournament.getMatches() - .forEach(mId -> { - try { - matches.put(mId, matchRepository.findById(mId) - .orElseThrow(() -> new MatchIdNotFoundException(mId))); - } catch (MatchIdNotFoundException e) { - log.debug("Match with id " + mId + " not found"); - } - }); - Map<UUID, MatchDTO> mappedMatches = matches.entrySet() - .stream() - .collect(Collectors.toMap(Entry::getKey, e -> mapToMatchDTO(e.getValue()))); - - Map<UUID, Team> teams = new HashMap<>(); - tournament.getTeams() - .forEach(teamId -> { - try { - teams.put(teamId, teamRepository.findById(teamId) - .orElseThrow(() -> new TournamentIdNotFoundException(teamId))); - } catch (TournamentIdNotFoundException e) { - log.debug("Team with id " + teamId + " not found"); - } - }); - Map<UUID, TeamDTO> mappedTeams = teams.entrySet() - .stream() - .collect(Collectors.toMap(Entry::getKey, e -> mapToTeamDTO(e.getValue()))); - return new TournamentDTO( - tournament.getTournamentId(), - tournament.getTournamentName(), - mappedMatches, - mappedTeams - ); - } + //todo +// public TournamentDTO mapToTournamentDTO(Tournament tournament) { +// Map<UUID, Match> matches = new HashMap<>(); +// tournament.getMatches() +// .forEach(mId -> { +// try { +// matches.put(mId, matchRepository.findById(mId) +// .orElseThrow(() -> new MatchIdNotFoundException(mId))); +// } catch (MatchIdNotFoundException e) { +// log.debug("Match with id " + mId + " not found"); +// } +// }); +// Map<UUID, MatchDTO> mappedMatches = matches.entrySet() +// .stream() +// .collect(Collectors.toMap(Entry::getKey, e -> mapToMatchDTO(e.getValue()))); +// +// Map<UUID, Team> teams = new HashMap<>(); +// tournament.getTeams() +// .forEach(teamId -> { +// try { +// teams.put(teamId, teamRepository.findById(teamId) +// .orElseThrow(() -> new TournamentIdNotFoundException(teamId))); +// } catch (TournamentIdNotFoundException e) { +// log.debug("Team with id " + teamId + " not found"); +// } +// }); +// Map<UUID, TeamDTO> mappedTeams = teams.entrySet() +// .stream() +// .collect(Collectors.toMap(Entry::getKey, e -> mapToTeamDTO(e.getValue()))); +// return new TournamentDTO( +// tournament.getTournamentId(), +// tournament.getTournamentName(), +// mappedMatches, +// mappedTeams +// ); +// } public MatchDTO mapToMatchDTO(Match match) { return new MatchDTO( diff --git a/sth-backend/src/main/java/hdm/mi/sthbackend/model/BracketRound.java b/sth-backend/src/main/java/hdm/mi/sthbackend/model/BracketRound.java new file mode 100644 index 0000000000000000000000000000000000000000..1875694505bc1960d22d823ec74d0a69df459ea1 --- /dev/null +++ b/sth-backend/src/main/java/hdm/mi/sthbackend/model/BracketRound.java @@ -0,0 +1,19 @@ +package hdm.mi.sthbackend.model; + +import lombok.Getter; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.*; + +public class BracketRound { + private final Logger log = LogManager.getLogger("BracketRound"); + @Getter + Map<UUID, Match> matches; + int round; + + public BracketRound(int round){ + this.round = round; + matches = new HashMap<>(); + } +} diff --git a/sth-backend/src/main/java/hdm/mi/sthbackend/model/Match.java b/sth-backend/src/main/java/hdm/mi/sthbackend/model/Match.java index 8041fd19e362850a7ff37b73a8d0be30189d02ef..1eeecc5316d75ac8f9b7cfa69dc0179af90e90b1 100644 --- a/sth-backend/src/main/java/hdm/mi/sthbackend/model/Match.java +++ b/sth-backend/src/main/java/hdm/mi/sthbackend/model/Match.java @@ -8,18 +8,19 @@ import org.apache.logging.log4j.Logger; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; +import java.util.HashMap; import java.util.Map; import java.util.UUID; @Getter @Document("Match") -@AllArgsConstructor public class Match { private static final Logger log = LogManager.getLogger(Match.class); @Id private UUID matchId; + @Getter private Map<UUID, Integer> teamScores; @Setter @@ -30,4 +31,9 @@ public class Match { @Setter private UUID nextMatchId; + + public Match(UUID matchId){ + this.matchId = matchId; + this.teamScores = new HashMap<>(); + } } diff --git a/sth-backend/src/main/java/hdm/mi/sthbackend/model/Player.java b/sth-backend/src/main/java/hdm/mi/sthbackend/model/Player.java index ca124371f0686e555a38a8f95342f88c11dd070b..5044850dbe214ab08fd5f4d334664842e096353b 100644 --- a/sth-backend/src/main/java/hdm/mi/sthbackend/model/Player.java +++ b/sth-backend/src/main/java/hdm/mi/sthbackend/model/Player.java @@ -12,8 +12,10 @@ import java.util.UUID; @Document("Player") @AllArgsConstructor public class Player { + @Id private final UUID playerId; @Setter private String name; + } diff --git a/sth-backend/src/main/java/hdm/mi/sthbackend/model/Tournament.java b/sth-backend/src/main/java/hdm/mi/sthbackend/model/Tournament.java index 4012eb19f9db7dbe23ab8ec65ec630972f3b39d8..18356b42fc89db0b33583facd9d2140c1105950c 100644 --- a/sth-backend/src/main/java/hdm/mi/sthbackend/model/Tournament.java +++ b/sth-backend/src/main/java/hdm/mi/sthbackend/model/Tournament.java @@ -6,6 +6,7 @@ import lombok.Setter; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; @@ -18,8 +19,14 @@ public class Tournament implements ITournament{ private UUID tournamentId; @Setter private String tournamentName; - - private List<UUID> matches; - + @Setter + private List<BracketRound> bracket; private List<UUID> teams; + + public Tournament(String tournamentName, List<UUID> teams){ + this.tournamentId = UUID.randomUUID(); + this.tournamentName = tournamentName; + this.teams = teams; + this.bracket = new ArrayList<>(); + } } diff --git a/sth-backend/src/main/java/hdm/mi/sthbackend/service/TournamentService.java b/sth-backend/src/main/java/hdm/mi/sthbackend/service/TournamentService.java index 857ff616f35fefbb2b3b904dc6217e11fd1c7343..fadff0303c71dcdc2ff2b86f30a00b7de6821e2c 100644 --- a/sth-backend/src/main/java/hdm/mi/sthbackend/service/TournamentService.java +++ b/sth-backend/src/main/java/hdm/mi/sthbackend/service/TournamentService.java @@ -6,10 +6,7 @@ import hdm.mi.sthbackend.dto.TeamDTO; import hdm.mi.sthbackend.dto.TournamentDTO; import hdm.mi.sthbackend.exeptions.*; import hdm.mi.sthbackend.mapper.ModelToDTOMapper; -import hdm.mi.sthbackend.model.Match; -import hdm.mi.sthbackend.model.Player; -import hdm.mi.sthbackend.model.Team; -import hdm.mi.sthbackend.model.Tournament; +import hdm.mi.sthbackend.model.*; import hdm.mi.sthbackend.repository.IMatchRepository; import hdm.mi.sthbackend.repository.IPlayerRepository; import hdm.mi.sthbackend.repository.ITeamRepository; @@ -145,11 +142,10 @@ public class TournamentService { return teamId; } - public TournamentDTO createTournament(String tournamentName) { - Tournament tournament = new Tournament(UUID.randomUUID(), tournamentName, new ArrayList<>(), new ArrayList<>()); + public Tournament createTournament(Tournament tournament) { tournamentRepository.insert(tournament); log.debug("created Tournament " + tournament.getTournamentId()); - return mapper.mapToTournamentDTO(tournament); + return tournament; } public UUID determineWinner (UUID matchId) throws MatchIdNotFoundException, WinnerNotDeterminedException { @@ -166,13 +162,25 @@ public class TournamentService { return winnerTeamId; } - public MatchDTO assignTeamToMatch(UUID matchId, UUID teamId, int score) throws MatchIdNotFoundException { - Match match = matchRepository.findById(matchId).orElseThrow(() -> new MatchIdNotFoundException(matchId)); + public Tournament assignTeamToMatch(UUID tournamentId, int bracketRound, UUID matchId, UUID teamId, int score) throws TournamentIdNotFoundException, MatchIdNotFoundException { + Tournament tournament = tournamentRepository.findById(tournamentId) + .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId)); + try{ + tournament + .getBracket() + .get(bracketRound) + .getMatches() + .get(matchId) + .getTeamScores() + .put(teamId, score); + } + catch (Exception e){ + throw new MatchIdNotFoundException(matchId); + } - match.getTeamScores().put(teamId,score); - matchRepository.save(match); + tournamentRepository.save(tournament); log.debug("Team " + teamId + " assign to Match " + matchId ); - return mapper.mapToMatchDTO(match); + return tournament; } @@ -207,23 +215,79 @@ public class TournamentService { log.debug("Tournament Name for TournamentID " + tournamentId + " updated to " + newTournamentName); return tournamentId; } - public TournamentDTO getTournament(UUID tournamentId) throws TournamentIdNotFoundException { + public Tournament getTournament(UUID tournamentId) throws TournamentIdNotFoundException { Tournament tournament = tournamentRepository.findById(tournamentId) .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId)); log.debug(tournament + "is found"); - return mapper.mapToTournamentDTO(tournament); + return tournament; } - public TournamentDTO deleteTournament(UUID tournamentId) throws TournamentIdNotFoundException { + public Tournament deleteTournament(UUID tournamentId) throws TournamentIdNotFoundException { Tournament tournamentToDelete = tournamentRepository.findById(tournamentId) .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId)); tournamentRepository.delete(tournamentToDelete); log.debug("Tournament " + tournamentId + " has been deleted"); - return mapper.mapToTournamentDTO(tournamentToDelete); + return tournamentToDelete; + } + + public Tournament createBracket(UUID tournamentId) throws TournamentIdNotFoundException, InsufficientTeamsException, BracketAlreadyInitializedException{ + Tournament tournament = tournamentRepository.findById(tournamentId) + .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId)); + List<UUID> teams = tournament.getTeams(); + + if(teams.size() < 2){ + throw new InsufficientTeamsException(tournamentId); + } + + // log zur Basis 2 von der Anzahl der Teams (aufgerundet) + int roundCount = (int) Math.ceil(Math.log(teams.size()) / Math.log(2)); + + if(tournament.getBracket().size() == 0){ + tournament.setBracket(new ArrayList<>()); + for(int i = 0; i < roundCount; i++){ + // richtige Anzahl an BracketRounds hinzufügen + tournament.getBracket().add(new BracketRound(i)); + + // anzahl der matches errechnen + int matchCount = (int) (Math.pow(2, roundCount)) / (int) Math.pow(2, i + 1); + + for(int j = 0; j < matchCount; j++){ + // matches hinzufügen + UUID matchId = UUID.randomUUID(); + tournament.getBracket().get(i).getMatches().put(matchId, new Match(matchId)); + } + } + } + else{ + throw new BracketAlreadyInitializedException(tournamentId); + } + tournamentRepository.save(tournament); + return tournament; } + public Tournament fillBracketRandom(UUID tournamentId) throws TournamentIdNotFoundException { + Tournament tournament = tournamentRepository.findById(tournamentId) + .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId)); + List<UUID> teams = tournament.getTeams(); + + Random random = new Random(); + for(int i = 0; i < 2; i++){ + for(Match match: tournament.getBracket().get(0).getMatches().values()){ + if(teams.size() > 0){ + int teamIndex = random.nextInt(0, teams.size()); + match.getTeamScores().put(teams.get(teamIndex), 0); + teams.remove(teamIndex); + } + else{ + break; + } + } + } + tournamentRepository.save(tournament); + return tournament; + } /* Weitere Methoden: UpdateTeamScore Marius diff --git a/sth-backend/src/test/java/hdm/mi/sthbackend/TournamentControllerTest.java b/sth-backend/src/test/java/hdm/mi/sthbackend/TournamentControllerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7970142aa0f9cf7c6c4ec0bdba2075a1a7322a0f --- /dev/null +++ b/sth-backend/src/test/java/hdm/mi/sthbackend/TournamentControllerTest.java @@ -0,0 +1,80 @@ +package hdm.mi.sthbackend; + +import com.fasterxml.jackson.databind.ObjectMapper; +import hdm.mi.sthbackend.controller.TournamentController; +import hdm.mi.sthbackend.model.BracketRound; +import hdm.mi.sthbackend.model.Match; +import hdm.mi.sthbackend.model.Tournament; +import hdm.mi.sthbackend.repository.ITournamentRepository; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.ArrayList; +import java.util.Optional; +import java.util.UUID; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.mockito.Mockito.*; + +@SpringBootTest +@AutoConfigureMockMvc +@ExtendWith(MockitoExtension.class) +public class TournamentControllerTest { + private final Logger log = LogManager.getLogger("TournamentControllerTest"); + + @Mock + ITournamentRepository tournamentRepository; + @InjectMocks + TournamentController tournamentController; + @Autowired + public MockMvc mockMvc; + @Test + public void assignTeamToMatch() throws Exception { + + UUID tournamentId = UUID.randomUUID(); + UUID matchId = UUID.randomUUID(); + UUID teamId = UUID.randomUUID(); + Match match = new Match(matchId); + Tournament tournament = new Tournament("TestTournament", new ArrayList<>()); + tournament.getBracket().add(new BracketRound(0)); + tournament.getBracket().get(0).getMatches().put(matchId, match); + + when(tournamentRepository.findById(tournamentId)).thenReturn(Optional.of(tournament)); + + mockMvc.perform(patch("/tournaments/{tournamentId}/matches/{matchId}/teams/{teamId}/assignTeamToMatch", tournamentId, matchId, teamId) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"bracketRound\": 0, \"teamMatchScore\": 0}")) + .andExpect(status().isOk()); + + + verify(tournamentRepository, times(1)).findById(tournamentId); + verify(tournamentRepository, times(1)).save(tournament); + } + + @Test + public void createTournamentTest() throws Exception { + + UUID tournamentId = UUID.randomUUID(); + Tournament tournament = new Tournament("TestTournament", new ArrayList<>()); + when(tournamentRepository.findById(tournamentId)).thenReturn(Optional.of(tournament)); + + mockMvc.perform(post("/tournaments") + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(tournament))) + .andExpect(status().isOk()); + } +} diff --git a/sth-backend/src/test/java/hdm/mi/sthbackend/dummyObjects/dummyTournaments.java b/sth-backend/src/test/java/hdm/mi/sthbackend/dummyObjects/dummyTournaments.java new file mode 100644 index 0000000000000000000000000000000000000000..2d5c9ee56ad0233c90934f963d0e7c71bedf0712 --- /dev/null +++ b/sth-backend/src/test/java/hdm/mi/sthbackend/dummyObjects/dummyTournaments.java @@ -0,0 +1,48 @@ +package hdm.mi.sthbackend.dummyObjects; + +import hdm.mi.sthbackend.model.Tournament; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.UUID; + +public class dummyTournaments { + private final Logger log = LogManager.getLogger("dummyTournaments"); + public static UUID dummyTournamentId = UUID.randomUUID(); + + public static Tournament t1 = new Tournament(dummyTournamentId, "TestTournament", new ArrayList<>(), + new ArrayList<>(Arrays.asList( + UUID.randomUUID(), UUID.randomUUID()))); + public static Tournament t2 = new Tournament(dummyTournamentId, "TestTournament", new ArrayList<>(), + new ArrayList<>(Arrays.asList( + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()))); + public static Tournament t3 = new Tournament(dummyTournamentId, "TestTournament", new ArrayList<>(), + new ArrayList<>(Arrays.asList( + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()))); + public static Tournament t4 = new Tournament(dummyTournamentId, "TestTournament", new ArrayList<>(), + new ArrayList<>(Arrays.asList( + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()))); + public static Tournament t11 = new Tournament(dummyTournamentId, "TestTournament", new ArrayList<>(), + new ArrayList<>(Arrays.asList( + UUID.randomUUID()))); + public static Tournament t12 = new Tournament(dummyTournamentId, "TestTournament", new ArrayList<>(), + new ArrayList<>(Arrays.asList( + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()))); + public static Tournament t13 = new Tournament(dummyTournamentId, "TestTournament", new ArrayList<>(), + new ArrayList<>(Arrays.asList( + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), + UUID.randomUUID()))); + public static Tournament t14 = new Tournament(dummyTournamentId, "TestTournament", new ArrayList<>(), + new ArrayList<>(Arrays.asList( + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), + UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID()))); + +} diff --git a/sth-backend/src/test/java/hdm/mi/sthbackend/serviceTests/CreacteBracketTest.java b/sth-backend/src/test/java/hdm/mi/sthbackend/serviceTests/CreacteBracketTest.java new file mode 100644 index 0000000000000000000000000000000000000000..03fc5eaea90fd0f086008b70917eebffd977e17b --- /dev/null +++ b/sth-backend/src/test/java/hdm/mi/sthbackend/serviceTests/CreacteBracketTest.java @@ -0,0 +1,108 @@ +package hdm.mi.sthbackend.serviceTests; + +import hdm.mi.sthbackend.exeptions.BracketAlreadyInitializedException; +import hdm.mi.sthbackend.exeptions.InsufficientTeamsException; +import hdm.mi.sthbackend.exeptions.TournamentIdNotFoundException; +import hdm.mi.sthbackend.model.Tournament; +import hdm.mi.sthbackend.repository.ITournamentRepository; +import hdm.mi.sthbackend.service.TournamentService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static hdm.mi.sthbackend.dummyObjects.dummyTournaments.*; +import static org.mockito.Mockito.*; + +import java.util.Optional; + +@ExtendWith(MockitoExtension.class) +public class CreacteBracketTest { + + @Mock + public ITournamentRepository tournamentRepository; + @InjectMocks + public TournamentService tournamentService; + + private final Logger log = LogManager.getLogger("CreateBracketTest"); + + @Test + public void create2TeamBracketTest() throws TournamentIdNotFoundException, InsufficientTeamsException, BracketAlreadyInitializedException { + when(tournamentRepository.findById(dummyTournamentId)).thenReturn(Optional.of(t1)); + + Tournament resultTournament = tournamentService.createBracket(dummyTournamentId); + Assertions.assertEquals(1, resultTournament.getBracket().size()); + Assertions.assertEquals(1, resultTournament.getBracket().get(0).getMatches().size()); + } + @Test + public void create4TeamBracketTest() throws TournamentIdNotFoundException, InsufficientTeamsException, BracketAlreadyInitializedException { + when(tournamentRepository.findById(dummyTournamentId)).thenReturn(Optional.of(t2)); + + Tournament resultTournament = tournamentService.createBracket(dummyTournamentId); + Assertions.assertEquals(2, resultTournament.getBracket().size()); + Assertions.assertEquals(2, resultTournament.getBracket().get(0).getMatches().size()); + Assertions.assertEquals(1, resultTournament.getBracket().get(1).getMatches().size()); + } + @Test + public void create8TeamBracketTest() throws TournamentIdNotFoundException, InsufficientTeamsException, BracketAlreadyInitializedException { + when(tournamentRepository.findById(dummyTournamentId)).thenReturn(Optional.of(t3)); + + Tournament resultTournament = tournamentService.createBracket(dummyTournamentId); + Assertions.assertEquals(3, resultTournament.getBracket().size()); + Assertions.assertEquals(4, resultTournament.getBracket().get(0).getMatches().size()); + Assertions.assertEquals(2, resultTournament.getBracket().get(1).getMatches().size()); + Assertions.assertEquals(1, resultTournament.getBracket().get(2).getMatches().size()); + } + @Test + public void create16TeamBracketTest() throws TournamentIdNotFoundException, InsufficientTeamsException, BracketAlreadyInitializedException { + when(tournamentRepository.findById(dummyTournamentId)).thenReturn(Optional.of(t4)); + + Tournament resultTournament = tournamentService.createBracket(dummyTournamentId); + Assertions.assertEquals(4, resultTournament.getBracket().size()); + Assertions.assertEquals(8, resultTournament.getBracket().get(0).getMatches().size()); + Assertions.assertEquals(4, resultTournament.getBracket().get(1).getMatches().size()); + Assertions.assertEquals(2, resultTournament.getBracket().get(2).getMatches().size()); + Assertions.assertEquals(1, resultTournament.getBracket().get(3).getMatches().size()); + } + @Test + public void create1TeamBracketTest(){ + when(tournamentRepository.findById(dummyTournamentId)).thenReturn(Optional.of(t11)); + + Assertions.assertThrows(InsufficientTeamsException.class, () -> tournamentService.createBracket(dummyTournamentId)); + } + @Test + public void create3TeamBracketTest() throws TournamentIdNotFoundException, InsufficientTeamsException, BracketAlreadyInitializedException { + when(tournamentRepository.findById(dummyTournamentId)).thenReturn(Optional.of(t12)); + + Tournament resultTournament = tournamentService.createBracket(dummyTournamentId); + Assertions.assertEquals(2, resultTournament.getBracket().size()); + Assertions.assertEquals(2, resultTournament.getBracket().get(0).getMatches().size()); + Assertions.assertEquals(1, resultTournament.getBracket().get(1).getMatches().size()); + } + @Test + public void create5TeamBracketTest() throws TournamentIdNotFoundException, InsufficientTeamsException, BracketAlreadyInitializedException { + when(tournamentRepository.findById(dummyTournamentId)).thenReturn(Optional.of(t13)); + + Tournament resultTournament = tournamentService.createBracket(dummyTournamentId); + Assertions.assertEquals(3, resultTournament.getBracket().size()); + Assertions.assertEquals(4, resultTournament.getBracket().get(0).getMatches().size()); + Assertions.assertEquals(2, resultTournament.getBracket().get(1).getMatches().size()); + Assertions.assertEquals(1, resultTournament.getBracket().get(2).getMatches().size()); + } + @Test + public void create15TeamBracketTest() throws TournamentIdNotFoundException, InsufficientTeamsException, BracketAlreadyInitializedException { + when(tournamentRepository.findById(dummyTournamentId)).thenReturn(Optional.of(t14)); + + Tournament resultTournament = tournamentService.createBracket(dummyTournamentId); + Assertions.assertEquals(4, resultTournament.getBracket().size(), 4); + Assertions.assertEquals(8, resultTournament.getBracket().get(0).getMatches().size()); + Assertions.assertEquals(4, resultTournament.getBracket().get(1).getMatches().size()); + Assertions.assertEquals(2, resultTournament.getBracket().get(2).getMatches().size()); + Assertions.assertEquals(1, resultTournament.getBracket().get(3).getMatches().size()); + } + +} diff --git a/sth-backend/src/test/java/hdm/mi/sthbackend/serviceTests/FillBracketRandomTest.java b/sth-backend/src/test/java/hdm/mi/sthbackend/serviceTests/FillBracketRandomTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3819613135968f78551bf6ac135f27069dc41ff5 --- /dev/null +++ b/sth-backend/src/test/java/hdm/mi/sthbackend/serviceTests/FillBracketRandomTest.java @@ -0,0 +1,103 @@ +package hdm.mi.sthbackend.serviceTests; + +import hdm.mi.sthbackend.exeptions.TournamentIdNotFoundException; +import hdm.mi.sthbackend.model.BracketRound; +import hdm.mi.sthbackend.model.Match; +import hdm.mi.sthbackend.model.Tournament; +import hdm.mi.sthbackend.repository.ITournamentRepository; +import hdm.mi.sthbackend.service.TournamentService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.Optional; +import java.util.UUID; + +import static hdm.mi.sthbackend.dummyObjects.dummyTournaments.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class FillBracketRandomTest { + private final Logger log = LogManager.getLogger("FillBracketTest"); + + @Mock + ITournamentRepository tournamentRepository; + @InjectMocks + TournamentService tournamentService; + + + private Tournament createDummyBracketAndMatches(int rounds, Tournament tournament){ // + tournament.setBracket(new ArrayList<>()); + for (int i = 0; i < rounds; i++) { + tournament.getBracket().add(new BracketRound(i)); + for (int j = 0; j < (Math.pow(2,rounds) / Math.pow(2, i + 1)); j++) { + UUID matchId = UUID.randomUUID(); + tournament.getBracket().get(i).getMatches().put(matchId, new Match(matchId)); + } + } + return tournament; + } + + private int calculateTeamSum(Tournament tournament){ + return tournament.getBracket() + .stream() + .flatMap(bracketRound -> bracketRound.getMatches().values().stream()) + .map(match -> match.getTeamScores().size()) + .reduce(0, Integer::sum); + } + + @Test + public void fill2TeamBracketRandomTest() throws TournamentIdNotFoundException { + Tournament t1withMatches = createDummyBracketAndMatches(1, t1); + + when(tournamentRepository.findById(dummyTournamentId)).thenReturn(Optional.of(t1withMatches)); + Tournament t1Filled = tournamentService.fillBracketRandom(dummyTournamentId); + + int teamSum = calculateTeamSum(t1Filled); + + assertEquals(2,teamSum); + } + + @Test + public void fill4TeamBracketRandomTest() throws TournamentIdNotFoundException { + Tournament t2withMatches = createDummyBracketAndMatches(2, t2); + + when(tournamentRepository.findById(dummyTournamentId)).thenReturn(Optional.of(t2withMatches)); + Tournament t2Filled = tournamentService.fillBracketRandom(dummyTournamentId); + + int teamSum = calculateTeamSum(t2Filled); + + assertEquals(4,teamSum); + } + + @Test + public void fill8TeamBracketRandomTest() throws TournamentIdNotFoundException { + Tournament t3withMatches = createDummyBracketAndMatches(3, t3); + + when(tournamentRepository.findById(dummyTournamentId)).thenReturn(Optional.of(t3withMatches)); + Tournament t3Filled = tournamentService.fillBracketRandom(dummyTournamentId); + + int teamSum = calculateTeamSum(t3Filled); + + assertEquals(8,teamSum); + + } + + @Test + public void fill16TeamBracketRandomTest() throws TournamentIdNotFoundException { + Tournament t4withMatches = createDummyBracketAndMatches(4, t4); + + when(tournamentRepository.findById(dummyTournamentId)).thenReturn(Optional.of(t4withMatches)); + Tournament t4Filled = tournamentService.fillBracketRandom(dummyTournamentId); + + int teamSum = calculateTeamSum(t4Filled); + + assertEquals(16,teamSum); + } +} diff --git a/sth-backend/src/test/java/hdm/mi/sthbackend/t1.java b/sth-backend/src/test/java/hdm/mi/sthbackend/t1.java new file mode 100644 index 0000000000000000000000000000000000000000..c97e7c712aca73d1ccf7278822e0844b39450737 --- /dev/null +++ b/sth-backend/src/test/java/hdm/mi/sthbackend/t1.java @@ -0,0 +1,88 @@ +//package hdm.mi.sthbackend; +// +//import hdm.mi.sthbackend.controller.TournamentController; +//import hdm.mi.sthbackend.dto.MatchDTO; +//import hdm.mi.sthbackend.exeptions.MatchIdNotFoundException; +//import hdm.mi.sthbackend.mapper.ModelToDTOMapper; +//import hdm.mi.sthbackend.model.Match; +//import hdm.mi.sthbackend.repository.IMatchRepository; +//import hdm.mi.sthbackend.repository.IPlayerRepository; +//import hdm.mi.sthbackend.repository.ITeamRepository; +//import hdm.mi.sthbackend.repository.ITournamentRepository; +//import hdm.mi.sthbackend.service.TournamentService; +//import hdm.mi.sthbackend.types.TeamMatchScore; +//import org.junit.Before; +//import org.junit.Test; +//import org.junit.runner.RunWith; +//import org.mockito.InjectMocks; +//import org.mockito.Mock; +//import org.mockito.MockitoAnnotations; +//import org.mockito.junit.MockitoJUnitRunner; +//import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.http.MediaType; +//import org.springframework.test.web.servlet.MockMvc; +//import org.springframework.test.web.servlet.ResultActions; +//import org.springframework.beans.factory.annotation.Autowired; +//import java.util.HashMap; +//import java.util.Optional; +//import java.util.UUID; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.test.web.servlet.MockMvc; +//import org.springframework.test.web.servlet.setup.MockMvcBuilders; +// +// +//import static org.hamcrest.Matchers.is; +//import static org.mockito.ArgumentMatchers.any; +//import static org.mockito.Mockito.*; +//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; +//import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +//import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +//import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +// +//@AutoConfigureMockMvc +//@RunWith(MockitoJUnitRunner.class) +//@SpringBootTest +//public class t1 { +// +// @Mock +// private IMatchRepository matchRepository; +// +// @Mock +// private ITeamRepository teamRepository; +// +// @Mock +// private IPlayerRepository playerRepository; +// +// @Mock +// private ITournamentRepository tournamentRepository; +// +// @Mock +// private ModelToDTOMapper mapper; +// +// @InjectMocks +// private TournamentController tournamentController; +// +// @Autowired +// private MockMvc mockMvc; +// +// @Test +// public void assignTeamToMatch() throws Exception { +// UUID matchId = UUID.randomUUID(); +// +// MatchDTO testMatch = new MatchDTO(); +// testMatch.setTeamScores(new HashMap<>()); +// testMatch.setComment("Sample comment"); +// +// // Erstelle ein gültiges Match-Objekt für die Mock-Antwort +// Match mockMatch = new Match(matchId, new HashMap<>(), UUID.randomUUID(), "Some comment", UUID.randomUUID()); +// +// when(matchRepository.findById(matchId)).thenReturn(Optional.of(mockMatch)); +// when(mapper.mapToMatchDTO(any())).thenReturn(testMatch); +// +// +// verify(matchRepository, times(1)).findById(matchId); +// verify(matchRepository, times(1)).save(any()); +// verify(mapper, times(1)).mapToMatchDTO(any()); +// } +// } diff --git a/sth-frontend/.env b/sth-frontend/.env new file mode 100644 index 0000000000000000000000000000000000000000..a97bd7733774a0d552408b194bada84ba0847ac6 --- /dev/null +++ b/sth-frontend/.env @@ -0,0 +1,2 @@ +# .env + diff --git a/sth-frontend/.env.developement b/sth-frontend/.env.developement new file mode 100644 index 0000000000000000000000000000000000000000..3533d50c62f1f8c09861795dea1e6cd8398ea56e --- /dev/null +++ b/sth-frontend/.env.developement @@ -0,0 +1 @@ +VITE_BASE_URL=http://localhost:8080 \ No newline at end of file diff --git a/sth-frontend/.env.production b/sth-frontend/.env.production new file mode 100644 index 0000000000000000000000000000000000000000..3533d50c62f1f8c09861795dea1e6cd8398ea56e --- /dev/null +++ b/sth-frontend/.env.production @@ -0,0 +1 @@ +VITE_BASE_URL=http://localhost:8080 \ No newline at end of file diff --git a/sth-frontend/package-lock.json b/sth-frontend/package-lock.json index b67f2562ea56e35e5bd0e55519ae382fdbc825ce..9afe47756c44a61ab7f633f417b44e21cb01ff31 100644 --- a/sth-frontend/package-lock.json +++ b/sth-frontend/package-lock.json @@ -15,6 +15,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.20.1", + "tailwind-merge": "^2.2.0", "web-vitals": "^2.1.4" }, "devDependencies": { @@ -331,9 +332,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", - "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", + "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -3916,6 +3917,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tailwind-merge": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.2.0.tgz", + "integrity": "sha512-SqqhhaL0T06SW59+JVNfAqKdqLs0497esifRrZ7jOaefP3o64fdFNDMrAQWZFMxTLJPiHVjRLUywT8uFz1xNWQ==", + "dependencies": { + "@babel/runtime": "^7.23.5" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.0.tgz", @@ -4458,9 +4471,9 @@ } }, "@babel/runtime": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", - "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", + "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", "requires": { "regenerator-runtime": "^0.14.0" } @@ -6849,6 +6862,14 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "tailwind-merge": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.2.0.tgz", + "integrity": "sha512-SqqhhaL0T06SW59+JVNfAqKdqLs0497esifRrZ7jOaefP3o64fdFNDMrAQWZFMxTLJPiHVjRLUywT8uFz1xNWQ==", + "requires": { + "@babel/runtime": "^7.23.5" + } + }, "tailwindcss": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.0.tgz", diff --git a/sth-frontend/package.json b/sth-frontend/package.json index ae412db2840a642d56867df9daf6068f41554698..2681dc3f8c9a60384d704c22b657cd6fa68750ce 100644 --- a/sth-frontend/package.json +++ b/sth-frontend/package.json @@ -10,6 +10,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.20.1", + "tailwind-merge": "^2.2.0", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/sth-frontend/src/App.jsx b/sth-frontend/src/App.jsx index 44798e3def41b80c43e008ad69853579271fb8af..cd877e1cf671d69ec4559b8cf0d918cb366386b7 100644 --- a/sth-frontend/src/App.jsx +++ b/sth-frontend/src/App.jsx @@ -1,6 +1,7 @@ import Navbar from "./layouts/Navbar"; import {Outlet} from "react-router-dom"; import "./index.css" +import Button from "./components/Button"; function App() { return ( @@ -9,7 +10,7 @@ function App() { <div className={'p-6'}> <Outlet /> </div> - + <Button className={'bg-blue-500'}>Hello</Button> </> ); } diff --git a/sth-frontend/src/components/Button.jsx b/sth-frontend/src/components/Button.jsx new file mode 100644 index 0000000000000000000000000000000000000000..42ec094c97360120c88dc1fb53f115095b940d74 --- /dev/null +++ b/sth-frontend/src/components/Button.jsx @@ -0,0 +1,7 @@ +import {twMerge} from "tailwind-merge"; + +export default function Button({children, className, ...props}) { + return ( + <button {...props} className={twMerge('bg-red-400', className)}>{children}</button> + ) +} \ No newline at end of file diff --git a/sth-frontend/src/components/TournamentForm.jsx b/sth-frontend/src/components/TournamentForm.jsx index d66c5cc1b6a24d456d38cf3c455b05fb82bbd3f7..71962aa13563dfbbe010f64ce4fa5035236d9b74 100644 --- a/sth-frontend/src/components/TournamentForm.jsx +++ b/sth-frontend/src/components/TournamentForm.jsx @@ -1,18 +1,73 @@ +import {useRef, useState} from "react"; +import Button from "./Button"; +import {createTournament} from "../features/tournament/services"; -export default function TournamentForm(){ +export default function TournamentForm({setIsOpen}) { + + const [tournamentName, setTournamentName] = useState('') + const [teamName, setTeamName] = useState('') + const [teamNames, setTeamNames] = useState([]) + + + const handleOnChange = (event, set) => { + set(event.target.value); + + } + + const handleOnKeyDown = (event) => { + if (event.key === 'Enter') { + event.preventDefault() + setTeamNames([...teamNames, teamName]) + setTeamName(''); + } + } + const handleRemoveTeam = (index) => { + setTeamNames(teamNames.filter((teamName, i) => i !== index)) + } + + + const handleSubmit = async (event) => { + event.preventDefault() + const tournament = { + name: tournamentName, + teams: teamNames + } + try { + await createTournament(tournament) + setIsOpen(false); + setTournamentName('') + setTeamName('') + setTeamNames([]) + } catch (e) { + + } + + } return ( - <form className={'flex flex-col'}> - <label htmlFor='tName'>Tournament Name</label> - <input type='text' id='tName'/> - <label htmlFor='teamCount'>Player Count</label> - <input type='number' id='teamCount'/> - <label htmlFor='tournamentType'>Tournament Type</label> - <select id='tournamentType'> - <option value='bracketing'>Bracketing</option> - </select> - <input type='submit'/> - </form> + <div className={'w-[40vw]'}> + <button className={'absolute top-0 right-0 m-1'} + onClick={() => setIsOpen(false)}>❌ + </button> + <form className={'flex flex-col'} onSubmit={handleSubmit}> + <label htmlFor='tournamentName'>Tournament Name</label> + <input type='text' id='tournamentName' value={tournamentName} + onChange={(event) => handleOnChange(event, setTournamentName)}/> + <label htmlFor='teamNames'>Team Name</label> + <input type='text' id='teamNames' value={teamName} + onChange={(event) => handleOnChange(event, setTeamName)} + onKeyDown={handleOnKeyDown}/> + <input className={'bg-green-700'} type='submit'/> + <ul> + {teamNames.map((teamName, index) => <li key={index}> + <div> + {teamName} + <Button onClick={() => handleRemoveTeam(index)}>Remove</Button> + </div> + </li>)} + </ul> + </form> + </div> ) -} \ No newline at end of file +} diff --git a/sth-frontend/src/features/tournament/components/BracketingRound.jsx b/sth-frontend/src/features/tournament/components/BracketingRound.jsx index b20d07cadd565f0074a5a9d2bd94be21d671cabc..ccac084577b284d3cedc9c74d79285cd480be367 100644 --- a/sth-frontend/src/features/tournament/components/BracketingRound.jsx +++ b/sth-frontend/src/features/tournament/components/BracketingRound.jsx @@ -4,8 +4,7 @@ export default function BracketingRound({matchesNum}) { const matches = []; for (let i = 0; i < matchesNum; i++) { - matches.push(<Match style={i + 1} key={i} />) - + matches.push(<Match style={i + 1} key={i}/>); } return( diff --git a/sth-frontend/src/features/tournament/services/index.js b/sth-frontend/src/features/tournament/services/index.js new file mode 100644 index 0000000000000000000000000000000000000000..3706bcd0216f974284d94425e2c8d1364c877e31 --- /dev/null +++ b/sth-frontend/src/features/tournament/services/index.js @@ -0,0 +1,2 @@ + +export { createTournament } from './tournamentService'; \ No newline at end of file diff --git a/sth-frontend/src/features/tournament/services/tournamentService.js b/sth-frontend/src/features/tournament/services/tournamentService.js new file mode 100644 index 0000000000000000000000000000000000000000..fd02f1168aed0fc127f5d6b2b45691ff3a771301 --- /dev/null +++ b/sth-frontend/src/features/tournament/services/tournamentService.js @@ -0,0 +1,28 @@ +async function createTournament(tournament) { + + const baseURL = import.meta.env.BASE_URL; + const url = `${baseURL}/api/v1/tournaments/`; + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + + }, + body: JSON.stringify(tournament), + mode: 'cors', + credentials: 'include' + }; + + try { + console.log('fetching'); + const response = await fetch(url, options); + + if (!response.ok) { + throw new HttpResponseError('Bad fetch', response); + } + } catch (error) { + throw error; + } +} + +export { createTournament }; diff --git a/sth-frontend/src/layouts/Navbar.jsx b/sth-frontend/src/layouts/Navbar.jsx index 71f7374ef12a4a440bbe2c002dca00983f8f809e..dc6654418a7a0e84533d3d74fc5181a5322834a4 100644 --- a/sth-frontend/src/layouts/Navbar.jsx +++ b/sth-frontend/src/layouts/Navbar.jsx @@ -6,16 +6,14 @@ import TournamentForm from "../components/TournamentForm"; export default function Navbar() { const [isOpen, setIsOpen] = useState(false) + if (true) { + + } return ( <nav className="flex items-center justify-end h-14 bg-gray-100 fixed w-full top-0 left-0 z-10 hover:shadow duration-100"> <Modal isOpen={isOpen} onClose={() => setIsOpen(false)}> - <div className={'w-[40vw]'}> - <button className={'absolute top-0 right-0 m-1'} - onClick={() => setIsOpen(false)}>❌ - </button> - <TournamentForm /> - </div> + <TournamentForm setIsOpen={setIsOpen}/> </Modal> <div className={'mr-12'}> <ul className="flex justify-evenly items-center w-full h-full text-gray-400"> @@ -32,5 +30,5 @@ export default function Navbar() { </ul> </div> </nav> - ) + ); } \ No newline at end of file diff --git a/sth-frontend/src/utils/errors/httpResponseError.js b/sth-frontend/src/utils/errors/httpResponseError.js new file mode 100644 index 0000000000000000000000000000000000000000..16ab9b11dc4836504b7c83f8b7a50b360db6a87a --- /dev/null +++ b/sth-frontend/src/utils/errors/httpResponseError.js @@ -0,0 +1,7 @@ + +class HttpResponseError extends Error { + constructor(message, response) { + super(message); + this.response = response; + } +} \ No newline at end of file