From 5ea5b322938ea809fb7b2b5534777548c82fed97 Mon Sep 17 00:00:00 2001 From: svifty7 Date: Tue, 24 Dec 2024 23:36:24 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=82=20=D0=BE=D1=82?= =?UTF-8?q?=D0=B2=D0=B5=D1=82=D0=B0=20=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BE?= =?UTF-8?q?=D1=87=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tools/dictionary/DirectoryController.java | 270 ++++++++++++++++-- .../dnd5/dto/select/DiceSelectOptionDto.java | 22 ++ .../ttg/dnd5/dto/select/SelectOptionDto.java | 29 ++ .../select/SpellcasterSelectOptionDto.java | 19 ++ .../dnd5/service/base/DirectoryService.java | 83 +++--- 5 files changed, 353 insertions(+), 70 deletions(-) create mode 100644 src/main/java/club/ttg/dnd5/dto/select/DiceSelectOptionDto.java create mode 100644 src/main/java/club/ttg/dnd5/dto/select/SelectOptionDto.java create mode 100644 src/main/java/club/ttg/dnd5/dto/select/SpellcasterSelectOptionDto.java diff --git a/src/main/java/club/ttg/dnd5/controller/tools/dictionary/DirectoryController.java b/src/main/java/club/ttg/dnd5/controller/tools/dictionary/DirectoryController.java index fd7ec79d..e341e5b5 100644 --- a/src/main/java/club/ttg/dnd5/controller/tools/dictionary/DirectoryController.java +++ b/src/main/java/club/ttg/dnd5/controller/tools/dictionary/DirectoryController.java @@ -1,8 +1,14 @@ package club.ttg.dnd5.controller.tools.dictionary; -import club.ttg.dnd5.dto.base.ValueDto; +import club.ttg.dnd5.dto.select.DiceSelectOptionDto; +import club.ttg.dnd5.dto.select.SelectOptionDto; +import club.ttg.dnd5.dto.select.SpellcasterSelectOptionDto; import club.ttg.dnd5.service.base.DirectoryService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; @@ -16,68 +22,294 @@ */ @RequiredArgsConstructor @Tag(name = "Справочники", description = "API для различных справочников") -@RequestMapping("/api/v2/directory/") +@RequestMapping("/api/v2/directory") @RestController public class DirectoryController { private final DirectoryService directoryService; @Operation(summary = "Дайсы") @GetMapping("/dices") - public Collection getDices() { + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = @Content(mediaType = "application/json", + examples = @ExampleObject(""" + [ + { + "label": "к4", + "value": "d4", + "maxValue": 4 + }, + { + "label": "к6", + "value": "d6", + "maxValue": 6 + }, + { + "label": "к8", + "value": "d8", + "maxValue": 8 + } + ] + """) + ) + ) + } + ) + public Collection getDices() { return directoryService.getDices(); } @Operation(summary = "Типы существ") - @GetMapping("/beast/types") - public Collection getCreatureCategories() { + @GetMapping("/creature/types") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = @Content(mediaType = "application/json", + examples = @ExampleObject(""" + [ + { + "label": "Аберрация", + "value": "ABERRATION" + }, + { + "label": "Зверь", + "value": "BEAST" + }, + { + "label": "Небожитель", + "value": "CELESTIAL" + } + ] + """) + ) + ) + } + ) + public Collection getCreatureCategories() { return directoryService.getCreatureCategories(); } + @Operation(summary = "Размеры существ") @GetMapping("/sizes") - public Collection getCreatureSizes() { + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = @Content(mediaType = "application/json", + examples = @ExampleObject(""" + [ + { + "label": "Маленький", + "value": "SMALL" + }, + { + "label": "Средний", + "value": "MEDIUM" + }, + { + "label": "Большой", + "value": "LARGE" + } + ] + """) + ) + ) + } + ) + public Collection getCreatureSizes() { return directoryService.getCreatureSizes(); } @Operation(summary = "Типы урона") @GetMapping("/damage/types") - public Collection getDamageTypes() { + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = @Content(mediaType = "application/json", + examples = @ExampleObject(""" + [ + { + "label": "огонь", + "value": "FAIR" + }, + { + "label": "холод", + "value": "COLD" + }, + { + "label": "электричество", + "value": "LIGHTNING" + } + ] + """) + ) + ) + } + ) + public Collection getDamageTypes() { return directoryService.getDamageTypes(); } @Operation(summary = "Состояния") @GetMapping("/conditions") - public Collection getConditions() { + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = @Content(mediaType = "application/json", + examples = @ExampleObject(""" + [ + { + "label": "ослепление", + "value": "BLINDED" + }, + { + "label": "очарование", + "value": "CHARMED" + }, + { + "label": "смерть", + "value": "DYING" + } + ] + """) + ) + ) + } + ) + public Collection getConditions() { return directoryService.getConditions(); } @Operation(summary = "Мировоззрение") @GetMapping("/alignments") - public Collection getAlignments() { + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = @Content(mediaType = "application/json", + examples = @ExampleObject(""" + [ + { + "label": "законно-добрый", + "value": "LAWFUL_GOOD" + }, + { + "label": "законно-нейтральный", + "value": "LAWFUL_NEUTRAL" + }, + { + "label": "законно-злой", + "value": "LAWFUL_EVIL" + } + ] + """) + ) + ) + } + ) + public Collection getAlignments() { return directoryService.getAlignments(); } @Operation(summary = "Места обитания существ") @GetMapping("/environments") - public Collection getEnvironments() { + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = @Content(mediaType = "application/json", + examples = @ExampleObject(""" + [ + { + "label": "полярная тундра", + "value": "ARCTIC" + }, + { + "label": "побережье", + "value": "COAST" + }, + { + "label": "под водой", + "value": "WATERS" + } + ] + """) + ) + ) + } + ) + public Collection getEnvironments() { return directoryService.getEnvironments(); } @Operation(summary = "Типы черт") - @GetMapping("/type/feats") - public Collection getFeatTypes() { + @GetMapping("/feat/types") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = @Content(mediaType = "application/json", + examples = @ExampleObject(""" + [ + { + "label": "черты происхождения", + "value": "ORIGIN" + }, + { + "label": "общие черты", + "value": "GENERAL" + }, + { + "label": "эпические черты", + "value": "EPIC_BOON" + } + ] + """) + ) + ) + } + ) + public Collection getFeatTypes() { return directoryService.getFeatTypes(); } @Operation(summary = "Типы заклинателей") @GetMapping("/spellcaster/types") - public Collection getSpellcasterTypes() { + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = @Content(mediaType = "application/json", + examples = @ExampleObject(""" + [ + { + "label": "полный заклинатель", + "value": "FULL", + "levels": 9 + }, + { + "label": "половинный заклинатель", + "value": "HALF", + "levels": 5 + }, + { + "label": "частичный заклинатель", + "value": "PARTLY", + "levels": 4 + } + ] + """) + ) + ) + } + ) + public Collection getSpellcasterTypes() { return directoryService.getSpellcasterTypes(); } - - @Operation(summary = "Типы черт") - @GetMapping("/feat/types") - public Collection getFeatTypesSpellcasterTypes() { - return directoryService.getFeatTypesSpellcasterTypes(); - } } diff --git a/src/main/java/club/ttg/dnd5/dto/select/DiceSelectOptionDto.java b/src/main/java/club/ttg/dnd5/dto/select/DiceSelectOptionDto.java new file mode 100644 index 00000000..781f7a30 --- /dev/null +++ b/src/main/java/club/ttg/dnd5/dto/select/DiceSelectOptionDto.java @@ -0,0 +1,22 @@ +package club.ttg.dnd5.dto.select; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.SuperBuilder; + +@Getter +@Setter +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class DiceSelectOptionDto extends SelectOptionDto { + @Schema( + example = "9", + description = "Максимальное значение на кубе", + requiredMode = Schema.RequiredMode.REQUIRED + ) + private int maxValue; +} diff --git a/src/main/java/club/ttg/dnd5/dto/select/SelectOptionDto.java b/src/main/java/club/ttg/dnd5/dto/select/SelectOptionDto.java new file mode 100644 index 00000000..e6168cd8 --- /dev/null +++ b/src/main/java/club/ttg/dnd5/dto/select/SelectOptionDto.java @@ -0,0 +1,29 @@ +package club.ttg.dnd5.dto.select; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import lombok.experimental.SuperBuilder; + +/** + * Описывает один пункт в выпадающем списке. + */ +@Getter +@Setter +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class SelectOptionDto { + @Schema( + example = "Средний", + description = "Отображаемое имя. В выпадающих списках используется для человекочитаемого текста.", + requiredMode = Schema.RequiredMode.REQUIRED + ) + private String label; + + @Schema( + example = "MEDIUM", + description = "Используемое значение. Передается в запросах на API, например, при создании вида.", + requiredMode = Schema.RequiredMode.REQUIRED + ) + private String value; +} diff --git a/src/main/java/club/ttg/dnd5/dto/select/SpellcasterSelectOptionDto.java b/src/main/java/club/ttg/dnd5/dto/select/SpellcasterSelectOptionDto.java new file mode 100644 index 00000000..2f7c532d --- /dev/null +++ b/src/main/java/club/ttg/dnd5/dto/select/SpellcasterSelectOptionDto.java @@ -0,0 +1,19 @@ +package club.ttg.dnd5.dto.select; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import lombok.experimental.SuperBuilder; + +@Getter +@Setter +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class SpellcasterSelectOptionDto extends SelectOptionDto { + @Schema( + example = "9", + description = "Количество доступных кругов заклинаний", + requiredMode = Schema.RequiredMode.REQUIRED + ) + private int levels; +} diff --git a/src/main/java/club/ttg/dnd5/service/base/DirectoryService.java b/src/main/java/club/ttg/dnd5/service/base/DirectoryService.java index 4e61a76f..302453b5 100644 --- a/src/main/java/club/ttg/dnd5/service/base/DirectoryService.java +++ b/src/main/java/club/ttg/dnd5/service/base/DirectoryService.java @@ -9,8 +9,9 @@ import club.ttg.dnd5.dictionary.beastiary.Environment; import club.ttg.dnd5.dictionary.character.FeatCategory; import club.ttg.dnd5.dictionary.character.SpellcasterType; -import club.ttg.dnd5.dto.base.NameBasedDTO; -import club.ttg.dnd5.dto.base.ValueDto; +import club.ttg.dnd5.dto.select.DiceSelectOptionDto; +import club.ttg.dnd5.dto.select.SelectOptionDto; +import club.ttg.dnd5.dto.select.SpellcasterSelectOptionDto; import org.springframework.stereotype.Service; import java.util.Arrays; @@ -19,92 +20,72 @@ @Service public class DirectoryService { - private NameBasedDTO createNameBasedDTO(String rus, String eng) { - return NameBasedDTO.builder() - .name(rus) - .english(eng) + private SelectOptionDto createSelectOptionDTO(String label, String value) { + return SelectOptionDto.builder() + .label(label) + .value(value) .build(); } - public Collection getDices() { + public Collection getDices() { return Arrays.stream(Dice.values()) - .map(type -> ValueDto.builder() - .name(createNameBasedDTO(type.getName(), type.name())) - .value(type.getMaxValue()) + .map(type -> DiceSelectOptionDto.builder() + .label(type.getName()) + .value(type.name()) + .maxValue(type.getMaxValue()) .build()) .collect(Collectors.toList()); } - public Collection getCreatureCategories() { + public Collection getCreatureCategories() { return Arrays.stream(CreatureType.values()) - .map(type -> ValueDto.builder() - .name(createNameBasedDTO(type.getCyrillicName(), type.name())) - .build()) + .map(type -> createSelectOptionDTO(type.getCyrillicName(), type.name())) .collect(Collectors.toList()); } - public Collection getCreatureSizes() { + public Collection getCreatureSizes() { return Arrays.stream(Size.values()) - .map(size -> ValueDto.builder() - .name(createNameBasedDTO(size.getName(), size.name())) - .build()) + .map(size -> createSelectOptionDTO(size.getName(), size.name())) .collect(Collectors.toList()); } - public Collection getDamageTypes() { + public Collection getDamageTypes() { return Arrays.stream(DamageType.values()) - .map(type -> ValueDto.builder() - .name(createNameBasedDTO(type.getCyrillicName(), type.name())) - .build()) + .map(type -> createSelectOptionDTO(type.getCyrillicName(), type.name())) .collect(Collectors.toList()); } - public Collection getConditions() { + public Collection getConditions() { return Arrays.stream(Condition.values()) - .map(type -> ValueDto.builder() - .name(createNameBasedDTO(type.getCyrillicName(), type.name())) - .build()) + .map(type -> createSelectOptionDTO(type.getCyrillicName(), type.name())) .collect(Collectors.toList()); } - public Collection getAlignments() { + public Collection getAlignments() { return Arrays.stream(Alignment.values()) - .map(type -> ValueDto.builder() - .name(createNameBasedDTO(type.getName(), type.name())) - .build()) + .map(type -> createSelectOptionDTO(type.getName(), type.name())) .collect(Collectors.toList()); } - public Collection getEnvironments() { + public Collection getEnvironments() { return Arrays.stream(Environment.values()) - .map(type -> ValueDto.builder() - .name(createNameBasedDTO(type.getName(), type.name())) - .build()) + .map(type -> createSelectOptionDTO(type.getName(), type.name())) .collect(Collectors.toList()); } - public Collection getFeatTypes() { + public Collection getFeatTypes() { return Arrays.stream(FeatCategory.values()) - .map(type -> ValueDto.builder() - .name(createNameBasedDTO(type.getName(), type.name())) - .build()) + .map(type -> createSelectOptionDTO(type.getName(), type.name())) .collect(Collectors.toList()); } - public Collection getSpellcasterTypes() { + public Collection getSpellcasterTypes() { return Arrays.stream(SpellcasterType.values()) - .map(type -> ValueDto.builder() - .name(createNameBasedDTO(type.getName(), type.name())) - .value(type.getMaxSpellLevel()) - .build()) - .collect(Collectors.toList()); - } - - public Collection getFeatTypesSpellcasterTypes() { - return Arrays.stream(FeatCategory.values()) - .map(type -> ValueDto.builder() - .name(createNameBasedDTO(type.getName(), type.name())) + .map(type -> SpellcasterSelectOptionDto.builder() + .label(type.getName()) + .value(type.name()) + .levels(type.getMaxSpellLevel()) .build()) .collect(Collectors.toList()); } -} \ No newline at end of file +}