From 400eb896b1f6e1784ac16d2609baac6d5ed24cfb Mon Sep 17 00:00:00 2001 From: Wain <102559365+alterdekim@users.noreply.github.com> Date: Sun, 11 Feb 2024 15:14:28 +0300 Subject: [PATCH] Reupload --- README.md | 7 + pom.xml | 113 ++++ .../com/alterdekim/javabot/Application.java | 25 + .../java/com/alterdekim/javabot/Commands.java | 10 + .../com/alterdekim/javabot/Constants.java | 54 ++ .../javabot/FileServerController.java | 41 ++ .../com/alterdekim/javabot/Initializer.java | 28 + .../com/alterdekim/javabot/MvcConfig.java | 41 ++ .../alterdekim/javabot/TelegramConfig.java | 16 + .../bot/BotAccountProfileGenerator.java | 30 + .../javabot/bot/DayNightFields.java | 31 ++ .../alterdekim/javabot/bot/InfoSections.java | 24 + .../alterdekim/javabot/bot/LiveFormula.java | 81 +++ .../com/alterdekim/javabot/bot/Player.java | 29 + .../javabot/components/BunkerBot.java | 513 ++++++++++++++++++ .../javabot/controller/AuthController.java | 75 +++ .../controller/DatabaseController.java | 312 +++++++++++ .../javabot/controller/PanelController.java | 175 ++++++ .../alterdekim/javabot/dto/SynergyResult.java | 18 + .../com/alterdekim/javabot/dto/UserDTO.java | 23 + .../javabot/entities/AdditionalFacts.java | 37 ++ .../com/alterdekim/javabot/entities/Bio.java | 42 ++ .../javabot/entities/ColumnType.java | 9 + .../alterdekim/javabot/entities/Disaster.java | 31 ++ .../javabot/entities/GameStats.java | 38 ++ .../alterdekim/javabot/entities/Games.java | 39 ++ .../alterdekim/javabot/entities/Health.java | 43 ++ .../alterdekim/javabot/entities/Hobby.java | 51 ++ .../alterdekim/javabot/entities/Invite.java | 22 + .../alterdekim/javabot/entities/Luggage.java | 61 +++ .../com/alterdekim/javabot/entities/Role.java | 28 + .../alterdekim/javabot/entities/Synergy.java | 42 ++ .../javabot/entities/TextDataVal.java | 28 + .../com/alterdekim/javabot/entities/User.java | 39 ++ .../com/alterdekim/javabot/entities/Work.java | 55 ++ .../handler/CustomAccessDeniedHandler.java | 15 + .../repository/AdditionalFactsRepository.java | 13 + .../javabot/repository/BioRepository.java | 19 + .../repository/DisasterRepository.java | 13 + .../javabot/repository/HealthRepository.java | 19 + .../javabot/repository/HobbyRepository.java | 19 + .../javabot/repository/InviteRepository.java | 10 + .../javabot/repository/LuggageRepository.java | 19 + .../javabot/repository/RoleRepository.java | 12 + .../javabot/repository/SynergyRepository.java | 13 + .../repository/TextDataValRepository.java | 10 + .../javabot/repository/UserRepository.java | 11 + .../javabot/repository/WorkRepository.java | 19 + .../javabot/security/SpringSecurity.java | 77 +++ .../service/AdditionalFactsService.java | 10 + .../service/AdditionalFactsServiceImpl.java | 27 + .../javabot/service/BioService.java | 17 + .../javabot/service/BioServiceImpl.java | 43 ++ .../service/CustomUserDetailsService.java | 43 ++ .../javabot/service/DisasterService.java | 14 + .../javabot/service/DisasterServiceImpl.java | 37 ++ .../javabot/service/HealthService.java | 17 + .../javabot/service/HealthServiceImpl.java | 43 ++ .../javabot/service/HobbyService.java | 17 + .../javabot/service/HobbyServiceImpl.java | 43 ++ .../javabot/service/InviteService.java | 7 + .../javabot/service/InviteServiceImpl.java | 20 + .../javabot/service/LuggageService.java | 17 + .../javabot/service/LuggageServiceImpl.java | 43 ++ .../javabot/service/SynergyService.java | 14 + .../javabot/service/SynergyServiceImpl.java | 32 ++ .../javabot/service/TextDataValService.java | 12 + .../service/TextDataValServiceImpl.java | 32 ++ .../javabot/service/UserService.java | 14 + .../javabot/service/UserServiceImpl.java | 67 +++ .../javabot/service/WorkService.java | 17 + .../javabot/service/WorkServiceImpl.java | 43 ++ .../storage/FileSystemStorageService.java | 106 ++++ .../javabot/storage/StorageException.java | 13 + .../storage/StorageFileNotFoundException.java | 12 + .../javabot/storage/StorageProperties.java | 13 + .../javabot/storage/StorageService.java | 23 + .../com/alterdekim/javabot/util/BotUtils.java | 99 ++++ .../com/alterdekim/javabot/util/Clamp.java | 7 + .../alterdekim/javabot/util/GameState.java | 7 + .../alterdekim/javabot/util/HashUtils.java | 59 ++ .../alterdekim/javabot/util/PseudoRandom.java | 27 + .../alterdekim/javabot/util/UAgentInfo.java | 490 +++++++++++++++++ src/main/resources/messages_en.properties | 57 ++ src/main/resources/messages_ru.properties | 57 ++ src/main/resources/static/css/panel.css | 4 + src/main/resources/static/css/sign-in.css | 25 + src/main/resources/static/css/sign-up.css | 13 + src/main/resources/static/css/util.css | 8 + .../static/javascript/color-modes.js | 80 +++ .../static/javascript/panel-script.js | 256 +++++++++ .../resources/templates/access-denied.html | 19 + .../templates/fragments/floating_button.html | 50 ++ .../resources/templates/fragments/footer.html | 5 + .../resources/templates/fragments/header.html | 87 +++ src/main/resources/templates/login.html | 46 ++ src/main/resources/templates/panel.html | 309 +++++++++++ src/main/resources/templates/signup.html | 51 ++ 98 files changed, 5032 insertions(+) create mode 100644 README.md create mode 100644 pom.xml create mode 100644 src/main/java/com/alterdekim/javabot/Application.java create mode 100644 src/main/java/com/alterdekim/javabot/Commands.java create mode 100644 src/main/java/com/alterdekim/javabot/Constants.java create mode 100644 src/main/java/com/alterdekim/javabot/FileServerController.java create mode 100644 src/main/java/com/alterdekim/javabot/Initializer.java create mode 100644 src/main/java/com/alterdekim/javabot/MvcConfig.java create mode 100644 src/main/java/com/alterdekim/javabot/TelegramConfig.java create mode 100644 src/main/java/com/alterdekim/javabot/bot/BotAccountProfileGenerator.java create mode 100644 src/main/java/com/alterdekim/javabot/bot/DayNightFields.java create mode 100644 src/main/java/com/alterdekim/javabot/bot/InfoSections.java create mode 100644 src/main/java/com/alterdekim/javabot/bot/LiveFormula.java create mode 100644 src/main/java/com/alterdekim/javabot/bot/Player.java create mode 100644 src/main/java/com/alterdekim/javabot/components/BunkerBot.java create mode 100644 src/main/java/com/alterdekim/javabot/controller/AuthController.java create mode 100644 src/main/java/com/alterdekim/javabot/controller/DatabaseController.java create mode 100644 src/main/java/com/alterdekim/javabot/controller/PanelController.java create mode 100644 src/main/java/com/alterdekim/javabot/dto/SynergyResult.java create mode 100644 src/main/java/com/alterdekim/javabot/dto/UserDTO.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/AdditionalFacts.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/Bio.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/ColumnType.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/Disaster.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/GameStats.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/Games.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/Health.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/Hobby.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/Invite.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/Luggage.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/Role.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/Synergy.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/TextDataVal.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/User.java create mode 100644 src/main/java/com/alterdekim/javabot/entities/Work.java create mode 100644 src/main/java/com/alterdekim/javabot/handler/CustomAccessDeniedHandler.java create mode 100644 src/main/java/com/alterdekim/javabot/repository/AdditionalFactsRepository.java create mode 100644 src/main/java/com/alterdekim/javabot/repository/BioRepository.java create mode 100644 src/main/java/com/alterdekim/javabot/repository/DisasterRepository.java create mode 100644 src/main/java/com/alterdekim/javabot/repository/HealthRepository.java create mode 100644 src/main/java/com/alterdekim/javabot/repository/HobbyRepository.java create mode 100644 src/main/java/com/alterdekim/javabot/repository/InviteRepository.java create mode 100644 src/main/java/com/alterdekim/javabot/repository/LuggageRepository.java create mode 100644 src/main/java/com/alterdekim/javabot/repository/RoleRepository.java create mode 100644 src/main/java/com/alterdekim/javabot/repository/SynergyRepository.java create mode 100644 src/main/java/com/alterdekim/javabot/repository/TextDataValRepository.java create mode 100644 src/main/java/com/alterdekim/javabot/repository/UserRepository.java create mode 100644 src/main/java/com/alterdekim/javabot/repository/WorkRepository.java create mode 100644 src/main/java/com/alterdekim/javabot/security/SpringSecurity.java create mode 100644 src/main/java/com/alterdekim/javabot/service/AdditionalFactsService.java create mode 100644 src/main/java/com/alterdekim/javabot/service/AdditionalFactsServiceImpl.java create mode 100644 src/main/java/com/alterdekim/javabot/service/BioService.java create mode 100644 src/main/java/com/alterdekim/javabot/service/BioServiceImpl.java create mode 100644 src/main/java/com/alterdekim/javabot/service/CustomUserDetailsService.java create mode 100644 src/main/java/com/alterdekim/javabot/service/DisasterService.java create mode 100644 src/main/java/com/alterdekim/javabot/service/DisasterServiceImpl.java create mode 100644 src/main/java/com/alterdekim/javabot/service/HealthService.java create mode 100644 src/main/java/com/alterdekim/javabot/service/HealthServiceImpl.java create mode 100644 src/main/java/com/alterdekim/javabot/service/HobbyService.java create mode 100644 src/main/java/com/alterdekim/javabot/service/HobbyServiceImpl.java create mode 100644 src/main/java/com/alterdekim/javabot/service/InviteService.java create mode 100644 src/main/java/com/alterdekim/javabot/service/InviteServiceImpl.java create mode 100644 src/main/java/com/alterdekim/javabot/service/LuggageService.java create mode 100644 src/main/java/com/alterdekim/javabot/service/LuggageServiceImpl.java create mode 100644 src/main/java/com/alterdekim/javabot/service/SynergyService.java create mode 100644 src/main/java/com/alterdekim/javabot/service/SynergyServiceImpl.java create mode 100644 src/main/java/com/alterdekim/javabot/service/TextDataValService.java create mode 100644 src/main/java/com/alterdekim/javabot/service/TextDataValServiceImpl.java create mode 100644 src/main/java/com/alterdekim/javabot/service/UserService.java create mode 100644 src/main/java/com/alterdekim/javabot/service/UserServiceImpl.java create mode 100644 src/main/java/com/alterdekim/javabot/service/WorkService.java create mode 100644 src/main/java/com/alterdekim/javabot/service/WorkServiceImpl.java create mode 100644 src/main/java/com/alterdekim/javabot/storage/FileSystemStorageService.java create mode 100644 src/main/java/com/alterdekim/javabot/storage/StorageException.java create mode 100644 src/main/java/com/alterdekim/javabot/storage/StorageFileNotFoundException.java create mode 100644 src/main/java/com/alterdekim/javabot/storage/StorageProperties.java create mode 100644 src/main/java/com/alterdekim/javabot/storage/StorageService.java create mode 100644 src/main/java/com/alterdekim/javabot/util/BotUtils.java create mode 100644 src/main/java/com/alterdekim/javabot/util/Clamp.java create mode 100644 src/main/java/com/alterdekim/javabot/util/GameState.java create mode 100644 src/main/java/com/alterdekim/javabot/util/HashUtils.java create mode 100644 src/main/java/com/alterdekim/javabot/util/PseudoRandom.java create mode 100644 src/main/java/com/alterdekim/javabot/util/UAgentInfo.java create mode 100644 src/main/resources/messages_en.properties create mode 100644 src/main/resources/messages_ru.properties create mode 100644 src/main/resources/static/css/panel.css create mode 100644 src/main/resources/static/css/sign-in.css create mode 100644 src/main/resources/static/css/sign-up.css create mode 100644 src/main/resources/static/css/util.css create mode 100644 src/main/resources/static/javascript/color-modes.js create mode 100644 src/main/resources/static/javascript/panel-script.js create mode 100644 src/main/resources/templates/access-denied.html create mode 100644 src/main/resources/templates/fragments/floating_button.html create mode 100644 src/main/resources/templates/fragments/footer.html create mode 100644 src/main/resources/templates/fragments/header.html create mode 100644 src/main/resources/templates/login.html create mode 100644 src/main/resources/templates/panel.html create mode 100644 src/main/resources/templates/signup.html diff --git a/README.md b/README.md new file mode 100644 index 0000000..d518662 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Bunker +Bunker - telegram bot, that provides ability to play a post-apocalypse survival game. + +## Description + +This bot acts as a "game master", providing unique game experience for you and your friends. + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8599f67 --- /dev/null +++ b/pom.xml @@ -0,0 +1,113 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + com.alterdekim.javabot + bunker + 1.0-SNAPSHOT + jar + + + 1.8 + 1.8 + UTF-8 + + + + + log4j + log4j + 1.2.17 + + + org.springframework.boot + spring-boot-devtools + runtime + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity6 + + 3.1.1.RELEASE + + + org.springframework.boot + spring-boot-starter-validation + + + mysql + mysql-connector-java + 8.0.33 + + + org.projectlombok + lombok + true + 1.18.28 + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-security + + + org.telegram + telegrambots-spring-boot-starter + 6.7.0 + + + org.telegram + telegrambots-abilities + 6.7.0 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + org.projectlombok + lombok + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/alterdekim/javabot/Application.java b/src/main/java/com/alterdekim/javabot/Application.java new file mode 100644 index 0000000..3ec6c98 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/Application.java @@ -0,0 +1,25 @@ +package com.alterdekim.javabot; + +import com.alterdekim.javabot.storage.StorageService; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableScheduling; + + +@SpringBootApplication +@EnableScheduling +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @Bean + CommandLineRunner init(StorageService storageService) { + return (args) -> { + storageService.init(); + }; + } +} diff --git a/src/main/java/com/alterdekim/javabot/Commands.java b/src/main/java/com/alterdekim/javabot/Commands.java new file mode 100644 index 0000000..cd3b9d6 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/Commands.java @@ -0,0 +1,10 @@ +package com.alterdekim.javabot; + +public interface Commands { + String SET_GROUP = "/setgroup"; + String GET_INFO = "/info"; + String STOP_GAME = "/stopgame"; + String START_GAME = "/startgame"; + String JOIN_GAME = "/join"; + String HELP = "/help"; +} diff --git a/src/main/java/com/alterdekim/javabot/Constants.java b/src/main/java/com/alterdekim/javabot/Constants.java new file mode 100644 index 0000000..7d4b5c5 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/Constants.java @@ -0,0 +1,54 @@ +package com.alterdekim.javabot; + +public interface Constants { + String REMOVE_PLAYER = "Игрок %s покидает бункер."; + String ENDVOTE = "Голосование окончено."; + String DRAW = "Ничья. Никто не уходит из игры."; + String GROUP_SET = "Чат выбран."; + String INTERRUPT_GAME = "Игра остановлена."; + String USER_VOTED = "%s проголосовал."; + String JOIN_GAME_BTN = "Присоединиться"; + String START_GAME_MSG = "Набор игроков начат. Присоединяйтесь."; + String JOINED_THE_GAME = "%s добавлен(а) в игру. Всего игроков: %d"; + String THANK_YOU = "Спасибо."; + String ALREADY_IN_GAME = "Ты уже в игре."; + String CANT_JOIN_NOT_STARTED = "Не могу добавить вас в игру, тк вы не разрешили вам писать сообщения."; + String HELP = "Help"; + String START_GAME_BTN = "Начать игру"; + String NOT_ADMIN_EXCEPTION = "Вы не администратор"; + String ACCOUNT = "Ваша анкета:\nПол: %s (смертный: %s, мужчина: %s, женщина: %s)\nВозраст: %d\nПрофессия: %s (%s)\nБагаж: %s (%s)\nХобби: %s\nЗдоровье: %s (%s) %d%%, бесплоден: %s"; + String TRUE = "да"; + String FALSE = "нет"; + String PLAYERS_LESS_THAN_ZERO = "Игроков должно быть больше, чем 1."; + String HOBBY_BTN = "Хобби"; + String WORK_BTN = "Работа"; + String HEALTH_BTN = "Здоровье"; + String AGE_BTN = "Возраст"; + String GENDER_BTN = "Гендер"; + String LUGG_BTN = "Багаж"; + String GENDER_MESAGE = "%s - пол: %s (смертный: %s, мужчина: %s, женщина: %s)"; + String HEALTH_MESSAGE = "%s - здоровье: %s (%s) %d%%, бесплоден(а): %s"; + String SHOW_TIME = "Время выбрать, какую часть анкеты показать в этом раунде?"; + String AGE_MESSAGE = "%s - возраст: %d"; + String HOBBY_MESSAGE = "%s - хобби: %s"; + String WORK_MESSAGE = "%s - профессия: %s (%s)"; + String LUGG_MESSAGE = "%s - багаж: %s (%s)"; + String DAY_MESSAGE_UPPER = "Следующий раунд начался!\nВероятность выжить \uD83D\uDCC8: %d%% (увеличилась на %f%%)"; + String PRESSED_NIGHT = "%s нажал(а)"; + String DAY_MESSAGE_DOWN = "Следующий раунд начался!\nВероятность выжить \uD83D\uDCC9: %d%% (уменьшилась на %f%%)"; + String DAY_MESSAGE = "Следующий раунд начался!\nВероятность выжить: %f%%"; + String END_GAME = "Конец игры.\nВероятность выжить: %f%%"; + String POLL_QUESTION = "Кто в бункер не идёт?"; + + String DEATHMATCH = "Deathmatch"; + + String PROBABILITY = "Обычная"; + + String WIN_MESSAGE = "Поздравляю! Победа за вами!\n%s"; + + String LOSE_MESSAGE = "Поздравляю! Вы проиграли!"; + + String INFO_MESSAGE = "Вот открытая информация о живых игроках\n"; + + String CANT_SEND_NOT_DAY = "Нельзя использовать эту команду во время перерыва."; +} \ No newline at end of file diff --git a/src/main/java/com/alterdekim/javabot/FileServerController.java b/src/main/java/com/alterdekim/javabot/FileServerController.java new file mode 100644 index 0000000..3f2c145 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/FileServerController.java @@ -0,0 +1,41 @@ +package com.alterdekim.javabot; + +import com.alterdekim.javabot.storage.StorageFileNotFoundException; +import com.alterdekim.javabot.storage.StorageProperties; +import com.alterdekim.javabot.storage.StorageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@EnableConfigurationProperties(StorageProperties.class) +public class FileServerController { + + private final StorageService storageService; + + @Autowired + public FileServerController(StorageService storageService) { + this.storageService = storageService; + } + + @GetMapping("/static/{assetspath}/{filename:.+}") + @ResponseBody + public ResponseEntity serveFile(@PathVariable String filename, @PathVariable String assetspath) { + Resource file = storageService.loadAsResource("static/" + assetspath + "/" + filename); + return ResponseEntity.ok().contentType(new MediaType("text", assetspath)).header(HttpHeaders.CONTENT_DISPOSITION, + "attachment; filename=\"" + file.getFilename() + "\"").body(file); + } + + @ExceptionHandler(StorageFileNotFoundException.class) + public ResponseEntity handleStorageFileNotFound(StorageFileNotFoundException exc) { + return ResponseEntity.notFound().build(); + } +} diff --git a/src/main/java/com/alterdekim/javabot/Initializer.java b/src/main/java/com/alterdekim/javabot/Initializer.java new file mode 100644 index 0000000..898de53 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/Initializer.java @@ -0,0 +1,28 @@ +package com.alterdekim.javabot; + +import com.alterdekim.javabot.components.BunkerBot; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import org.telegram.telegrambots.meta.TelegramBotsApi; +import org.telegram.telegrambots.meta.exceptions.TelegramApiException; +import org.telegram.telegrambots.updatesreceivers.DefaultBotSession; + +@Component +@Slf4j +public class Initializer { + @Autowired + BunkerBot bot; + + @EventListener({ContextRefreshedEvent.class}) + public void init() { + try { + TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class); + telegramBotsApi.registerBot(bot); + } catch (TelegramApiException e) { + log.error(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/alterdekim/javabot/MvcConfig.java b/src/main/java/com/alterdekim/javabot/MvcConfig.java new file mode 100644 index 0000000..31921f6 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/MvcConfig.java @@ -0,0 +1,41 @@ +package com.alterdekim.javabot; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; +import org.springframework.web.servlet.i18n.SessionLocaleResolver; + +import java.util.Locale; + +@Configuration +public class MvcConfig implements WebMvcConfigurer { + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/signup").setViewName("signup"); + registry.addViewController("/login").setViewName("login"); + registry.addViewController("/panel").setViewName("panel"); + registry.addRedirectViewController("/", "/panel"); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(localeChangeInterceptor()); + } + + @Bean + public LocaleChangeInterceptor localeChangeInterceptor() { + LocaleChangeInterceptor lci = new LocaleChangeInterceptor(); + lci.setParamName("lang"); + return lci; + } + + @Bean + public LocaleResolver localeResolver() { + SessionLocaleResolver slr = new SessionLocaleResolver(); + slr.setDefaultLocale(Locale.US); + return slr; + } +} diff --git a/src/main/java/com/alterdekim/javabot/TelegramConfig.java b/src/main/java/com/alterdekim/javabot/TelegramConfig.java new file mode 100644 index 0000000..025fd75 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/TelegramConfig.java @@ -0,0 +1,16 @@ +package com.alterdekim.javabot; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + + +@Data +@Configuration +@PropertySource("file:./telegram.properties") // classpath:/telegram.properties +public class TelegramConfig { + @Value("${bot.botToken}") private String botToken; + @Value("${bot.botLogin}") private String botLogin; + @Value("${bot.master}") private String masterId; +} diff --git a/src/main/java/com/alterdekim/javabot/bot/BotAccountProfileGenerator.java b/src/main/java/com/alterdekim/javabot/bot/BotAccountProfileGenerator.java new file mode 100644 index 0000000..e057585 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/bot/BotAccountProfileGenerator.java @@ -0,0 +1,30 @@ +package com.alterdekim.javabot.bot; + +import com.alterdekim.javabot.Constants; +import com.alterdekim.javabot.service.TextDataValService; + +public class BotAccountProfileGenerator { + + public static String build(TextDataValService textDataValService, Player p) { + return String.format(Constants.ACCOUNT, + getStringById(textDataValService, p.getGender().getGenderTextId()), + p.getGender().getCanDie() ? Constants.TRUE : Constants.FALSE, + p.getGender().getIsMale() ? Constants.TRUE : Constants.FALSE, + p.getGender().getIsFemale() ? Constants.TRUE : Constants.FALSE, + p.getAge(), + getStringById(textDataValService, p.getWork().getTextNameId()), + getStringById(textDataValService, p.getWork().getTextDescId()), + getStringById(textDataValService, p.getLuggage().getTextNameId()), + getStringById(textDataValService, p.getLuggage().getTextDescId()), + getStringById(textDataValService, p.getHobby().getTextDescId()), + getStringById(textDataValService, p.getHealth().getTextNameId()), + getStringById(textDataValService, p.getHealth().getTextDescId()), + (int) (p.getHealth().getHealth_index()*100f), + p.getHealth().getIsChildfree() ? Constants.TRUE : Constants.FALSE + ); + } + + private static String getStringById(TextDataValService textDataValService, Long id) { + return textDataValService.getTextDataValById(id).getText(); + } +} diff --git a/src/main/java/com/alterdekim/javabot/bot/DayNightFields.java b/src/main/java/com/alterdekim/javabot/bot/DayNightFields.java new file mode 100644 index 0000000..455f5f9 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/bot/DayNightFields.java @@ -0,0 +1,31 @@ +package com.alterdekim.javabot.bot; + +import lombok.Getter; +import lombok.Setter; + +import java.util.HashMap; +import java.util.Map; + +@Getter +@Setter +public class DayNightFields { + private Boolean isNight; + private Integer nightToken; + private String lastPollId; + private Map poll; + private String dayMessage; + private Integer turnCount; + + public DayNightFields() { + this.isNight = false; + this.nightToken = 0; + this.lastPollId = ""; + this.poll = new HashMap<>(); + this.dayMessage = ""; + this.turnCount = 0; + } + + public void appendMessage(String s) { + this.dayMessage += s; + } +} diff --git a/src/main/java/com/alterdekim/javabot/bot/InfoSections.java b/src/main/java/com/alterdekim/javabot/bot/InfoSections.java new file mode 100644 index 0000000..0980a76 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/bot/InfoSections.java @@ -0,0 +1,24 @@ +package com.alterdekim.javabot.bot; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class InfoSections { + private Boolean isGenderShowed; + private Boolean isAgeShowed; + private Boolean isWorkShowed; + private Boolean isLuggageShowed; + private Boolean isHobbyShowed; + private Boolean isHealthShowed; + + public InfoSections() { + this.isAgeShowed = false; + this.isLuggageShowed = false; + this.isGenderShowed = false; + this.isWorkShowed = false; + this.isHealthShowed = false; + this.isHobbyShowed = false; + } +} diff --git a/src/main/java/com/alterdekim/javabot/bot/LiveFormula.java b/src/main/java/com/alterdekim/javabot/bot/LiveFormula.java new file mode 100644 index 0000000..d8ef135 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/bot/LiveFormula.java @@ -0,0 +1,81 @@ +package com.alterdekim.javabot.bot; + +import com.alterdekim.javabot.entities.ColumnType; +import com.alterdekim.javabot.entities.Synergy; +import com.alterdekim.javabot.util.Clamp; + +import java.util.List; + +public class LiveFormula { + public static double calc(List playerList, List synergies) { + double i = 0; + for( Player p : playerList ) { + double age = 1.0D - (((double) p.getAge()) / 75.0D); + age = p.getGender().getCanDie() ? age : 1.0D; + double gender = p.getGender().getIsMale() ? 1 : 0; + gender += p.getGender().getIsFemale() ? 1 : 0; + gender = p.getHealth().getIsChildfree() ? 0 : gender; + gender *= 0.5D; + double work = p.getWork().getValue(); + double luggage = p.getLuggage().getValue(); + luggage = p.getLuggage().getGarbage() ? 0 : luggage; + double hobby = p.getHobby().getValue(); + double health = p.getHealth().getHealth_index().doubleValue(); + i += ((age + gender + work + luggage + hobby + health) / 6.0d); + } + i = i / ((double) playerList.size()); + double _i = i; + if( playerList.stream().anyMatch(t -> (t.getGender().getIsMale() && !t.getHealth().getIsChildfree())) && + playerList.stream().anyMatch(t -> (t.getGender().getIsFemale() && !t.getHealth().getIsChildfree())) ) { + i += 0.3 * _i; + } + for( Synergy s : synergies ) { + Boolean fb = LiveFormula.entity(playerList, s.getFirstType(), s.getFirstEntityId()); + Boolean eb = LiveFormula.entity(playerList, s.getSecondType(), s.getSecondEntityId()); + if( fb && eb ) i += s.getProbabilityValue().doubleValue() * _i; + } + return Clamp.clamp(i * 1.2d, 0, 1); + } + + private static Boolean entity(List players, ColumnType ct, Long eid) { + Boolean fb = false; + switch (ct) { + case Bio: + fb = LiveFormula.searchForBio(players, eid); + break; + case Work: + fb = LiveFormula.searchForWork(players, eid); + break; + case Hobby: + fb = LiveFormula.searchForHobby(players, eid); + break; + case Health: + fb = LiveFormula.searchForHealth(players, eid); + break; + case Luggage: + fb = LiveFormula.searchForLuggage(players, eid); + break; + } + return fb; + } + + private static Boolean searchForBio(List players, Long id) { + return players.stream().anyMatch(p -> p.getGender().getId().equals(id)); + } + + private static Boolean searchForWork(List players, Long id) { + return players.stream().anyMatch(p -> p.getWork().getId().equals(id)); + } + + private static Boolean searchForHobby(List players, Long id) { + return players.stream().anyMatch(p -> p.getHobby().getId().equals(id)); + } + + private static Boolean searchForHealth(List players, Long id) { + return players.stream().anyMatch(p -> p.getHealth().getId().equals(id)); + } + + private static Boolean searchForLuggage(List players, Long id) { + return players.stream().anyMatch(p -> p.getLuggage().getId().equals(id)); + } +} diff --git a/src/main/java/com/alterdekim/javabot/bot/Player.java b/src/main/java/com/alterdekim/javabot/bot/Player.java new file mode 100644 index 0000000..c567aea --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/bot/Player.java @@ -0,0 +1,29 @@ +package com.alterdekim.javabot.bot; + +import com.alterdekim.javabot.entities.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class Player { + private Long telegramId; + private int age; + private Bio gender; + private Health health; + private Hobby hobby; + private Work work; + private Luggage luggage; + private Boolean isAnswered = false; + private String firstName; + private InfoSections infoSections; + private Boolean isVoted = false; + + public Player(Long telegramId, String name) { + this.telegramId = telegramId; + this.firstName = name; + this.infoSections = new InfoSections(); + } +} diff --git a/src/main/java/com/alterdekim/javabot/components/BunkerBot.java b/src/main/java/com/alterdekim/javabot/components/BunkerBot.java new file mode 100644 index 0000000..b65ebdf --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/components/BunkerBot.java @@ -0,0 +1,513 @@ +package com.alterdekim.javabot.components; + +import com.alterdekim.javabot.bot.*; +import com.alterdekim.javabot.Commands; +import com.alterdekim.javabot.Constants; +import com.alterdekim.javabot.TelegramConfig; +import com.alterdekim.javabot.entities.*; +import com.alterdekim.javabot.service.*; +import com.alterdekim.javabot.util.BotUtils; +import com.alterdekim.javabot.util.GameState; +import com.alterdekim.javabot.util.HashUtils; +import jakarta.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.telegram.telegrambots.bots.TelegramLongPollingBot; +import org.telegram.telegrambots.meta.api.methods.AnswerCallbackQuery; +import org.telegram.telegrambots.meta.api.methods.BotApiMethod; +import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatMember; +import org.telegram.telegrambots.meta.api.methods.polls.SendPoll; +import org.telegram.telegrambots.meta.api.methods.send.SendMessage; +import org.telegram.telegrambots.meta.api.methods.updatingmessages.DeleteMessage; +import org.telegram.telegrambots.meta.api.objects.CallbackQuery; +import org.telegram.telegrambots.meta.api.objects.Message; +import org.telegram.telegrambots.meta.api.objects.Update; +import org.telegram.telegrambots.meta.api.objects.User; +import org.telegram.telegrambots.meta.api.objects.chatmember.ChatMember; +import org.telegram.telegrambots.meta.exceptions.TelegramApiException; + +import java.io.Serializable; +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.Collectors; + +@Component +@Slf4j +public class BunkerBot extends TelegramLongPollingBot { + private final TelegramConfig telegramConfig; + private String groupId = ""; + + private GameState gameState; + + private double last_p = -1; + + private List players; + + private final BioService bioService; + private final HealthService healthService; + private final HobbyService hobbyService; + private final LuggageService luggageService; + private final WorkService workService; + private final TextDataValService textDataValService; + private final DisasterService disasterService; + private final SynergyService synergyService; + + private final Random random; + + private DayNightFields dayNightFields; + + private ConcurrentLinkedQueue> linkedQueue; + + @SuppressWarnings("deprecation") + public BunkerBot(TelegramConfig telegramConfig, + BioService bioService, + HealthService healthService, + HobbyService hobbyService, + LuggageService luggageService, + WorkService workService, + TextDataValService textDataValService, + DisasterService disasterService, + SynergyService synergyService) { + this.telegramConfig = telegramConfig; + this.players = new ArrayList<>(); + this.gameState = GameState.NONE; + this.bioService = bioService; + this.healthService = healthService; + this.hobbyService = hobbyService; + this.luggageService = luggageService; + this.workService = workService; + this.textDataValService = textDataValService; + this.disasterService = disasterService; + this.synergyService = synergyService; + this.random = new Random(); + this.dayNightFields = new DayNightFields(); + this.linkedQueue = new ConcurrentLinkedQueue<>(); + } + + @Scheduled(fixedRate = 100) + private void executeApi() { + if( !this.linkedQueue.isEmpty() ) + sendApiMethodAsync(this.linkedQueue.poll()); + } + + + @Override + public String getBotUsername() { + return telegramConfig.getBotLogin(); + } + + @Override + @SuppressWarnings("deprecation") + public String getBotToken() { + return telegramConfig.getBotToken(); + } + + private Long getMasterId() { + return Long.parseLong(telegramConfig.getMasterId()); + } + + private void joinGame(User user, Integer msgid) { + if( gameState != GameState.JOINING ) + return; + + if( !hasPlayerWithId(user.getId()) ) { + if( canWrite(user) ) { + this.players.add(new Player(user.getId(), user.getFirstName())); + sendApi( + new SendMessage( + groupId, + String.format( + Constants.JOINED_THE_GAME, + user.getFirstName(), + players.size() + ) + ) + ); + return; + } + + if( msgid != 0 ) { + SendMessage sm = new SendMessage(groupId, Constants.CANT_JOIN_NOT_STARTED); + sm.setReplyToMessageId(msgid); + sendApi(sm); + return; + } + SendMessage sm = new SendMessage(groupId, BotUtils.mentionUser(user.getUserName()) + Constants.CANT_JOIN_NOT_STARTED); + sendApi(sm); + return; + } + sendApi( + new SendMessage( + groupId, + Constants.ALREADY_IN_GAME + ) + ); + } + + private Boolean canWrite(User u) { + SendMessage message = new SendMessage(u.getId()+"", "."); + message.disableNotification(); + Message mr; + try { + mr = sendApiMethod(message); + } catch ( Exception e ) { + return false; + } + sendApi(new DeleteMessage(u.getId()+"", mr.getMessageId())); + return true; + } + + private Boolean isAdmin(User u) { + GetChatMember chatMember = new GetChatMember(groupId, u.getId()); + try { + ChatMember cm = sendApiMethod(chatMember); + return cm.getStatus().equals("creator") || cm.getStatus().startsWith("admin"); + } catch (Exception e) { + return false; + } + } + + private void startGame() { + if( gameState != GameState.JOINING ) + return; + if(players.size() < 2) { + sendApi(new SendMessage(groupId, Constants.PLAYERS_LESS_THAN_ZERO)); + return; + } + this.gameState = GameState.STARTED; + Disaster d = (Disaster) BotUtils.getRandomFromList(disasterService.getAllDisasters(), random); + sendApi(new SendMessage(groupId, getStringById(d.getDescTextId()))); + List bios = bioService.getAllBios(); + List works = workService.getAllWorks(); + List luggs = luggageService.getAllLuggages(); + List hobbies = hobbyService.getAllHobbies(); + List healths = healthService.getAllHealth(); + for( Player p : players ) { + p.setAge(random.nextInt(57)+18); + p.setGender((Bio) BotUtils.getRandomFromList(bios, random)); + p.setWork((Work) BotUtils.getRandomFromList(works, random)); + p.setLuggage((Luggage) BotUtils.getRandomFromList(luggs, random)); + p.setHobby((Hobby) BotUtils.getRandomFromList(hobbies, random)); + p.setHealth((Health) BotUtils.getRandomFromList(healths, random)); + + SendMessage sendMessage = new SendMessage(p.getTelegramId()+"", BotAccountProfileGenerator.build(textDataValService, p)); + sendApi(sendMessage); + } + doNight(); + } + + private void doNight() { + this.dayNightFields.setIsNight(true); + this.dayNightFields.setNightToken(random.nextInt(1000)+10); + this.dayNightFields.setPoll(new HashMap<>()); + this.dayNightFields.setTurnCount(this.dayNightFields.getTurnCount()+1); + for( Player p : players ) { + SendMessage sendMessage = new SendMessage(p.getTelegramId()+"", Constants.SHOW_TIME); + sendMessage.setReplyMarkup(BotUtils.getShowKeyboard(p.getInfoSections())); + sendApi(sendMessage); + } + } + + private String getStringById(Long id) { + return textDataValService.getTextDataValById(id).getText(); + } + + private void processNightButton(CallbackQuery callbackQuery) { + if( this.hasPlayerWithId(callbackQuery.getFrom().getId()) && + !getPlayerById(callbackQuery.getFrom().getId()).getIsAnswered() ) { + Player p = getPlayerById(callbackQuery.getFrom().getId()); + InfoSections ins = p.getInfoSections(); + switch (new String(HashUtils.decodeHexString(callbackQuery.getData()))) { + case Constants.GENDER_BTN: + dayNightFields.appendMessage(String.format(Constants.GENDER_MESAGE, callbackQuery.getFrom().getFirstName(), getStringById(p.getGender().getGenderTextId()), + p.getGender().getCanDie() ? Constants.TRUE : Constants.FALSE, + p.getGender().getIsMale() ? Constants.TRUE : Constants.FALSE, + p.getGender().getIsFemale() ? Constants.TRUE : Constants.FALSE) + "\n"); + ins.setIsGenderShowed(true); + break; + case Constants.HEALTH_BTN: + dayNightFields.appendMessage(String.format(Constants.HEALTH_MESSAGE, callbackQuery.getFrom().getFirstName(), getStringById(p.getHealth().getTextNameId()), + getStringById(p.getHealth().getTextDescId()), + (int) (p.getHealth().getHealth_index()*100f), + p.getHealth().getIsChildfree() ? Constants.TRUE : Constants.FALSE) + "\n"); + ins.setIsHealthShowed(true); + break; + case Constants.AGE_BTN: + dayNightFields.appendMessage(String.format(Constants.AGE_MESSAGE, callbackQuery.getFrom().getFirstName(), p.getAge()) + "\n"); + ins.setIsAgeShowed(true); + break; + case Constants.HOBBY_BTN: + dayNightFields.appendMessage(String.format(Constants.HOBBY_MESSAGE, callbackQuery.getFrom().getFirstName(), + getStringById(p.getHobby().getTextDescId())) + "\n"); + ins.setIsHobbyShowed(true); + break; + case Constants.LUGG_BTN: + dayNightFields.appendMessage(String.format(Constants.LUGG_MESSAGE, callbackQuery.getFrom().getFirstName(), + getStringById(p.getLuggage().getTextNameId()), + getStringById(p.getLuggage().getTextDescId())) + "\n"); + ins.setIsLuggageShowed(true); + break; + case Constants.WORK_BTN: + dayNightFields.appendMessage(String.format(Constants.WORK_MESSAGE, callbackQuery.getFrom().getFirstName(), + getStringById(p.getWork().getTextNameId()), + getStringById(p.getWork().getTextDescId())) + "\n"); + ins.setIsWorkShowed(true); + break; + } + setIsAnswered(callbackQuery.getFrom().getId()); + updateInfoSections(p, ins); + sendApi(new SendMessage(callbackQuery.getMessage().getChatId()+"", Constants.THANK_YOU)); + sendApi(new DeleteMessage(callbackQuery.getMessage().getChatId()+"", callbackQuery.getMessage().getMessageId())); + sendApi(new SendMessage(groupId, String.format(Constants.PRESSED_NIGHT, callbackQuery.getFrom().getFirstName()))); + if( isAllAnswered() ) doDay(); + } + } + + private void sendApi(BotApiMethod method) { + this.linkedQueue.add(method); + } + + private void updateInfoSections(Player p1, InfoSections infoSections) { + players.stream().filter((p) -> p.equals(p1)).forEach((p) -> p.setInfoSections(infoSections)); + } + + private void setIsAnswered(Long id) { + players.stream().filter(p -> p.getTelegramId().equals(id) ).forEach(p -> p.setIsAnswered(true)); + } + + private void setIsVoted(Long id) { + players.stream().filter(p -> p.getTelegramId().equals(id) ).forEach(p -> p.setIsVoted(true)); + } + + private void doDay() { + dayNightFields.setIsNight(false); + double p = Math.floor(LiveFormula.calc(players, synergyService.getAllSynergies())*100d); + if( this.last_p < 0 ) { this.last_p = p; } + if( p > this.last_p ) { + sendApi(new SendMessage(groupId, String.format(Constants.DAY_MESSAGE_UPPER, (int) p, (p - this.last_p)))); + } else if( p < this.last_p ) { + sendApi(new SendMessage(groupId, String.format(Constants.DAY_MESSAGE_DOWN, (int) p, (this.last_p - p)))); + } else { + sendApi(new SendMessage(groupId, String.format(Constants.DAY_MESSAGE, p))); + } + this.last_p = p; + sendApi(new SendMessage(groupId, dayNightFields.getDayMessage())); + dayNightFields.setDayMessage(""); + setAllNotAnswered(); + setAllNotVoted(); + SendPoll sp = new SendPoll(groupId, Constants.POLL_QUESTION, getAllUsers()); + sp.setIsAnonymous(false); + sp.setAllowMultipleAnswers(false); + try { + dayNightFields.setLastPollId(sendApiMethod(sp).getPoll().getId()); + } catch (TelegramApiException e) { + log.error(e.getMessage()); + } + } + + private void setAllNotVoted() { + players.forEach((p) -> p.setIsVoted(false)); + } + + private Boolean isAllVoted() { + return players.stream().allMatch(Player::getIsVoted); + } + + private List getAllUsers() { + return players.stream().map(Player::getFirstName).collect(Collectors.toList()); + } + + private void setAllNotAnswered() { + players.forEach((p) -> p.setIsAnswered(false)); + } + + private Boolean isAllAnswered() { + return players.stream().allMatch(Player::getIsAnswered); + } + + private void showInfo() { + if( this.dayNightFields.getIsNight() ) { + sendApi(new SendMessage(groupId, Constants.CANT_SEND_NOT_DAY)); + return; + } + String message = Constants.INFO_MESSAGE; + for( Player p : players ) { + message += p.getFirstName() + ":\n"; + InfoSections s = p.getInfoSections(); + if(s.getIsGenderShowed()) { + message += String.format(Constants.GENDER_MESAGE, p.getFirstName(), getStringById(p.getGender().getGenderTextId()), + p.getGender().getCanDie() ? Constants.TRUE : Constants.FALSE, + p.getGender().getIsMale() ? Constants.TRUE : Constants.FALSE, + p.getGender().getIsFemale() ? Constants.TRUE : Constants.FALSE) + "\n"; + } + if(s.getIsAgeShowed()) { + message += String.format(Constants.AGE_MESSAGE, p.getFirstName(), p.getAge()) + "\n"; + } + if(s.getIsLuggageShowed()) { + message += String.format(Constants.LUGG_MESSAGE, p.getFirstName(), + getStringById(p.getLuggage().getTextNameId()), + getStringById(p.getLuggage().getTextDescId())) + "\n"; + } + if(s.getIsHealthShowed()) { + message += String.format(Constants.HEALTH_MESSAGE, p.getFirstName(), getStringById(p.getHealth().getTextNameId()), + getStringById(p.getHealth().getTextDescId()), + (int) (p.getHealth().getHealth_index()*100f), + p.getHealth().getIsChildfree() ? Constants.TRUE : Constants.FALSE) + "\n"; + } + if(s.getIsWorkShowed()) { + message += String.format(Constants.WORK_MESSAGE, p.getFirstName(), + getStringById(p.getWork().getTextNameId()), + getStringById(p.getWork().getTextDescId())) + "\n"; + } + if(s.getIsHobbyShowed()) { + message += String.format(Constants.HOBBY_MESSAGE, p.getFirstName(), + getStringById(p.getHobby().getTextDescId())) + "\n"; + } + message += "\n"; + } + sendApi(new SendMessage(groupId, message)); + } + + private void endVote() { + Integer max = dayNightFields.getPoll().values().stream().max(Integer::compareTo).get(); + long count = dayNightFields.getPoll().values().stream().filter(p -> p.equals(max)).count(); + SendMessage sendMessage = new SendMessage(groupId, Constants.ENDVOTE); + if( count > 1 ) { + sendMessage = new SendMessage(groupId, Constants.DRAW); + } else { + removeVotePlayers(max); + } + sendApi(sendMessage); + if( !checkEndGame() ) { + doNight(); + return; + } + endGame(); + } + + private Boolean checkEndGame() { + return players.size() < 2 || dayNightFields.getTurnCount() >= 6; + } + + private void endGame() { + double d = Math.floor(LiveFormula.calc(players, synergyService.getAllSynergies())*100d); + sendApi(new SendMessage(groupId, String.format(Constants.END_GAME, d))); + if(!players.isEmpty() && Math.floor(random.nextDouble()*100d) <= d) { + sendApi(new SendMessage(groupId, String.format(Constants.WIN_MESSAGE, + players.stream().map(Player::getFirstName).collect(Collectors.joining(", ")) + ))); + } else { + sendApi(new SendMessage(groupId, Constants.LOSE_MESSAGE)); + } + interruptGame(); + } + + private void removeVotePlayers(Integer max) { + dayNightFields.getPoll() + .entrySet() + .stream() + .filter(e -> e.getValue().equals(max)) + .forEach(i -> { + sendApi(new SendMessage(groupId, String.format(Constants.REMOVE_PLAYER, players.get(i.getKey()).getFirstName()))); + players.remove(i.getKey().intValue()); + }); + } + + private void interruptGame() { + this.dayNightFields = new DayNightFields(); + this.players = new ArrayList<>(); + this.gameState = GameState.NONE; + } + + @Override + public void onUpdateReceived(@NotNull Update update) { + if( update.hasPollAnswer() && update.getPollAnswer().getPollId().equals(dayNightFields.getLastPollId()) + && !dayNightFields.getIsNight() && !update.getPollAnswer().getOptionIds().isEmpty()) { + if( getPlayerById(update.getPollAnswer().getUser().getId()).getIsVoted() ) + return; + if( dayNightFields.getPoll().containsKey(update.getPollAnswer().getOptionIds().get(0)) ) { + dayNightFields.getPoll().put(update.getPollAnswer().getOptionIds().get(0), + dayNightFields.getPoll().get(update.getPollAnswer().getOptionIds().get(0)) + 1); + } else { + dayNightFields.getPoll().put(update.getPollAnswer().getOptionIds().get(0), 1); + } + setIsVoted(update.getPollAnswer().getUser().getId()); + sendApi(new SendMessage(groupId, String.format(Constants.USER_VOTED, update.getPollAnswer().getUser().getFirstName()))); + if( isAllVoted() ) + endVote(); + return; + } + + if( update.hasCallbackQuery() ) { + sendApi( + new AnswerCallbackQuery( + update.getCallbackQuery().getId() + ) + ); + if( update.getCallbackQuery().getData().equals(HashUtils.bytesToHex(Constants.JOIN_GAME_BTN.getBytes())) ) { + joinGame(update.getCallbackQuery().getFrom(), 0); + } else if( update.getCallbackQuery().getData().equals(HashUtils.bytesToHex(Constants.START_GAME_BTN.getBytes())) ) { + if( isAdmin(update.getCallbackQuery().getFrom()) ) { + startGame(); + return; + } + sendApi(new SendMessage(groupId, Constants.NOT_ADMIN_EXCEPTION)); + } else if( gameState == GameState.STARTED && dayNightFields.getIsNight() ) { + processNightButton(update.getCallbackQuery()); + } + return; + } + + if( !(update.hasMessage() && update.getMessage().hasText() && update.getMessage().isCommand()) ) + return; + + String chatId = update.getMessage().getChatId()+""; + + if( ( update.getMessage().getText().equals(Commands.SET_GROUP + "@" + getBotUsername()) || + update.getMessage().getText().equals(Commands.SET_GROUP)) && + update.getMessage().getFrom().getId().equals(getMasterId()) && gameState == GameState.NONE) { + groupId = chatId; + sendApi(new SendMessage(chatId, Constants.GROUP_SET)); + } + + if( !chatId.equals(groupId) ) + return; + + if ( (update.getMessage().getText().equals(Commands.START_GAME + "@" + getBotUsername()) || + update.getMessage().getText().equals(Commands.START_GAME) ) && + gameState == GameState.NONE) { + SendMessage message = new SendMessage(chatId, Constants.START_GAME_MSG); + message.setReplyMarkup(BotUtils.getJoinKeyboard()); + sendApi(message); + gameState = GameState.JOINING; + } else if (update.getMessage().getText().equals(Commands.JOIN_GAME + "@" + getBotUsername()) || + update.getMessage().getText().equals(Commands.JOIN_GAME)) { + joinGame(update.getMessage().getFrom(), update.getMessage().getMessageId()); + } else if (update.getMessage().getText().equals(Commands.HELP + "@" + getBotUsername()) || + update.getMessage().getText().equals(Commands.HELP)) { + sendApi(new SendMessage(chatId, Constants.HELP)); + } else if ((update.getMessage().getText().equals(Commands.STOP_GAME + "@" + getBotUsername()) || + update.getMessage().getText().equals(Commands.STOP_GAME) ) && + gameState != GameState.NONE) { + if( isAdmin(update.getMessage().getFrom()) ) { + sendApi(new SendMessage(groupId, Constants.INTERRUPT_GAME)); + interruptGame(); + return; + } + sendApi(new SendMessage(groupId, Constants.NOT_ADMIN_EXCEPTION)); + } else if((update.getMessage().getText().equals(Commands.GET_INFO + "@" + getBotUsername()) || + update.getMessage().getText().equals(Commands.GET_INFO) ) && + gameState == GameState.STARTED) { + showInfo(); + } + } + + private Player getPlayerById(Long id) { + return players.stream().filter((p) -> p.getTelegramId().equals(id) ).findFirst().orElse(null); + } + + private Boolean hasPlayerWithId(Long id) { + return players.stream().anyMatch((p) -> p.getTelegramId().equals(id)); + } +} \ No newline at end of file diff --git a/src/main/java/com/alterdekim/javabot/controller/AuthController.java b/src/main/java/com/alterdekim/javabot/controller/AuthController.java new file mode 100644 index 0000000..fc94407 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/controller/AuthController.java @@ -0,0 +1,75 @@ +package com.alterdekim.javabot.controller; + +import com.alterdekim.javabot.dto.UserDTO; +import com.alterdekim.javabot.entities.Invite; +import com.alterdekim.javabot.entities.User; +import com.alterdekim.javabot.service.InviteService; +import com.alterdekim.javabot.service.UserService; +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; + +@Slf4j +@Controller +public class AuthController { + + private final String base_title = " | Bunker"; + + private final UserService userService; + private final InviteService inviteService; + + public AuthController(UserService userService, InviteService inviteService) { + this.inviteService = inviteService; + this.userService = userService; + } + + @GetMapping("/login") + public String loginPage(Model model) { + model.addAttribute("title", "Login" + base_title); + return "login"; + } + + @GetMapping("/access-denied") + public String accessDenied(Model model) { + model.addAttribute("title", "Access denied"); + return "access-denied"; + } + + @GetMapping("/signup") + public String showRegistrationForm(Model model) { + UserDTO userDto = new UserDTO(); + model.addAttribute("user", userDto); + return "signup"; + } + + @PostMapping("/signup") + public String registration( + @ModelAttribute("user") @Valid UserDTO userDto, + BindingResult result, + Model model) { + User existingUser = userService.findByUsername(userDto.getUsername()); + Invite existingInvite = inviteService.findById(1); + + if(existingUser != null && existingUser.getUsername() != null && !existingUser.getUsername().isEmpty() ){ + result.rejectValue("username", null, + "There is already an account registered with the same username"); + return "redirect:/signup?error=1"; + } + + if(!existingInvite.getInvite_code().equals(userDto.getInvite_code())) { + result.rejectValue("invite_code", null, "Incorrect invite code."); + return "redirect:/signup?error=1"; + } + + if(result.hasErrors()) { + model.addAttribute("user", new UserDTO()); + return "redirect:/signup?error=1"; + } + + userService.saveUser(userDto); + return "redirect:/"; + } +} diff --git a/src/main/java/com/alterdekim/javabot/controller/DatabaseController.java b/src/main/java/com/alterdekim/javabot/controller/DatabaseController.java new file mode 100644 index 0000000..a101e26 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/controller/DatabaseController.java @@ -0,0 +1,312 @@ +package com.alterdekim.javabot.controller; + +import com.alterdekim.javabot.dto.SynergyResult; +import com.alterdekim.javabot.entities.*; +import com.alterdekim.javabot.service.*; +import com.alterdekim.javabot.util.HashUtils; +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Slf4j +@RestController +public class DatabaseController { + private final BioService bioService; + private final HealthService healthService; + private final HobbyService hobbyService; + private final LuggageService luggageService; + private final WorkService workService; + private final TextDataValService textDataValService; + private final DisasterService disasterService; + private final SynergyService synergyService; + + public DatabaseController( + BioService bioService, + HealthService healthService, + HobbyService hobbyService, + LuggageService luggageService, + WorkService workService, + TextDataValService textDataValService, + DisasterService disasterService, + SynergyService synergyService) { + this.bioService = bioService; + this.healthService = healthService; + this.hobbyService = hobbyService; + this.luggageService = luggageService; + this.workService = workService; + this.textDataValService = textDataValService; + this.disasterService = disasterService; + this.synergyService = synergyService; + } + + private void saveGender(Map params) { + Boolean canDie = Boolean.parseBoolean(params.get("canDie")); + Boolean ismale = Boolean.parseBoolean(params.get("ismale")); + Boolean isfemale = Boolean.parseBoolean(params.get("isfemale")); + String gender_text = new String(HashUtils.decodeHexString(params.get("gender_text"))); + TextDataVal t = textDataValService.save(new TextDataVal(gender_text)); + bioService.saveBio(new Bio(ismale, isfemale, canDie, t.getId())); + } + + private void saveHobby(Map params) { + Float powerRange = Float.parseFloat(params.get("powerRange")); + Float violenceRange = Float.parseFloat(params.get("violenceRange")); + Float healRange = Float.parseFloat(params.get("healRange")); + Float foodRange = Float.parseFloat(params.get("foodRange")); + String hobby_text = new String(HashUtils.decodeHexString(params.get("hobby_text"))); + TextDataVal t = textDataValService.save(new TextDataVal(hobby_text)); + hobbyService.saveHobby(new Hobby(foodRange, powerRange, violenceRange, healRange, t.getId())); + } + + private void saveLuggage(Map params) { + Float powerRange = Float.parseFloat(params.get("powerRange")); + Float violenceRange = Float.parseFloat(params.get("violenceRange")); + Float healRange = Float.parseFloat(params.get("healRange")); + Float foodRange = Float.parseFloat(params.get("foodRange")); + Boolean isGarbage = Boolean.parseBoolean(params.get("isgarbage")); + + String name_text = new String(HashUtils.decodeHexString(params.get("luggage_name_text"))); + TextDataVal t1 = textDataValService.save(new TextDataVal(name_text)); + + String desc_text = new String(HashUtils.decodeHexString(params.get("luggage_desc_text"))); + TextDataVal t2 = textDataValService.save(new TextDataVal(desc_text)); + + luggageService.saveLuggage(new Luggage(violenceRange, powerRange, healRange, foodRange, isGarbage, t1.getId(), t2.getId())); + } + + private void saveHealth(Map params) { + Float health_index = Float.parseFloat(params.get("health_index")); + Boolean childFree = Boolean.parseBoolean(params.get("childFree")); + String name_text = new String(HashUtils.decodeHexString(params.get("heal_name_text"))); + TextDataVal t1 = textDataValService.save(new TextDataVal(name_text)); + + String desc_text = new String(HashUtils.decodeHexString(params.get("heal_desc_text"))); + TextDataVal t2 = textDataValService.save(new TextDataVal(desc_text)); + + healthService.saveHealth(new Health(health_index, t1.getId(), t2.getId(), childFree)); + } + + private void saveWork(Map params) { + Float powerRange = Float.parseFloat(params.get("powerRange")); + Float violenceRange = Float.parseFloat(params.get("violenceRange")); + Float healRange = Float.parseFloat(params.get("healRange")); + Float foodRange = Float.parseFloat(params.get("foodRange")); + + String name_text = new String(HashUtils.decodeHexString(params.get("work_name_text"))); + TextDataVal t1 = textDataValService.save(new TextDataVal(name_text)); + + String desc_text = new String(HashUtils.decodeHexString(params.get("work_desc_text"))); + TextDataVal t2 = textDataValService.save(new TextDataVal(desc_text)); + + workService.saveWork(new Work(healRange, powerRange, violenceRange, foodRange, t1.getId(), t2.getId())); + } + + private void saveDiss(Map params) { + String name_text = new String(HashUtils.decodeHexString(params.get("diss_name_text"))); + TextDataVal t1 = textDataValService.save(new TextDataVal(name_text)); + + String desc_text = new String(HashUtils.decodeHexString(params.get("diss_desc_text"))); + TextDataVal t2 = textDataValService.save(new TextDataVal(desc_text)); + + disasterService.saveDisaster(new Disaster(t1.getId(), t2.getId())); + } + + @PostMapping("/api/remove_synergy") + public String remove_synergy(@RequestParam Map params) { + Long id = Long.parseLong(params.get("synergy_id")); + synergyService.removeById(id); + return "ok"; + } + + @PostMapping("/api/add_synergy") + public String add_synergy(@RequestParam Map params) { + Long feid = Long.parseLong(params.get("first_entity_id")); + ColumnType fetype = ColumnType.values()[Integer.parseInt(params.get("first_entity_type"))]; + Long seid = Long.parseLong(params.get("second_entity_id")); + ColumnType setype = ColumnType.values()[Integer.parseInt(params.get("second_entity_type"))]; + Float probability = Float.parseFloat(params.get("probability")); + + synergyService.saveSynergy(new Synergy(feid, fetype, seid, setype, probability)); + + return "ok"; + } + + @PostMapping("/api/get_synergies") + public String get_synergies(@RequestParam Map params) { + Long id = Long.parseLong(params.get("entity_id")); + String section = params.get("entity_type"); + ObjectMapper mapper = new ObjectMapper(); + try { + List synergyList = new ArrayList<>(); + switch (section) { + case "agge": + synergyList = bioService.getSynergies(id); + break; + case "lugg": + synergyList = luggageService.getSynergies(id); + break; + case "prof": + synergyList = workService.getSynergies(id); + break; + case "heal": + synergyList = healthService.getSynergies(id); + break; + case "hobb": + synergyList = hobbyService.getSynergies(id); + break; + } + List results = new ArrayList<>(); + for( Synergy s : synergyList ) { + String textFirst = getText(s.getFirstType(), s.getFirstEntityId()); + String textSecond = getText(s.getSecondType(), s.getSecondEntityId()); + results.add(new SynergyResult(s.getId(), textFirst, textSecond, s.getFirstType(), s.getSecondType(), s.getProbabilityValue())); + } + return mapper.writeValueAsString(results); + } catch (JacksonException e) { + log.error(e.getMessage()); + } + return "ok"; + } + + private String getText(ColumnType type, Long feid) { + switch (type) { + case Bio: + return textDataValService.getTextDataValById(bioService.getBioById(feid).getGenderTextId()).getText(); + case Health: + return textDataValService.getTextDataValById(healthService.getHealthById(feid).getTextNameId()).getText(); + case Hobby: + return textDataValService.getTextDataValById(hobbyService.getHobbyById(feid).getTextDescId()).getText(); + case Luggage: + return textDataValService.getTextDataValById(luggageService.getLuggageById(feid).getTextNameId()).getText(); + case Work: + return textDataValService.getTextDataValById(workService.getWorkById(feid).getTextNameId()).getText(); + } + return "-"; + } + + @PostMapping("/api/add_entry") + public String add_entry(@RequestParam Map params) { + /* additional data, disasters */ + String section = params.get("section"); + switch (section) { + case "agge": + saveGender(params); + break; + case "lugg": + saveLuggage(params); + break; + case "prof": + saveWork(params); + break; + case "heal": + saveHealth(params); + break; + case "hobb": + saveHobby(params); + break; + case "diss": + saveDiss(params); + break; + default: + saveDiss(params); + break; + } + return "ok"; + } + + @PostMapping("/api/remove_entry") + public String remove_entry(@RequestParam Map params) { + String section = params.get("section"); + long entry_id = Long.parseLong(params.get("entry_id")); + switch (section) { + case "agge": + bioService.removeById(entry_id); + break; + case "hobb": + hobbyService.removeById(entry_id); + break; + case "lugg": + luggageService.removeById(entry_id); + break; + case "heal": + healthService.removeById(entry_id); + break; + case "prof": + workService.removeById(entry_id); + break; + case "diss": + disasterService.removeById(entry_id); + break; + default: + disasterService.removeById(entry_id); + break; + } + return "ok"; + } + + @PostMapping("/api/getTextById") + public String getText(@RequestParam Map params) { + long l = Long.parseLong(params.get("entry_id")); + return textDataValService.getTextDataValById(l).getText(); + } + + @PostMapping("/api/get_entries") + public String getEntries(@RequestParam Map params) { + ObjectMapper mapper = new ObjectMapper(); + try { + switch (params.get("section")) { + case "agge": + return mapper.writeValueAsString(bioService.getAllBios()); + case "hobb": + return mapper.writeValueAsString(hobbyService.getAllHobbies()); + case "prof": + return mapper.writeValueAsString(workService.getAllWorks()); + case "heal": + return mapper.writeValueAsString(healthService.getAllHealth()); + case "lugg": + return mapper.writeValueAsString(luggageService.getAllLuggages()); + case "diss": + return mapper.writeValueAsString(disasterService.getAllDisasters()); + default: + return mapper.writeValueAsString(disasterService.getAllDisasters()); + } + } catch (JacksonException e) { + log.error(e.getMessage()); + } + return "error"; + } + + @PostMapping("/api/edit_entry") + public String edit_entry(@RequestParam Map params) { + ObjectMapper mapper = new ObjectMapper(); + long l = Long.parseLong(params.get("entry_id")); + try { + switch (params.get("section")) { + case "agge": + return mapper.writeValueAsString(bioService.getBioById(l)); + case "hobb": + return mapper.writeValueAsString(hobbyService.getHobbyById(l)); + case "prof": + return mapper.writeValueAsString(workService.getWorkById(l)); + case "heal": + return mapper.writeValueAsString(healthService.getHealthById(l)); + case "lugg": + return mapper.writeValueAsString(luggageService.getLuggageById(l)); + case "diss": + return mapper.writeValueAsString(disasterService.getDisasterById(l)); + default: + return mapper.writeValueAsString(disasterService.getDisasterById(l)); + } + } catch (JacksonException e) { + log.error(e.getMessage()); + } + return "error"; + } +} diff --git a/src/main/java/com/alterdekim/javabot/controller/PanelController.java b/src/main/java/com/alterdekim/javabot/controller/PanelController.java new file mode 100644 index 0000000..dc92b51 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/controller/PanelController.java @@ -0,0 +1,175 @@ +package com.alterdekim.javabot.controller; + +import com.alterdekim.javabot.entities.*; +import com.alterdekim.javabot.service.*; +import com.alterdekim.javabot.util.UAgentInfo; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; + +import java.io.Serializable; +import java.util.*; + +@Slf4j +@Controller +public class PanelController { + private final BioService bioService; + private final HealthService healthService; + private final HobbyService hobbyService; + private final LuggageService luggageService; + private final WorkService workService; + private final TextDataValService textDataValService; + private final DisasterService disasterService; + + public PanelController( + BioService bioService, + HealthService healthService, + HobbyService hobbyService, + LuggageService luggageService, + WorkService workService, + TextDataValService textDataValService, + DisasterService disasterService) { + this.bioService = bioService; + this.healthService = healthService; + this.hobbyService = hobbyService; + this.luggageService = luggageService; + this.workService = workService; + this.textDataValService = textDataValService; + this.disasterService = disasterService; + } + + private List dissToCards() { + List bios = disasterService.getAllDisasters(); + List cards = new ArrayList<>(); + for( Disaster b : bios ) { + Card card = new Card(); + card.setId(b.getId()); + card.setTitle(textDataValService.getTextDataValById(b.getNameTextId()).getText()); + card.setBody(Collections.singletonList("Description: " + textDataValService.getTextDataValById(b.getDescTextId()).getText())); + cards.add(card); + } + cards.sort(Comparator.comparing(Card::getId)); + Collections.reverse(cards); + return cards; + } + + private List bioToCards() { + List bios = bioService.getAllBios(); + List cards = new ArrayList<>(); + for( Bio b : bios ) { + Card card = new Card(); + card.setId(b.getId()); + card.setTitle(textDataValService.getTextDataValById(b.getGenderTextId()).getText()); + card.setBody(Arrays.asList("canDie: " + b.getCanDie(), "isMale: " + b.getIsMale(), "isFemale: " + b.getIsFemale())); + cards.add(card); + } + cards.sort(Comparator.comparing(Card::getId)); + Collections.reverse(cards); + return cards; + } + + private List hobbyToCards() { + List bios = hobbyService.getAllHobbies(); + List cards = new ArrayList<>(); + for( Hobby b : bios ) { + Card card = new Card(); + card.setId(b.getId()); + card.setTitle(textDataValService.getTextDataValById(b.getTextDescId()).getText()); + card.setBody(Arrays.asList("Foodstuffs: " + b.getFoodstuffs(), "Asocial: " + b.getAsocial(), "Power: " + b.getPower(), "Violence:" + b.getViolence())); + cards.add(card); + } + cards.sort(Comparator.comparing(Card::getId)); + Collections.reverse(cards); + return cards; + } + + private List workToCards() { + List bios = workService.getAllWorks(); + List cards = new ArrayList<>(); + for( Work b : bios ) { + Card card = new Card(); + card.setId(b.getId()); + card.setTitle(textDataValService.getTextDataValById(b.getTextNameId()).getText()); + card.setBody(Arrays.asList("Foodstuffs: " + b.getFoodstuffs(), "Power: " + b.getPower(), "Violence: " + b.getViolence(), "Asocial: " + b.getAsocial(), "Description: " + textDataValService.getTextDataValById(b.getTextDescId()).getText())); + cards.add(card); + } + cards.sort(Comparator.comparing(Card::getId)); + Collections.reverse(cards); + return cards; + } + + private List healToCards() { + List bios = healthService.getAllHealth(); + List cards = new ArrayList<>(); + for( Health b : bios ) { + Card card = new Card(); + card.setId(b.getId()); + card.setTitle(textDataValService.getTextDataValById(b.getTextNameId()).getText()); + card.setBody(Arrays.asList("Health index: " + b.getHealth_index(),"isChildfree: " + b.getIsChildfree(), "Description: " + textDataValService.getTextDataValById(b.getTextDescId()).getText())); + cards.add(card); + } + cards.sort(Comparator.comparing(Card::getId)); + Collections.reverse(cards); + return cards; + } + + private List luggageToCards() { + List bios = luggageService.getAllLuggages(); + List cards = new ArrayList<>(); + for( Luggage b : bios ) { + Card card = new Card(); + card.setId(b.getId()); + card.setTitle(textDataValService.getTextDataValById(b.getTextNameId()).getText()); + card.setBody(Arrays.asList("Foodstuffs: " + b.getFoodstuffs(), "Power: " + b.getPower(), "Asocial: " + b.getAsocial(), "Violence: " + b.getViolence(), "Is garbage: " + b.getGarbage(), "Description: " + textDataValService.getTextDataValById(b.getTextDescId()).getText())); + cards.add(card); + } + cards.sort(Comparator.comparing(Card::getId)); + Collections.reverse(cards); + return cards; + } + + @GetMapping("/panel") + public String panelPage(Model model, @RequestHeader("User-Agent") String uagent, @RequestHeader("Accept") String accepth, @RequestParam(value = "section", defaultValue = "diss") String section) { + model.addAttribute("is_mobile", new UAgentInfo(uagent, accepth).detectSmartphone()); + model.addAttribute("section", section); + switch (section) { + case "lugg": + model.addAttribute( "cards", luggageToCards() ); + break; + case "heal": + model.addAttribute("cards", healToCards() ); + break; + case "prof": + model.addAttribute("cards", workToCards() ); + break; + case "hobb": + model.addAttribute("cards", hobbyToCards() ); + break; + case "agge": + model.addAttribute("cards", bioToCards() ); + break; + case "diss": + model.addAttribute("cards", dissToCards() ); + break; + case "stats": + // ! + break; + } + return "panel"; + } + + @Getter + @Setter + @NoArgsConstructor + private static class Card implements Serializable { + private String title; + private List body; + private Long id; + } +} diff --git a/src/main/java/com/alterdekim/javabot/dto/SynergyResult.java b/src/main/java/com/alterdekim/javabot/dto/SynergyResult.java new file mode 100644 index 0000000..e6ae0f3 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/dto/SynergyResult.java @@ -0,0 +1,18 @@ +package com.alterdekim.javabot.dto; + +import com.alterdekim.javabot.entities.ColumnType; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class SynergyResult { + private Long id; + private String firstEntityText; + private String secondEntityText; + private ColumnType firstType; + private ColumnType secondType; + private Float probabilityValue; +} diff --git a/src/main/java/com/alterdekim/javabot/dto/UserDTO.java b/src/main/java/com/alterdekim/javabot/dto/UserDTO.java new file mode 100644 index 0000000..90ad8cd --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/dto/UserDTO.java @@ -0,0 +1,23 @@ +package com.alterdekim.javabot.dto; + +import jakarta.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class UserDTO { + private Long id; + @NotEmpty(message = "Username should not be empty") + private String username; + @NotEmpty(message = "Password should not be empty") + private String password; + @NotEmpty(message = "Invite code should not be empty") + private String invite_code; + + private String lang; +} diff --git a/src/main/java/com/alterdekim/javabot/entities/AdditionalFacts.java b/src/main/java/com/alterdekim/javabot/entities/AdditionalFacts.java new file mode 100644 index 0000000..b52553e --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/AdditionalFacts.java @@ -0,0 +1,37 @@ +package com.alterdekim.javabot.entities; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "addfacts") +public class AdditionalFacts { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable=false) + private Float violence; + + @Column(nullable=false) + private Float power; + + @Column(nullable=false) + private Float food; + + @Column(nullable=false) + private Float heal; + + @Column(nullable = false) + private Float health_index; + + @Column(nullable = false) + private Long textDescId; +} diff --git a/src/main/java/com/alterdekim/javabot/entities/Bio.java b/src/main/java/com/alterdekim/javabot/entities/Bio.java new file mode 100644 index 0000000..e54fedf --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/Bio.java @@ -0,0 +1,42 @@ +package com.alterdekim.javabot.entities; + + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.JoinFormula; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "bio") +public class Bio { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + public Bio(Boolean isMale, Boolean isFemale, Boolean canDie, Long genderTextId) { + this.isMale = isMale; + this.isFemale = isFemale; + this.canDie = canDie; + this.genderTextId = genderTextId; + } + + @Column(nullable = false) + private Boolean isMale; + + @Column(nullable = false) + private Boolean isFemale; + + @Column(nullable = false) + private Boolean canDie; + + @Column(nullable = false) + private Long genderTextId; +} diff --git a/src/main/java/com/alterdekim/javabot/entities/ColumnType.java b/src/main/java/com/alterdekim/javabot/entities/ColumnType.java new file mode 100644 index 0000000..a18d535 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/ColumnType.java @@ -0,0 +1,9 @@ +package com.alterdekim.javabot.entities; + +public enum ColumnType { + Bio, + Health, + Hobby, + Luggage, + Work +} diff --git a/src/main/java/com/alterdekim/javabot/entities/Disaster.java b/src/main/java/com/alterdekim/javabot/entities/Disaster.java new file mode 100644 index 0000000..3555446 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/Disaster.java @@ -0,0 +1,31 @@ +package com.alterdekim.javabot.entities; + + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "disasters") +public class Disaster { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private Long nameTextId; + + @Column(nullable = false) + private Long descTextId; + + public Disaster(Long nameTextId, Long descTextId) { + this.nameTextId = nameTextId; + this.descTextId = descTextId; + } +} diff --git a/src/main/java/com/alterdekim/javabot/entities/GameStats.java b/src/main/java/com/alterdekim/javabot/entities/GameStats.java new file mode 100644 index 0000000..76d369c --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/GameStats.java @@ -0,0 +1,38 @@ +package com.alterdekim.javabot.entities; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "game_stats") +public class GameStats { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private Long gameId; + + @Column(nullable = false) + private Short turnNumber; + + @Column(nullable = false) + private Double probability; + + @Column(nullable = false) + private Integer playersCount; + + public GameStats(Long gameId, Short turnNumber, Double probability, Integer playersCount) { + this.gameId = gameId; + this.turnNumber = turnNumber; + this.probability = probability; + this.playersCount = playersCount; + } +} diff --git a/src/main/java/com/alterdekim/javabot/entities/Games.java b/src/main/java/com/alterdekim/javabot/entities/Games.java new file mode 100644 index 0000000..dede66c --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/Games.java @@ -0,0 +1,39 @@ +package com.alterdekim.javabot.entities; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "games_list") +public class Games { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private Boolean hasEnded; + + @Column(nullable = false) + private Boolean hasStoppedManually; + + @Column(nullable = false) + private Boolean isWon; + + @Column(nullable = false) + private Long started; + + public Games(Boolean hasEnded, Boolean hasStoppedManually, Boolean isWon, Long started) { + this.hasEnded = hasEnded; + this.hasStoppedManually = hasStoppedManually; + this.isWon = isWon; + this.started = started; + } +} diff --git a/src/main/java/com/alterdekim/javabot/entities/Health.java b/src/main/java/com/alterdekim/javabot/entities/Health.java new file mode 100644 index 0000000..d7de87a --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/Health.java @@ -0,0 +1,43 @@ +package com.alterdekim.javabot.entities; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.JoinFormula; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; +import java.util.Set; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "health") +public class Health { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private Float health_index; + + @Column(nullable = false) + private Long textNameId; + + @Column(nullable = false) + private Long textDescId; + + @Column(nullable = false) + private Boolean isChildfree; + + public Health(Float health_index, Long textNameId, Long textDescId, Boolean isChildfree) { + this.health_index = health_index; + this.textNameId = textNameId; + this.textDescId = textDescId; + this.isChildfree = isChildfree; + } +} diff --git a/src/main/java/com/alterdekim/javabot/entities/Hobby.java b/src/main/java/com/alterdekim/javabot/entities/Hobby.java new file mode 100644 index 0000000..4c88abf --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/Hobby.java @@ -0,0 +1,51 @@ +package com.alterdekim.javabot.entities; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.JoinFormula; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "hobby") +public class Hobby { + + public Hobby(Float foodstuffs, Float power, Float violence, Float asocial, Long textDescId) { + this.foodstuffs = foodstuffs; + this.power = power; + this.violence = violence; + this.asocial = asocial; + this.textDescId = textDescId; + } + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private Float asocial; + + @Column(nullable=false) + private Float power; + + @Column(nullable=false) + private Float violence; + + @Column(nullable=false) + private Float foodstuffs; + + @Column(nullable = false) + private Long textDescId; + + public Double getValue() { + return ((this.getFoodstuffs().doubleValue() + + this.getPower().doubleValue()) / 2.0d) - (((this.getViolence().doubleValue() + this.getAsocial().doubleValue()) / 2.0d)); + } +} diff --git a/src/main/java/com/alterdekim/javabot/entities/Invite.java b/src/main/java/com/alterdekim/javabot/entities/Invite.java new file mode 100644 index 0000000..160ce79 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/Invite.java @@ -0,0 +1,22 @@ +package com.alterdekim.javabot.entities; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "invite_codes") +public class Invite { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable=false) + private String invite_code; +} diff --git a/src/main/java/com/alterdekim/javabot/entities/Luggage.java b/src/main/java/com/alterdekim/javabot/entities/Luggage.java new file mode 100644 index 0000000..c0bc8ca --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/Luggage.java @@ -0,0 +1,61 @@ +package com.alterdekim.javabot.entities; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.JoinColumnOrFormula; +import org.hibernate.annotations.JoinColumnsOrFormulas; +import org.hibernate.annotations.JoinFormula; +import org.hibernate.annotations.WhereJoinTable; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "luggage") +public class Luggage { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + public Luggage(Float violence, Float power, Float asocial, Float foodstuffs, Boolean garbage, Long textNameId, Long textDescId) { + this.violence = violence; + this.power = power; + this.asocial = asocial; + this.foodstuffs = foodstuffs; + this.garbage = garbage; + this.textNameId = textNameId; + this.textDescId = textDescId; + } + + @Column(nullable=false) + private Float violence; + + @Column(nullable=false) + private Float power; + + @Column(nullable = false) + private Float asocial; + + @Column(nullable=false) + private Float foodstuffs; + + @Column(nullable=false) + private Boolean garbage; + + @Column(nullable = false) + private Long textNameId; + + @Column(nullable = false) + private Long textDescId; + + public Double getValue() { + return ((this.getFoodstuffs().doubleValue() + + this.getPower().doubleValue()) * 0.5d) - (((this.getViolence().doubleValue() + this.getAsocial().doubleValue()) / 2.0d)); + } +} diff --git a/src/main/java/com/alterdekim/javabot/entities/Role.java b/src/main/java/com/alterdekim/javabot/entities/Role.java new file mode 100644 index 0000000..fec5c75 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/Role.java @@ -0,0 +1,28 @@ +package com.alterdekim.javabot.entities; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Setter +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name="roles") +public class Role +{ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable=false, unique=true) + private String name; + + @ManyToMany(mappedBy="roles") + private List users; +} diff --git a/src/main/java/com/alterdekim/javabot/entities/Synergy.java b/src/main/java/com/alterdekim/javabot/entities/Synergy.java new file mode 100644 index 0000000..830a26c --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/Synergy.java @@ -0,0 +1,42 @@ +package com.alterdekim.javabot.entities; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "synergy") +public class Synergy { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private Long firstEntityId; + + @Enumerated(EnumType.ORDINAL) + private ColumnType firstType; + + @Column(nullable = false) + private Long secondEntityId; + + @Enumerated(EnumType.ORDINAL) + private ColumnType secondType; + + @Column(nullable = false) + private Float probabilityValue; + + public Synergy(Long firstEntityId, ColumnType firstType, Long secondEntityId, ColumnType secondType, Float probabilityValue) { + this.firstEntityId = firstEntityId; + this.firstType = firstType; + this.secondEntityId = secondEntityId; + this.secondType = secondType; + this.probabilityValue = probabilityValue; + } +} diff --git a/src/main/java/com/alterdekim/javabot/entities/TextDataVal.java b/src/main/java/com/alterdekim/javabot/entities/TextDataVal.java new file mode 100644 index 0000000..a342e9c --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/TextDataVal.java @@ -0,0 +1,28 @@ +package com.alterdekim.javabot.entities; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "textdata_val") +public class TextDataVal { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(length = 65555) + @NotNull + private String text; + + public TextDataVal(String text) { + this.text = text; + } +} diff --git a/src/main/java/com/alterdekim/javabot/entities/User.java b/src/main/java/com/alterdekim/javabot/entities/User.java new file mode 100644 index 0000000..ad0029a --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/User.java @@ -0,0 +1,39 @@ +package com.alterdekim.javabot.entities; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name="users") +public class User { + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable=false, unique=true) + private String username; + + @Column(nullable=false) + private String password; + + @ManyToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL) + @JoinTable( + name="users_roles", + joinColumns={@JoinColumn(name="USER_ID", referencedColumnName="ID")}, + inverseJoinColumns={@JoinColumn(name="ROLE_ID", referencedColumnName="ID")}) + private List roles = new ArrayList<>(); + +} \ No newline at end of file diff --git a/src/main/java/com/alterdekim/javabot/entities/Work.java b/src/main/java/com/alterdekim/javabot/entities/Work.java new file mode 100644 index 0000000..28e5a3b --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/entities/Work.java @@ -0,0 +1,55 @@ +package com.alterdekim.javabot.entities; + + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.JoinFormula; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "work") +public class Work { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable=false) + private Float asocial; + + @Column(nullable=false) + private Float power; + + @Column(nullable=false) + private Float violence; + + @Column(nullable=false) + private Float foodstuffs; + + @Column(nullable = false) + private Long textNameId; + + @Column(nullable = false) + private Long textDescId; + + public Work(Float asocial, Float power, Float violence, Float foodstuffs, Long textNameId, Long textDescId) { + this.asocial = asocial; + this.power = power; + this.violence = violence; + this.foodstuffs = foodstuffs; + this.textNameId = textNameId; + this.textDescId = textDescId; + } + + public Double getValue() { + return ((this.getFoodstuffs().doubleValue() + + this.getPower().doubleValue()) * 0.5d) - (((this.getViolence().doubleValue() + this.getAsocial().doubleValue()) / 2.0d)); + } +} diff --git a/src/main/java/com/alterdekim/javabot/handler/CustomAccessDeniedHandler.java b/src/main/java/com/alterdekim/javabot/handler/CustomAccessDeniedHandler.java new file mode 100644 index 0000000..db67100 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/handler/CustomAccessDeniedHandler.java @@ -0,0 +1,15 @@ +package com.alterdekim.javabot.handler; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; + +import java.io.IOException; + +public class CustomAccessDeniedHandler implements AccessDeniedHandler { + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException { + response.sendRedirect("/access-denied"); + } +} diff --git a/src/main/java/com/alterdekim/javabot/repository/AdditionalFactsRepository.java b/src/main/java/com/alterdekim/javabot/repository/AdditionalFactsRepository.java new file mode 100644 index 0000000..85f75d8 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/repository/AdditionalFactsRepository.java @@ -0,0 +1,13 @@ +package com.alterdekim.javabot.repository; + +import com.alterdekim.javabot.entities.AdditionalFacts; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Optional; + +public interface AdditionalFactsRepository extends JpaRepository { + Optional findById(Long id); + + List findAll(); +} diff --git a/src/main/java/com/alterdekim/javabot/repository/BioRepository.java b/src/main/java/com/alterdekim/javabot/repository/BioRepository.java new file mode 100644 index 0000000..775deb1 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/repository/BioRepository.java @@ -0,0 +1,19 @@ +package com.alterdekim.javabot.repository; + +import com.alterdekim.javabot.entities.Bio; +import com.alterdekim.javabot.entities.Synergy; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Optional; + +public interface BioRepository extends JpaRepository { + Optional findById(Long id); + + List findAll(); + + @Query(value = "SELECT new Synergy(s.id, s.firstEntityId, s.firstType, s.secondEntityId, s.secondType, s.probabilityValue) FROM Synergy s WHERE (s.firstType = 0 AND s.firstEntityId = :uuid) OR (s.secondType = 0 AND s.secondEntityId = :uuid)") + List getSynergies(@Param(value = "uuid") Long bioId); +} \ No newline at end of file diff --git a/src/main/java/com/alterdekim/javabot/repository/DisasterRepository.java b/src/main/java/com/alterdekim/javabot/repository/DisasterRepository.java new file mode 100644 index 0000000..ed84f69 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/repository/DisasterRepository.java @@ -0,0 +1,13 @@ +package com.alterdekim.javabot.repository; + +import com.alterdekim.javabot.entities.Disaster; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Optional; + +public interface DisasterRepository extends JpaRepository { + Optional findById(Long id); + + List findAll(); +} diff --git a/src/main/java/com/alterdekim/javabot/repository/HealthRepository.java b/src/main/java/com/alterdekim/javabot/repository/HealthRepository.java new file mode 100644 index 0000000..910e9cf --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/repository/HealthRepository.java @@ -0,0 +1,19 @@ +package com.alterdekim.javabot.repository; + +import com.alterdekim.javabot.entities.Health; +import com.alterdekim.javabot.entities.Synergy; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Optional; + +public interface HealthRepository extends JpaRepository { + Optional findById(Long id); + + List findAll(); + + @Query(value = "SELECT new Synergy(s.id, s.firstEntityId, s.firstType, s.secondEntityId, s.secondType, s.probabilityValue) FROM Synergy s WHERE (s.firstType = 1 AND s.firstEntityId = :uuid) OR (s.secondType = 1 AND s.secondEntityId = :uuid)") + List getSynergies(@Param(value = "uuid") Long healthId); +} diff --git a/src/main/java/com/alterdekim/javabot/repository/HobbyRepository.java b/src/main/java/com/alterdekim/javabot/repository/HobbyRepository.java new file mode 100644 index 0000000..5f988d5 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/repository/HobbyRepository.java @@ -0,0 +1,19 @@ +package com.alterdekim.javabot.repository; + +import com.alterdekim.javabot.entities.Hobby; +import com.alterdekim.javabot.entities.Synergy; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Optional; + +public interface HobbyRepository extends JpaRepository { + Optional findById(Long id); + + List findAll(); + + @Query(value = "SELECT new Synergy(s.id, s.firstEntityId, s.firstType, s.secondEntityId, s.secondType, s.probabilityValue) FROM Synergy s WHERE (s.firstType = 2 AND s.firstEntityId = :uuid) OR (s.secondType = 2 AND s.secondEntityId = :uuid)") + List getSynergies(@Param(value = "uuid") Long hobbId); +} diff --git a/src/main/java/com/alterdekim/javabot/repository/InviteRepository.java b/src/main/java/com/alterdekim/javabot/repository/InviteRepository.java new file mode 100644 index 0000000..99d21e0 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/repository/InviteRepository.java @@ -0,0 +1,10 @@ +package com.alterdekim.javabot.repository; + +import com.alterdekim.javabot.entities.Invite; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface InviteRepository extends JpaRepository { + Optional findById(Integer id); +} diff --git a/src/main/java/com/alterdekim/javabot/repository/LuggageRepository.java b/src/main/java/com/alterdekim/javabot/repository/LuggageRepository.java new file mode 100644 index 0000000..16eec7e --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/repository/LuggageRepository.java @@ -0,0 +1,19 @@ +package com.alterdekim.javabot.repository; + +import com.alterdekim.javabot.entities.Luggage; +import com.alterdekim.javabot.entities.Synergy; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Optional; + +public interface LuggageRepository extends JpaRepository { + Optional findById(Long id); + + List findAll(); + + @Query(value = "SELECT new Synergy(s.id, s.firstEntityId, s.firstType, s.secondEntityId, s.secondType, s.probabilityValue) FROM Synergy s WHERE (s.firstType = 3 AND s.firstEntityId = :uuid) OR (s.secondType = 3 AND s.secondEntityId = :uuid)") + List getSynergies(@Param(value = "uuid") Long luggId); +} diff --git a/src/main/java/com/alterdekim/javabot/repository/RoleRepository.java b/src/main/java/com/alterdekim/javabot/repository/RoleRepository.java new file mode 100644 index 0000000..23f4d38 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/repository/RoleRepository.java @@ -0,0 +1,12 @@ +package com.alterdekim.javabot.repository; + +import com.alterdekim.javabot.entities.Role; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface RoleRepository extends JpaRepository { + Role findByName(String name); + + List findAll(); +} diff --git a/src/main/java/com/alterdekim/javabot/repository/SynergyRepository.java b/src/main/java/com/alterdekim/javabot/repository/SynergyRepository.java new file mode 100644 index 0000000..37f8112 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/repository/SynergyRepository.java @@ -0,0 +1,13 @@ +package com.alterdekim.javabot.repository; + +import com.alterdekim.javabot.entities.Synergy; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Optional; + +public interface SynergyRepository extends JpaRepository { + Optional findById(Long id); + + List findAll(); +} diff --git a/src/main/java/com/alterdekim/javabot/repository/TextDataValRepository.java b/src/main/java/com/alterdekim/javabot/repository/TextDataValRepository.java new file mode 100644 index 0000000..4960c75 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/repository/TextDataValRepository.java @@ -0,0 +1,10 @@ +package com.alterdekim.javabot.repository; + +import com.alterdekim.javabot.entities.TextDataVal; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface TextDataValRepository extends JpaRepository { + Optional findById(Long id); +} diff --git a/src/main/java/com/alterdekim/javabot/repository/UserRepository.java b/src/main/java/com/alterdekim/javabot/repository/UserRepository.java new file mode 100644 index 0000000..ff69e29 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/repository/UserRepository.java @@ -0,0 +1,11 @@ +package com.alterdekim.javabot.repository; + +import com.alterdekim.javabot.entities.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends JpaRepository { + User findByUsername(String username); + +} diff --git a/src/main/java/com/alterdekim/javabot/repository/WorkRepository.java b/src/main/java/com/alterdekim/javabot/repository/WorkRepository.java new file mode 100644 index 0000000..8ddfbaa --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/repository/WorkRepository.java @@ -0,0 +1,19 @@ +package com.alterdekim.javabot.repository; + +import com.alterdekim.javabot.entities.Synergy; +import com.alterdekim.javabot.entities.Work; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Optional; + +public interface WorkRepository extends JpaRepository { + Optional findById(Long id); + + List findAll(); + + @Query(value = "SELECT new Synergy(s.id, s.firstEntityId, s.firstType, s.secondEntityId, s.secondType, s.probabilityValue) FROM Synergy s WHERE (s.firstType = 4 AND s.firstEntityId = :uuid) OR (s.secondType = 4 AND s.secondEntityId = :uuid)") + List getSynergies(@Param(value = "uuid") Long workId); +} diff --git a/src/main/java/com/alterdekim/javabot/security/SpringSecurity.java b/src/main/java/com/alterdekim/javabot/security/SpringSecurity.java new file mode 100644 index 0000000..d18c431 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/security/SpringSecurity.java @@ -0,0 +1,77 @@ +package com.alterdekim.javabot.security; + +import com.alterdekim.javabot.handler.CustomAccessDeniedHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +@Configuration +@EnableWebSecurity +public class SpringSecurity { + + @Autowired + private UserDetailsService userDetailsService; + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + HttpSessionRequestCache requestCache = new HttpSessionRequestCache(); + requestCache.setMatchingRequestParameterName(null); + http.csrf().disable() + .authorizeHttpRequests((authorize) -> + authorize + .requestMatchers("/panel").hasAnyAuthority("ROLE_ADMIN") + .requestMatchers("/api/**").hasAnyAuthority("ROLE_ADMIN") + .requestMatchers("/static/**").permitAll() + .requestMatchers("/access-denied").permitAll() + .requestMatchers("/signup").permitAll() + .requestMatchers("/favicon.ico").permitAll() + .requestMatchers("/signup/**").permitAll() + .requestMatchers("/").permitAll() + ).formLogin( + form -> form + .loginPage("/login") + .loginProcessingUrl("/login") + .failureForwardUrl("/") + .defaultSuccessUrl("/panel") + .permitAll() + ) + .logout( + logout -> logout + .logoutUrl("/logout") + .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) + .permitAll() + ) + .requestCache((cache) -> cache + .requestCache(requestCache) + ) + .exceptionHandling((exc) -> exc + .accessDeniedHandler(accessDeniedHandler()) + .accessDeniedPage("/access-denied")); + return http.build(); + } + + @Bean + public AccessDeniedHandler accessDeniedHandler() { + return new CustomAccessDeniedHandler(); + } + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); + } + + @Bean + public static PasswordEncoder passwordEncoder(){ + return new BCryptPasswordEncoder(); + } +} diff --git a/src/main/java/com/alterdekim/javabot/service/AdditionalFactsService.java b/src/main/java/com/alterdekim/javabot/service/AdditionalFactsService.java new file mode 100644 index 0000000..58c4905 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/AdditionalFactsService.java @@ -0,0 +1,10 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.AdditionalFacts; + +import java.util.List; + +public interface AdditionalFactsService { + List getAllFacts(); + AdditionalFacts getAdditionalFactById(long addFactId); +} diff --git a/src/main/java/com/alterdekim/javabot/service/AdditionalFactsServiceImpl.java b/src/main/java/com/alterdekim/javabot/service/AdditionalFactsServiceImpl.java new file mode 100644 index 0000000..eec227a --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/AdditionalFactsServiceImpl.java @@ -0,0 +1,27 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.AdditionalFacts; +import com.alterdekim.javabot.repository.AdditionalFactsRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class AdditionalFactsServiceImpl implements AdditionalFactsService { + + private AdditionalFactsRepository repository; + + public AdditionalFactsServiceImpl(AdditionalFactsRepository repository) { + this.repository = repository; + } + + @Override + public List getAllFacts() { + return repository.findAll(); + } + + @Override + public AdditionalFacts getAdditionalFactById(long addFactId) { + return repository.findById(addFactId).orElse(null); + } +} \ No newline at end of file diff --git a/src/main/java/com/alterdekim/javabot/service/BioService.java b/src/main/java/com/alterdekim/javabot/service/BioService.java new file mode 100644 index 0000000..87e0c37 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/BioService.java @@ -0,0 +1,17 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Bio; +import com.alterdekim.javabot.entities.Synergy; + +import java.util.List; + +public interface BioService { + List getAllBios(); + Bio getBioById(long bioId); + + void saveBio(Bio bio); + + void removeById(Long id); + + List getSynergies(Long id); +} diff --git a/src/main/java/com/alterdekim/javabot/service/BioServiceImpl.java b/src/main/java/com/alterdekim/javabot/service/BioServiceImpl.java new file mode 100644 index 0000000..5c6cb7a --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/BioServiceImpl.java @@ -0,0 +1,43 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Bio; +import com.alterdekim.javabot.entities.Synergy; +import com.alterdekim.javabot.repository.BioRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class BioServiceImpl implements BioService { + + private BioRepository repository; + + public BioServiceImpl(BioRepository repository) { + this.repository = repository; + } + + @Override + public List getAllBios() { + return repository.findAll(); + } + + @Override + public Bio getBioById(long bioId) { + return repository.findById(bioId).orElse(null); + } + + @Override + public void saveBio(Bio bio) { + repository.save(bio); + } + + @Override + public void removeById(Long id) { + repository.deleteById(id); + } + + @Override + public List getSynergies(Long id) { + return repository.getSynergies(id); + } +} diff --git a/src/main/java/com/alterdekim/javabot/service/CustomUserDetailsService.java b/src/main/java/com/alterdekim/javabot/service/CustomUserDetailsService.java new file mode 100644 index 0000000..967e411 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/CustomUserDetailsService.java @@ -0,0 +1,43 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Role; +import com.alterdekim.javabot.entities.User; +import com.alterdekim.javabot.repository.UserRepository; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.stream.Collectors; + +@Service +public class CustomUserDetailsService implements UserDetailsService { + + private final UserRepository userRepository; + + public CustomUserDetailsService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @Override + public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { + User user = userRepository.findByUsername(email); + + if (user != null) { + return new org.springframework.security.core.userdetails.User(user.getUsername(), + user.getPassword(), + mapRolesToAuthorities(user.getRoles())); + }else{ + throw new UsernameNotFoundException("Invalid username or password."); + } + } + + private Collection < ? extends GrantedAuthority> mapRolesToAuthorities(Collection roles) { + return roles.stream() + .map(role -> new SimpleGrantedAuthority(role.getName())) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/src/main/java/com/alterdekim/javabot/service/DisasterService.java b/src/main/java/com/alterdekim/javabot/service/DisasterService.java new file mode 100644 index 0000000..0db270f --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/DisasterService.java @@ -0,0 +1,14 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Disaster; + +import java.util.List; + +public interface DisasterService { + List getAllDisasters(); + Disaster getDisasterById(long dId); + + void removeById(long dId); + + void saveDisaster(Disaster disaster); +} diff --git a/src/main/java/com/alterdekim/javabot/service/DisasterServiceImpl.java b/src/main/java/com/alterdekim/javabot/service/DisasterServiceImpl.java new file mode 100644 index 0000000..d695075 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/DisasterServiceImpl.java @@ -0,0 +1,37 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Disaster; +import com.alterdekim.javabot.repository.DisasterRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class DisasterServiceImpl implements DisasterService { + + private final DisasterRepository repository; + + public DisasterServiceImpl(DisasterRepository repository) { + this.repository = repository; + } + + @Override + public List getAllDisasters() { + return repository.findAll(); + } + + @Override + public Disaster getDisasterById(long dId) { + return repository.findById(dId).orElse(null); + } + + @Override + public void removeById(long dId) { + repository.deleteById(dId); + } + + @Override + public void saveDisaster(Disaster disaster) { + repository.save(disaster); + } +} diff --git a/src/main/java/com/alterdekim/javabot/service/HealthService.java b/src/main/java/com/alterdekim/javabot/service/HealthService.java new file mode 100644 index 0000000..299e6a0 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/HealthService.java @@ -0,0 +1,17 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Health; +import com.alterdekim.javabot.entities.Synergy; + +import java.util.List; + +public interface HealthService { + List getAllHealth(); + Health getHealthById(long healthId); + + void removeById(long healthId); + + void saveHealth(Health health); + + List getSynergies(Long id); +} diff --git a/src/main/java/com/alterdekim/javabot/service/HealthServiceImpl.java b/src/main/java/com/alterdekim/javabot/service/HealthServiceImpl.java new file mode 100644 index 0000000..34abae9 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/HealthServiceImpl.java @@ -0,0 +1,43 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Health; +import com.alterdekim.javabot.entities.Synergy; +import com.alterdekim.javabot.repository.HealthRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class HealthServiceImpl implements HealthService { + + private final HealthRepository repository; + + public HealthServiceImpl(HealthRepository repository) { + this.repository = repository; + } + + @Override + public List getAllHealth() { + return repository.findAll(); + } + + @Override + public Health getHealthById(long healthId) { + return repository.findById(healthId).orElse(null); + } + + @Override + public void removeById(long healthId) { + repository.deleteById(healthId); + } + + @Override + public void saveHealth(Health health) { + repository.save(health); + } + + @Override + public List getSynergies(Long id) { + return repository.getSynergies(id); + } +} diff --git a/src/main/java/com/alterdekim/javabot/service/HobbyService.java b/src/main/java/com/alterdekim/javabot/service/HobbyService.java new file mode 100644 index 0000000..9fa0a92 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/HobbyService.java @@ -0,0 +1,17 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Hobby; +import com.alterdekim.javabot.entities.Synergy; + +import java.util.List; + +public interface HobbyService { + List getAllHobbies(); + Hobby getHobbyById(long hobbyId); + + void saveHobby(Hobby hobby); + + void removeById(Long id); + + List getSynergies(Long id); +} diff --git a/src/main/java/com/alterdekim/javabot/service/HobbyServiceImpl.java b/src/main/java/com/alterdekim/javabot/service/HobbyServiceImpl.java new file mode 100644 index 0000000..4fc9fdb --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/HobbyServiceImpl.java @@ -0,0 +1,43 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Hobby; +import com.alterdekim.javabot.entities.Synergy; +import com.alterdekim.javabot.repository.HobbyRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class HobbyServiceImpl implements HobbyService { + + private final HobbyRepository repository; + + public HobbyServiceImpl(HobbyRepository repository) { + this.repository = repository; + } + + @Override + public List getAllHobbies() { + return repository.findAll(); + } + + @Override + public Hobby getHobbyById(long hobbyId) { + return repository.findById(hobbyId).orElse(null); + } + + @Override + public void saveHobby(Hobby hobby) { + repository.save(hobby); + } + + @Override + public void removeById(Long id) { + repository.deleteById(id); + } + + @Override + public List getSynergies(Long id) { + return repository.getSynergies(id); + } +} diff --git a/src/main/java/com/alterdekim/javabot/service/InviteService.java b/src/main/java/com/alterdekim/javabot/service/InviteService.java new file mode 100644 index 0000000..7fb7867 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/InviteService.java @@ -0,0 +1,7 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Invite; + +public interface InviteService { + Invite findById(Integer id); +} diff --git a/src/main/java/com/alterdekim/javabot/service/InviteServiceImpl.java b/src/main/java/com/alterdekim/javabot/service/InviteServiceImpl.java new file mode 100644 index 0000000..905d902 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/InviteServiceImpl.java @@ -0,0 +1,20 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Invite; +import com.alterdekim.javabot.repository.InviteRepository; +import org.springframework.stereotype.Service; + +@Service +public class InviteServiceImpl implements InviteService { + + private final InviteRepository repository; + + public InviteServiceImpl(InviteRepository repository) { + this.repository = repository; + } + + @Override + public Invite findById(Integer id) { + return repository.findById(id).orElse(null); + } +} diff --git a/src/main/java/com/alterdekim/javabot/service/LuggageService.java b/src/main/java/com/alterdekim/javabot/service/LuggageService.java new file mode 100644 index 0000000..25a9e55 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/LuggageService.java @@ -0,0 +1,17 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Luggage; +import com.alterdekim.javabot.entities.Synergy; + +import java.util.List; + +public interface LuggageService { + List getAllLuggages(); + Luggage getLuggageById(long luggageId); + + void removeById(long luggageId); + + void saveLuggage(Luggage luggage); + + List getSynergies(Long id); +} diff --git a/src/main/java/com/alterdekim/javabot/service/LuggageServiceImpl.java b/src/main/java/com/alterdekim/javabot/service/LuggageServiceImpl.java new file mode 100644 index 0000000..cf67719 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/LuggageServiceImpl.java @@ -0,0 +1,43 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Luggage; +import com.alterdekim.javabot.entities.Synergy; +import com.alterdekim.javabot.repository.LuggageRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class LuggageServiceImpl implements LuggageService { + + private final LuggageRepository repository; + + public LuggageServiceImpl(LuggageRepository repository) { + this.repository = repository; + } + + @Override + public List getAllLuggages() { + return repository.findAll(); + } + + @Override + public Luggage getLuggageById(long luggageId) { + return repository.findById(luggageId).orElse(null); + } + + @Override + public void removeById(long luggageId) { + repository.deleteById(luggageId); + } + + @Override + public void saveLuggage(Luggage luggage) { + repository.save(luggage); + } + + @Override + public List getSynergies(Long id) { + return repository.getSynergies(id); + } +} diff --git a/src/main/java/com/alterdekim/javabot/service/SynergyService.java b/src/main/java/com/alterdekim/javabot/service/SynergyService.java new file mode 100644 index 0000000..b356711 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/SynergyService.java @@ -0,0 +1,14 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Luggage; +import com.alterdekim.javabot.entities.Synergy; + +import java.util.List; + +public interface SynergyService { + void removeById(long synergyId); + + void saveSynergy(Synergy synergy); + + List getAllSynergies(); +} diff --git a/src/main/java/com/alterdekim/javabot/service/SynergyServiceImpl.java b/src/main/java/com/alterdekim/javabot/service/SynergyServiceImpl.java new file mode 100644 index 0000000..da6a9c3 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/SynergyServiceImpl.java @@ -0,0 +1,32 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Synergy; +import com.alterdekim.javabot.repository.SynergyRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class SynergyServiceImpl implements SynergyService { + + private final SynergyRepository repository; + + public SynergyServiceImpl(SynergyRepository repository) { + this.repository = repository; + } + + @Override + public void removeById(long synergyId) { + repository.deleteById(synergyId); + } + + @Override + public void saveSynergy(Synergy synergy) { + repository.save(synergy); + } + + @Override + public List getAllSynergies() { + return repository.findAll(); + } +} diff --git a/src/main/java/com/alterdekim/javabot/service/TextDataValService.java b/src/main/java/com/alterdekim/javabot/service/TextDataValService.java new file mode 100644 index 0000000..bf9c2d9 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/TextDataValService.java @@ -0,0 +1,12 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.TextDataVal; + +import java.util.List; + +public interface TextDataValService { + List getAllTexts(); + TextDataVal getTextDataValById(long textId); + + TextDataVal save(TextDataVal val); +} diff --git a/src/main/java/com/alterdekim/javabot/service/TextDataValServiceImpl.java b/src/main/java/com/alterdekim/javabot/service/TextDataValServiceImpl.java new file mode 100644 index 0000000..0fd3e9b --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/TextDataValServiceImpl.java @@ -0,0 +1,32 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.TextDataVal; +import com.alterdekim.javabot.repository.TextDataValRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class TextDataValServiceImpl implements TextDataValService { + + private final TextDataValRepository repository; + + public TextDataValServiceImpl(TextDataValRepository repository) { + this.repository = repository; + } + + @Override + public List getAllTexts() { + return repository.findAll(); + } + + @Override + public TextDataVal getTextDataValById(long textId) { + return repository.findById(textId).orElse(null); + } + + @Override + public TextDataVal save(TextDataVal val) { + return repository.save(val); + } +} diff --git a/src/main/java/com/alterdekim/javabot/service/UserService.java b/src/main/java/com/alterdekim/javabot/service/UserService.java new file mode 100644 index 0000000..ce37b8f --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/UserService.java @@ -0,0 +1,14 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.dto.UserDTO; +import com.alterdekim.javabot.entities.User; + +import java.util.List; + +public interface UserService { + void saveUser(UserDTO userDto); + + User findByUsername(String usernane); + + List findAllUsers(); +} diff --git a/src/main/java/com/alterdekim/javabot/service/UserServiceImpl.java b/src/main/java/com/alterdekim/javabot/service/UserServiceImpl.java new file mode 100644 index 0000000..4b3c4b3 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/UserServiceImpl.java @@ -0,0 +1,67 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.dto.UserDTO; +import com.alterdekim.javabot.entities.Role; +import com.alterdekim.javabot.entities.User; +import com.alterdekim.javabot.repository.RoleRepository; +import com.alterdekim.javabot.repository.UserRepository; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class UserServiceImpl implements UserService { + + private final UserRepository userRepository; + private final RoleRepository roleRepository; + private final PasswordEncoder passwordEncoder; + + public UserServiceImpl(UserRepository userRepository, + RoleRepository roleRepository, + PasswordEncoder passwordEncoder) { + this.userRepository = userRepository; + this.roleRepository = roleRepository; + this.passwordEncoder = passwordEncoder; + } + + @Override + public void saveUser(UserDTO userDto) { + User user = new User(); + user.setUsername(userDto.getUsername()); + + user.setPassword(passwordEncoder.encode(userDto.getPassword())); + Role role = roleRepository.findByName("ROLE_ADMIN"); + if(role == null){ + role = checkRoleExist(); + } + user.setRoles(Collections.singletonList(role)); + userRepository.save(user); + } + + @Override + public User findByUsername(String username) { + return userRepository.findByUsername(username); + } + + @Override + public List findAllUsers() { + List users = userRepository.findAll(); + return users.stream().map(this::convertEntityToDto) + .collect(Collectors.toList()); + } + + private UserDTO convertEntityToDto(User user){ + UserDTO userDto = new UserDTO(); + userDto.setUsername(user.getUsername()); + return userDto; + } + + private Role checkRoleExist() { + Role role = new Role(); + role.setName("ROLE_ADMIN"); + return roleRepository.save(role); + } +} diff --git a/src/main/java/com/alterdekim/javabot/service/WorkService.java b/src/main/java/com/alterdekim/javabot/service/WorkService.java new file mode 100644 index 0000000..9c7cd04 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/WorkService.java @@ -0,0 +1,17 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Synergy; +import com.alterdekim.javabot.entities.Work; + +import java.util.List; + +public interface WorkService { + List getAllWorks(); + Work getWorkById(long workId); + + void removeById(long workId); + + void saveWork(Work work); + + List getSynergies(Long id); +} \ No newline at end of file diff --git a/src/main/java/com/alterdekim/javabot/service/WorkServiceImpl.java b/src/main/java/com/alterdekim/javabot/service/WorkServiceImpl.java new file mode 100644 index 0000000..9168d34 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/service/WorkServiceImpl.java @@ -0,0 +1,43 @@ +package com.alterdekim.javabot.service; + +import com.alterdekim.javabot.entities.Synergy; +import com.alterdekim.javabot.entities.Work; +import com.alterdekim.javabot.repository.WorkRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class WorkServiceImpl implements WorkService { + + private final WorkRepository repository; + + public WorkServiceImpl(WorkRepository repository) { + this.repository = repository; + } + + @Override + public List getAllWorks() { + return repository.findAll(); + } + + @Override + public Work getWorkById(long workId) { + return repository.findById(workId).orElse(null); + } + + @Override + public void removeById(long workId) { + repository.deleteById(workId); + } + + @Override + public void saveWork(Work work) { + repository.save(work); + } + + @Override + public List getSynergies(Long id) { + return repository.getSynergies(id); + } +} diff --git a/src/main/java/com/alterdekim/javabot/storage/FileSystemStorageService.java b/src/main/java/com/alterdekim/javabot/storage/FileSystemStorageService.java new file mode 100644 index 0000000..5a4c83c --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/storage/FileSystemStorageService.java @@ -0,0 +1,106 @@ +package com.alterdekim.javabot.storage; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.stream.Stream; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.stereotype.Service; +import org.springframework.util.FileSystemUtils; +import org.springframework.web.multipart.MultipartFile; + +@Service +public class FileSystemStorageService implements StorageService { + + private final Path rootLocation; + + @Autowired + public FileSystemStorageService(StorageProperties properties) { + + if(properties.getLocation().trim().isEmpty()){ + throw new StorageException("File upload location can not be Empty."); + } + + this.rootLocation = Paths.get(new ClassPathResource(properties.getLocation()).getPath()); + } + + @Override + public void store(MultipartFile file) { + try { + if (file.isEmpty()) { + throw new StorageException("Failed to store empty file."); + } + Path destinationFile = this.rootLocation.resolve( + Paths.get(file.getOriginalFilename())) + .normalize().toAbsolutePath(); + if (!destinationFile.getParent().equals(this.rootLocation.toAbsolutePath())) { + throw new StorageException( + "Cannot store file outside current directory."); + } + try (InputStream inputStream = file.getInputStream()) { + Files.copy(inputStream, destinationFile, + StandardCopyOption.REPLACE_EXISTING); + } + } + catch (IOException e) { + throw new StorageException("Failed to store file.", e); + } + } + + @Override + public Stream loadAll() { + try { + return Files.walk(this.rootLocation, 1) + .filter(path -> !path.equals(this.rootLocation)) + .map(this.rootLocation::relativize); + } + catch (IOException e) { + throw new StorageException("Failed to read stored files", e); + } + + } + + @Override + public Path load(String filename) { + return rootLocation.resolve(filename); + } + + @Override + public Resource loadAsResource(String filename) { + try { + Resource resource = new ClassPathResource(filename); + if (resource.exists() || resource.isReadable()) { + return resource; + } + else { + throw new StorageFileNotFoundException( + "Could not read file: " + filename); + + } + } + catch (Exception e) { + throw new StorageFileNotFoundException("Could not read file: " + filename, e); + } + } + + @Override + public void deleteAll() { + FileSystemUtils.deleteRecursively(rootLocation.toFile()); + } + + @Override + public void init() { + // try { + // Files.createDirectories(rootLocation); + // } + // catch (IOException e) { + // throw new StorageException("Could not initialize storage", e); + // } + } +} diff --git a/src/main/java/com/alterdekim/javabot/storage/StorageException.java b/src/main/java/com/alterdekim/javabot/storage/StorageException.java new file mode 100644 index 0000000..8448d2e --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/storage/StorageException.java @@ -0,0 +1,13 @@ +package com.alterdekim.javabot.storage; + + +public class StorageException extends RuntimeException { + + public StorageException(String message) { + super(message); + } + + public StorageException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/alterdekim/javabot/storage/StorageFileNotFoundException.java b/src/main/java/com/alterdekim/javabot/storage/StorageFileNotFoundException.java new file mode 100644 index 0000000..e137461 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/storage/StorageFileNotFoundException.java @@ -0,0 +1,12 @@ +package com.alterdekim.javabot.storage; + +public class StorageFileNotFoundException extends StorageException { + + public StorageFileNotFoundException(String message) { + super(message); + } + + public StorageFileNotFoundException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/src/main/java/com/alterdekim/javabot/storage/StorageProperties.java b/src/main/java/com/alterdekim/javabot/storage/StorageProperties.java new file mode 100644 index 0000000..e0efe60 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/storage/StorageProperties.java @@ -0,0 +1,13 @@ +package com.alterdekim.javabot.storage; + + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Setter +@Getter +@ConfigurationProperties("storage") +public class StorageProperties { + private String location = "static"; +} \ No newline at end of file diff --git a/src/main/java/com/alterdekim/javabot/storage/StorageService.java b/src/main/java/com/alterdekim/javabot/storage/StorageService.java new file mode 100644 index 0000000..ff3475d --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/storage/StorageService.java @@ -0,0 +1,23 @@ +package com.alterdekim.javabot.storage; + +import org.springframework.core.io.Resource; +import org.springframework.web.multipart.MultipartFile; + +import java.nio.file.Path; +import java.util.stream.Stream; + +public interface StorageService { + + void init(); + + void store(MultipartFile file); + + Stream loadAll(); + + Path load(String filename); + + Resource loadAsResource(String filename); + + void deleteAll(); + +} diff --git a/src/main/java/com/alterdekim/javabot/util/BotUtils.java b/src/main/java/com/alterdekim/javabot/util/BotUtils.java new file mode 100644 index 0000000..133f324 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/util/BotUtils.java @@ -0,0 +1,99 @@ +package com.alterdekim.javabot.util; + +import com.alterdekim.javabot.Constants; +import com.alterdekim.javabot.bot.InfoSections; +import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup; +import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton; + +import java.util.*; + +public class BotUtils { + public static InlineKeyboardMarkup getJoinKeyboard() { + InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup(); + List> columns = new ArrayList<>(); + InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton(); + inlineKeyboardButton.setText(Constants.JOIN_GAME_BTN); + inlineKeyboardButton.setCallbackData(HashUtils.bytesToHex(Constants.JOIN_GAME_BTN.getBytes())); + List keyboardButtonsRow1 = new ArrayList<>(); + keyboardButtonsRow1.add(inlineKeyboardButton); + columns.add(keyboardButtonsRow1); + InlineKeyboardButton inlineKeyboardButton1 = new InlineKeyboardButton(); + inlineKeyboardButton1.setText(Constants.START_GAME_BTN); + inlineKeyboardButton1.setCallbackData(HashUtils.bytesToHex(Constants.START_GAME_BTN.getBytes())); + List keyboardButtonsRow2 = new ArrayList<>(); + keyboardButtonsRow2.add(inlineKeyboardButton1); + columns.add(keyboardButtonsRow2); + inlineKeyboardMarkup.setKeyboard(columns); + return inlineKeyboardMarkup; + } + + public static InlineKeyboardMarkup getShowKeyboard(InfoSections infoSections) { + InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup(); + List> columns = new ArrayList<>(); + if( !infoSections.getIsHobbyShowed() ) { + InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton(); + inlineKeyboardButton.setText(Constants.HOBBY_BTN); + inlineKeyboardButton.setCallbackData(HashUtils.bytesToHex(Constants.HOBBY_BTN.getBytes())); + columns.add(Collections.singletonList(inlineKeyboardButton)); + } + if( !infoSections.getIsAgeShowed() ) { + InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton(); + inlineKeyboardButton.setText(Constants.AGE_BTN); + inlineKeyboardButton.setCallbackData(HashUtils.bytesToHex(Constants.AGE_BTN.getBytes())); + columns.add(Collections.singletonList(inlineKeyboardButton)); + } + if( !infoSections.getIsGenderShowed() ) { + InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton(); + inlineKeyboardButton.setText(Constants.GENDER_BTN); + inlineKeyboardButton.setCallbackData(HashUtils.bytesToHex(Constants.GENDER_BTN.getBytes())); + columns.add(Collections.singletonList(inlineKeyboardButton)); + } + if( !infoSections.getIsHealthShowed() ) { + InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton(); + inlineKeyboardButton.setText(Constants.HEALTH_BTN); + inlineKeyboardButton.setCallbackData(HashUtils.bytesToHex(Constants.HEALTH_BTN.getBytes())); + columns.add(Collections.singletonList(inlineKeyboardButton)); + } + if( !infoSections.getIsWorkShowed() ) { + InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton(); + inlineKeyboardButton.setText(Constants.WORK_BTN); + inlineKeyboardButton.setCallbackData(HashUtils.bytesToHex(Constants.WORK_BTN.getBytes())); + columns.add(Collections.singletonList(inlineKeyboardButton)); + } + if( !infoSections.getIsLuggageShowed() ) { + InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton(); + inlineKeyboardButton.setText(Constants.LUGG_BTN); + inlineKeyboardButton.setCallbackData(HashUtils.bytesToHex(Constants.LUGG_BTN.getBytes())); + columns.add(Collections.singletonList(inlineKeyboardButton)); + } + inlineKeyboardMarkup.setKeyboard(columns); + return inlineKeyboardMarkup; + } + + public static InlineKeyboardMarkup getGameTypeKeyboard() { + InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup(); + List> columns = new ArrayList<>(); + InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton(); + inlineKeyboardButton.setText(Constants.PROBABILITY); + inlineKeyboardButton.setCallbackData(HashUtils.bytesToHex(Constants.PROBABILITY.getBytes())); + List keyboardButtonsRow1 = new ArrayList<>(); + keyboardButtonsRow1.add(inlineKeyboardButton); + columns.add(keyboardButtonsRow1); + InlineKeyboardButton inlineKeyboardButton1 = new InlineKeyboardButton(); + inlineKeyboardButton1.setText(Constants.DEATHMATCH); + inlineKeyboardButton1.setCallbackData(HashUtils.bytesToHex(Constants.DEATHMATCH.getBytes())); + List keyboardButtonsRow2 = new ArrayList<>(); + keyboardButtonsRow2.add(inlineKeyboardButton1); + columns.add(keyboardButtonsRow2); + inlineKeyboardMarkup.setKeyboard(columns); + return inlineKeyboardMarkup; + } + + public static String mentionUser(String name) { + return " @"+name+" "; + } + + public static Object getRandomFromList(List list, Random random) { + return list.get(random.nextInt(list.size())); + } +} diff --git a/src/main/java/com/alterdekim/javabot/util/Clamp.java b/src/main/java/com/alterdekim/javabot/util/Clamp.java new file mode 100644 index 0000000..9a2d016 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/util/Clamp.java @@ -0,0 +1,7 @@ +package com.alterdekim.javabot.util; + +public class Clamp { + public static double clamp(double value, double min, double max) { + return Math.max(min, Math.min(max, value)); + } +} diff --git a/src/main/java/com/alterdekim/javabot/util/GameState.java b/src/main/java/com/alterdekim/javabot/util/GameState.java new file mode 100644 index 0000000..780907d --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/util/GameState.java @@ -0,0 +1,7 @@ +package com.alterdekim.javabot.util; + +public enum GameState { + NONE, + JOINING, + STARTED +} diff --git a/src/main/java/com/alterdekim/javabot/util/HashUtils.java b/src/main/java/com/alterdekim/javabot/util/HashUtils.java new file mode 100644 index 0000000..a5878e2 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/util/HashUtils.java @@ -0,0 +1,59 @@ +package com.alterdekim.javabot.util; + +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; + +@Slf4j +public class HashUtils { + public static String md5(String s) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] theMD5digest = md.digest(s.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(theMD5digest); + } catch ( Exception e ) { + log.error(e.getMessage()); + } + return null; + } + + public static byte[] decodeHexString(String hexString) { + if (hexString.length() % 2 == 1) { + throw new IllegalArgumentException( + "Invalid hexadecimal String supplied."); + } + + byte[] bytes = new byte[hexString.length() / 2]; + for (int i = 0; i < hexString.length(); i += 2) { + bytes[i / 2] = hexToByte(hexString.substring(i, i + 2)); + } + return bytes; + } + + private static byte hexToByte(String hexString) { + int firstDigit = toDigit(hexString.charAt(0)); + int secondDigit = toDigit(hexString.charAt(1)); + return (byte) ((firstDigit << 4) + secondDigit); + } + + private static int toDigit(char hexChar) { + int digit = Character.digit(hexChar, 16); + if(digit == -1) { + throw new IllegalArgumentException( + "Invalid Hexadecimal Character: "+ hexChar); + } + return digit; + } + + private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII); + public static String bytesToHex(byte[] bytes) { + byte[] hexChars = new byte[bytes.length * 2]; + for (int j = 0; j < bytes.length; j++) { + int v = bytes[j] & 0xFF; + hexChars[j * 2] = HEX_ARRAY[v >>> 4]; + hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; + } + return new String(hexChars, StandardCharsets.UTF_8); + } +} diff --git a/src/main/java/com/alterdekim/javabot/util/PseudoRandom.java b/src/main/java/com/alterdekim/javabot/util/PseudoRandom.java new file mode 100644 index 0000000..eb44406 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/util/PseudoRandom.java @@ -0,0 +1,27 @@ +package com.alterdekim.javabot.util; + +public class PseudoRandom { + private final double seed; + + private double i = 0; + + public PseudoRandom( double seed ) { + assert seed > 0 && seed < 1; + this.seed = seed; + } + + public PseudoRandom() { + this.seed = 1; + } + + public double next() { + double f = ((Math.cos(3d * i) * Math.cos(3d * i) * Math.sin(3d * i)) * 1.3333d * Math.cos(i) * Math.cos(i)) + 0.5d; + i += seed; + i = i % 6.2d; + return f; + } + + public int nextInt(int bound) { + return (int) Math.floor(next() * ((double) bound)); + } +} diff --git a/src/main/java/com/alterdekim/javabot/util/UAgentInfo.java b/src/main/java/com/alterdekim/javabot/util/UAgentInfo.java new file mode 100644 index 0000000..c106fa7 --- /dev/null +++ b/src/main/java/com/alterdekim/javabot/util/UAgentInfo.java @@ -0,0 +1,490 @@ +package com.alterdekim.javabot.util; + +/* ******************************************* +// LICENSE INFORMATION +// The code, "Detecting Smartphones Using PHP" +// by Anthony Hand, is licensed under a Creative Commons +// Attribution 3.0 United States License. +// +// Updated 01 March 2010 by Bryan J Swift +// - Remove un-needed if statements instead just returning the boolean +// inside the if clause +// +// Updated 14 December 2009 by A Hand +// - Added the method for detecting BlackBerry Touch +// devices like the Storm 1 and 2. +// +// Updated 5 December 2009 by A Hand +// - Fixed the DetectPalmOS method. It should filter +// out WebOS devices. +// +// Updated 8 November 2009 by A Hand +// - Added the deviceWebOS variable. +// - Added Palm's WebOS to the DetectPalmOS method. +// - Created a new method to check for Palm's WebOS devices. +// - Added Palm's WebOS to the DetectTierIphone method. +// +// Updated 4 April 2009 by A Hand +// - Changed the name of the class from DetectSmartPhone to UAgentInfo. +// New name is more consistent with PHP and JavaScript classes. +// - Added a method to detect Opera Mobile and Mini. Opera Mobile is new. +// - Updated the algorithm for detecting a Sony Mylo. +// - Added Android to the DetectTierIphone method. +// - Updated comments for Detect Tier methods. +// +// Updated 22 January 2009 +// - Ported to Java from the PHP code by +// Satish Kumar Nookala, javasatish@yahoo.com +// +// Anthony Hand, ahand@hand-interactive.com +// Web: www.hand-interactive.com +// +// License info: http://creativecommons.org/licenses/by/3.0/us/ +// +// This code is provided AS IS with no expressed or implied warranty. +// You have the right to use this code or any portion of it +// so long as you provide credit toward myself as the original author. +// +// ******************************************* +*/ + +/** + * The DetectSmartPhone class encapsulates information about + * a browser's connection to your web site. + * You can use it to find out whether the browser asking for + * your site's content is probably running on a mobile device. + * The methods were written so you can be as granular as you want. + * For example, enquiring whether it's as specific as an iPod Touch or + * as general as a smartphone class device. + * The object's methods return true, or false. + */ +public class UAgentInfo { + // User-Agent and Accept HTTP request headers + private String userAgent = ""; + private String httpAccept = ""; + + // Initialize some initial smartphone string variables. + public static final String engineWebKit = "webkit"; + public static final String deviceAndroid = "android"; + public static final String deviceIphone = "iphone"; + public static final String deviceIpod = "ipod"; + public static final String deviceSymbian = "symbian"; + public static final String deviceS60 = "series60"; + public static final String deviceS70 = "series70"; + public static final String deviceS80 = "series80"; + public static final String deviceS90 = "series90"; + public static final String deviceWinMob = "windows ce"; + public static final String deviceWindows = "windows"; + public static final String deviceIeMob = "iemobile"; + public static final String enginePie = "wm5 pie"; //An old Windows Mobile + public static final String deviceBB = "blackberry"; + public static final String vndRIM = "vnd.rim"; //Detectable when BB devices emulate IE or Firefox + public static final String deviceBBStorm = "blackberry95"; //Storm 1 and 2 + public static final String devicePalm = "palm"; + public static final String deviceWebOS = "webos"; //For Palm's new WebOS devices + + public static final String engineBlazer = "blazer"; //Old Palm + public static final String engineXiino = "xiino"; //Another old Palm + + //Initialize variables for mobile-specific content. + public static final String vndwap = "vnd.wap"; + public static final String wml = "wml"; + + //Initialize variables for other random devices and mobile browsers. + public static final String deviceBrew = "brew"; + public static final String deviceDanger = "danger"; + public static final String deviceHiptop = "hiptop"; + public static final String devicePlaystation = "playstation"; + public static final String deviceNintendoDs = "nitro"; + public static final String deviceNintendo = "nintendo"; + public static final String deviceWii = "wii"; + public static final String deviceXbox = "xbox"; + public static final String deviceArchos = "archos"; + + public static final String engineOpera = "opera"; //Popular browser + public static final String engineNetfront = "netfront"; //Common embedded OS browser + public static final String engineUpBrowser = "up.browser"; //common on some phones + public static final String engineOpenWeb = "openweb"; //Transcoding by OpenWave server + public static final String deviceMidp = "midp"; //a mobile Java technology + public static final String uplink = "up.link"; + + public static final String devicePda = "pda"; //some devices report themselves as PDAs + public static final String mini = "mini"; //Some mobile browsers put "mini" in their names. + public static final String mobile = "mobile"; //Some mobile browsers put "mobile" in their user agent strings. + public static final String mobi = "mobi"; //Some mobile browsers put "mobi" in their user agent strings. + + //Use Maemo, Tablet, and Linux to test for Nokia"s Internet Tablets. + public static final String maemo = "maemo"; + public static final String maemoTablet = "tablet"; + public static final String linux = "linux"; + public static final String qtembedded = "qt embedded"; //for Sony Mylo + public static final String mylocom2 = "com2"; //for Sony Mylo also + + //In some UserAgents, the only clue is the manufacturer. + public static final String manuSonyEricsson = "sonyericsson"; + public static final String manuericsson = "ericsson"; + public static final String manuSamsung1 = "sec-sgh"; + public static final String manuSony = "sony"; + + //In some UserAgents, the only clue is the operator. + public static final String svcDocomo = "docomo"; + public static final String svcKddi = "kddi"; + public static final String svcVodafone = "vodafone"; + + // Standard desktop browser detection strings + public static final String msie = "MSIE"; + public static final String msie60 = "MSIE 6.0"; + public static final String msie61 = "MSIE 6.1"; + public static final String msie70 = "MSIE 7.0"; + public static final String msie8 = "MSIE 8.0"; + public static final String msie9 = "MSIE 9.0"; + /** + * Initialize the userAgent and httpAccept variables + * + * @param userAgent the User-Agent header + * @param httpAccept the Accept header + */ + public UAgentInfo(String userAgent, String httpAccept) { + if (userAgent != null) { + this.userAgent = userAgent.toLowerCase(); + } + if (httpAccept != null) { + this.httpAccept = httpAccept.toLowerCase(); + } + } + + /** + * Return the lower case HTTP_USER_AGENT + */ + public String getUserAgent() { + return userAgent; + } + + /** + * Return the lower case HTTP_ACCEPT + */ + public String getHttpAccept() { + return httpAccept; + } + + /** + * Detects if the current device is an iPhone. + */ + public boolean detectIphone() { + // The iPod touch says it's an iPhone! So let's disambiguate. + return userAgent.indexOf(deviceIphone) != -1 && !detectIpod(); + } + + /** + * Detects if the current device is an iPod Touch. + */ + public boolean detectIpod() { + return userAgent.indexOf(deviceIpod) != -1; + } + + /** + * Detects if the current device is an iPhone or iPod Touch. + */ + public boolean detectIphoneOrIpod() { + //We repeat the searches here because some iPods may report themselves as an iPhone, which would be okay. + return userAgent.indexOf(deviceIphone) != -1 || userAgent.indexOf(deviceIpod) != -1; + } + + /** + * Detects if the current device is an Android OS-based device. + */ + public boolean detectAndroid() { + return userAgent.indexOf(deviceAndroid) != -1; + } + + /** + * Detects if the current device is an Android OS-based device and + * the browser is based on WebKit. + */ + public boolean detectAndroidWebKit() { + return detectAndroid() && detectWebkit(); + } + + /** + * Detects if the current browser is based on WebKit. + */ + public boolean detectWebkit() { + return userAgent.indexOf(engineWebKit) != -1; + } + + /** + * Detects if the current browser is the S60 Open Source Browser. + */ + public boolean detectS60OssBrowser() { + //First, test for WebKit, then make sure it's either Symbian or S60. + return detectWebkit() && (userAgent.indexOf(deviceSymbian) != -1 || userAgent.indexOf(deviceS60) != -1); + } + + /** + * + * Detects if the current device is any Symbian OS-based device, + * including older S60, Series 70, Series 80, Series 90, and UIQ, + * or other browsers running on these devices. + */ + public boolean detectSymbianOS() { + return userAgent.indexOf(deviceSymbian) != -1 || userAgent.indexOf(deviceS60) != -1 || + userAgent.indexOf(deviceS70) != -1 || userAgent.indexOf(deviceS80) != -1 || + userAgent.indexOf(deviceS90) != -1; + } + + /** + * Detects if the current browser is a Windows Mobile device. + */ + public boolean detectWindowsMobile() { + //Most devices use 'Windows CE', but some report 'iemobile' + // and some older ones report as 'PIE' for Pocket IE. + return userAgent.indexOf(deviceWinMob) != -1 || + userAgent.indexOf(deviceIeMob) != -1 || + userAgent.indexOf(enginePie) != -1 || + (detectWapWml() && userAgent.indexOf(deviceWindows) != -1); + } + + /** + * Detects if the current browser is a BlackBerry of some sort. + */ + public boolean detectBlackBerry() { + return userAgent.indexOf(deviceBB) != -1 || httpAccept.indexOf(vndRIM) != -1; + } + + /** + * Detects if the current browser is a BlackBerry Touch + * device, such as the Storm + */ + public boolean detectBlackBerryTouch() { + return userAgent.indexOf(deviceBBStorm) != -1; + } + + /** + * Detects if the current browser is on a PalmOS device. + */ + public boolean detectPalmOS() { + //Most devices nowadays report as 'Palm', but some older ones reported as Blazer or Xiino. + if (userAgent.indexOf(devicePalm) != -1 || userAgent.indexOf(engineBlazer) != -1 || + userAgent.indexOf(engineXiino) != -1 && !detectPalmWebOS()) { + //Make sure it's not WebOS first + if (detectPalmWebOS()) { return false; } + else { return true; } + } + return false; + } + + /** + * Detects if the current browser is on a Palm device + * running the new WebOS. + */ + public boolean detectPalmWebOS() { + return userAgent.indexOf(deviceWebOS) != -1; + } + + /** + * Check to see whether the device is any device + * in the 'smartphone' category. + */ + public boolean detectSmartphone() { + return (detectIphoneOrIpod() || + detectS60OssBrowser() || + detectSymbianOS() || + detectWindowsMobile() || + detectBlackBerry() || + detectPalmOS() || + detectPalmWebOS() || + detectAndroid()); + } + + /** + * Detects whether the device is a Brew-powered device. + */ + public boolean detectBrewDevice() { + return userAgent.indexOf(deviceBrew) != -1; + } + + /** + * Detects the Danger Hiptop device. + */ + public boolean detectDangerHiptop() { + return userAgent.indexOf(deviceDanger) != -1 || userAgent.indexOf(deviceHiptop) != -1; + } + + /** + * Detects Opera Mobile or Opera Mini. + * Added by AHand + */ + public boolean detectOperaMobile() { + return userAgent.indexOf(engineOpera) != -1 && (userAgent.indexOf(mini) != -1 || userAgent.indexOf(mobi) != -1); + } + + /** + * Detects whether the device supports WAP or WML. + */ + public boolean detectWapWml() { + return httpAccept.indexOf(vndwap) != -1 || httpAccept.indexOf(wml) != -1; + } + + /** + * The quick way to detect for a mobile device. + * Will probably detect most recent/current mid-tier Feature Phones + * as well as smartphone-class devices. + */ + public boolean detectMobileQuick() { + //Ordered roughly by market share, WAP/XML > Brew > Smartphone. + if (detectWapWml()) { return true; } + if (detectBrewDevice()) { return true; } + + // Updated by AHand + if (detectOperaMobile()) { return true; } + + if (userAgent.indexOf(engineUpBrowser) != -1) { return true; } + if (userAgent.indexOf(engineOpenWeb) != -1) { return true; } + if (userAgent.indexOf(deviceMidp) != -1) { return true; } + + if (detectSmartphone()) { return true; } + if (detectDangerHiptop()) { return true; } + + if (detectMidpCapable()) { return true; } + + if (userAgent.indexOf(devicePda) != -1) { return true; } + if (userAgent.indexOf(mobile) != -1) { return true; } + + //detect older phones from certain manufacturers and operators. + if (userAgent.indexOf(uplink) != -1) { return true; } + if (userAgent.indexOf(manuSonyEricsson) != -1) { return true; } + if (userAgent.indexOf(manuericsson) != -1) { return true; } + if (userAgent.indexOf(manuSamsung1) != -1) { return true; } + if (userAgent.indexOf(svcDocomo) != -1) { return true; } + if (userAgent.indexOf(svcKddi) != -1) { return true; } + if (userAgent.indexOf(svcVodafone) != -1) { return true; } + + return false; + } + + /** + * Detects if the current device is a Sony Playstation. + */ + public boolean detectSonyPlaystation() { + return userAgent.indexOf(devicePlaystation) != -1; + } + + /** + * Detects if the current device is a Nintendo game device. + */ + public boolean detectNintendo() { + return userAgent.indexOf(deviceNintendo) != -1 || userAgent.indexOf(deviceWii) != -1 || + userAgent.indexOf(deviceNintendoDs) != -1; + } + + /** + * Detects if the current device is a Microsoft Xbox. + */ + public boolean detectXbox() { + return userAgent.indexOf(deviceXbox) != -1; + } + + /** + * Detects if the current device is an Internet-capable game console. + */ + public boolean detectGameConsole() { + return detectSonyPlaystation() || detectNintendo() || detectXbox(); + } + + /** + * Detects if the current device supports MIDP, a mobile Java technology. + */ + public boolean detectMidpCapable() { + return userAgent.indexOf(deviceMidp) != -1 || httpAccept.indexOf(deviceMidp) != -1; + } + + /** + * Detects if the current device is on one of the Maemo-based Nokia Internet Tablets. + */ + public boolean detectMaemoTablet() { + return (userAgent.indexOf(maemo) != -1 || (userAgent.indexOf(maemoTablet) != -1 && userAgent.indexOf(linux) != -1)); + } + + /** + * Detects if the current device is an Archos media player/Internet tablet. + */ + public boolean detectArchos() { + return userAgent.indexOf(deviceArchos) != -1; + } + + /** + * Detects if the current browser is a Sony Mylo device. + * Updated by AHand + */ + public boolean detectSonyMylo() { + return userAgent.indexOf(manuSony) != -1 && (userAgent.indexOf(qtembedded) != -1 || + userAgent.indexOf(mylocom2) != -1); + } + + /** + * The longer and more thorough way to detect for a mobile device. + * Will probably detect most feature phones, + * smartphone-class devices, Internet Tablets, + * Internet-enabled game consoles, etc. + * This ought to catch a lot of the more obscure and older devices, also -- + * but no promises on thoroughness! + */ + public boolean detectMobileLong() { + return detectMobileQuick() || detectMaemoTablet() || detectGameConsole(); + } + + //***************************** + // For Desktop Browsers + //***************************** + public boolean detectMSIE() { + return userAgent.indexOf(msie) != -1; + } + + public boolean detectMSIE6() { + return userAgent.indexOf(msie60) != -1 && userAgent.indexOf(msie61) != -1; + } + + public boolean detectMSIE7() { + return userAgent.indexOf(msie70) != -1; + } + + public boolean detectMSIE8() { + return userAgent.indexOf(msie8) != -1; + } + + public boolean detectMSIE9() { + return userAgent.indexOf(msie9) != -1; + } + + //***************************** + // For Mobile Web Site Design + //***************************** + + /** + * The quick way to detect for a tier of devices. + * This method detects for devices which can + * display iPhone-optimized web content. + * Includes iPhone, iPod Touch, Android, Palm WebOS, etc. + */ + public boolean detectTierIphone() { + return detectIphoneOrIpod() || detectPalmWebOS() || detectAndroid() || detectAndroidWebKit(); + } + + /** + * The quick way to detect for a tier of devices. + * This method detects for all smartphones, but + * excludes the iPhone Tier devices. + */ + public boolean detectTierSmartphones() { + return detectSmartphone() && (!detectTierIphone()); + } + + /** + * The quick way to detect for a tier of devices. + * This method detects for all other types of phones, + * but excludes the iPhone and Smartphone Tier devices. + */ + public boolean detectTierOtherPhones() { + return detectMobileQuick() && (!detectTierIphone()) && (!detectTierSmartphones()); + } +} diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties new file mode 100644 index 0000000..b3967c0 --- /dev/null +++ b/src/main/resources/messages_en.properties @@ -0,0 +1,57 @@ +signup=Sign up +signin=Sign in +remember=Remember me +pass=Password +nname=Nickname +login_error=Incorrect nickname or password +invitecode=Invite code +incorcred=Incorrect credentials +logote=Logout +rlang=Russian +elang=English +langl=Language +abby=Abilities +diss=Disasters +lugg=Luggage +heeal=Health +pprof=Profession +hhobb=Hobby +aggend=Gender +addata=Additional Data +pplay=Player +hhome=Home +aaccden=Access denied +oopsi=Opps! +badway= You're in a bad way. +light=Light +dark=Dark +auto=Auto +toggleth=Toggle theme +aedentry=Add(or edit) entry +inlcandie=Can die? +inlcfr=Childfree? +inlismal=Male? +inlisfem=Female? +inlgente=Gender label: +inlfood=Food +inlheal=Asocial +inlpower=Power +inlviol=Violence +hobblab=Hobby label: +inlgarb=Garbage? +inlaname=Name label: +inladesc=Description label: +inlhin=Health index +cancbt=Cancel +adddbtn=Add +edditbtn=Edit +remombtn=Remove +inlprobbb=Add probability +eddittsynn=Edit synergies +firentname=First entity name +firenttype=First entity type +secentname=Second entity name +secenttype=Second entity type +probbval=Probability value +actionbtn=Action +stats=Statistics \ No newline at end of file diff --git a/src/main/resources/messages_ru.properties b/src/main/resources/messages_ru.properties new file mode 100644 index 0000000..f684eda --- /dev/null +++ b/src/main/resources/messages_ru.properties @@ -0,0 +1,57 @@ +signup=Регистрация +signin=Войти +remember=Запомнить +pass=Пароль +nname=Ник +login_error=Неправильный ник или пароль +invitecode=Инвайт +incorcred=Неправильные данные +logote=Выйти +rlang=Русский +elang=Английский +langl=Язык +abby=Способности +diss=Катастрофы +lugg=Багаж +heeal=Здоровье +pprof=Профессия +hhobb=Хобби +aggend=Гендер +addata=Факты +pplay=Игрок +hhome=Главная +aaccden=Доступ запрещен +oopsi=Упс! +badway= Вас сюда не звали. +light=Светлая +dark=Тёмная +auto=Авто +toggleth=Переключить +aedentry=Добавить/изменить запись +inlcandie=Может умереть? +inlcfr=Бесплоден? +inlismal=Мужчина? +inlisfem=Женщина? +inlgente=Гендер(текст): +inlfood=Еда +inlheal=Асоциальность +inlpower=Сила +inlviol=Насилие +hobblab=Название хобби: +inlgarb=Мусор? +inlaname=Имя: +inladesc=Описание: +inlhin=Здоровье +cancbt=Отмена +adddbtn=Добавить +edditbtn=Изменить +remombtn=Удалить +inlprobbb=Add probability +eddittsynn=Синергии +firentname=Имя первой вещи +firenttype=Тип первой вещи +secentname=Имя второй вещи +secenttype=Тип второй вещи +probbval=Вероятность(знач) +actionbtn=Действие +stats=Статистика \ No newline at end of file diff --git a/src/main/resources/static/css/panel.css b/src/main/resources/static/css/panel.css new file mode 100644 index 0000000..74f5094 --- /dev/null +++ b/src/main/resources/static/css/panel.css @@ -0,0 +1,4 @@ +html, +body { + height: 100%; +} \ No newline at end of file diff --git a/src/main/resources/static/css/sign-in.css b/src/main/resources/static/css/sign-in.css new file mode 100644 index 0000000..3a6e982 --- /dev/null +++ b/src/main/resources/static/css/sign-in.css @@ -0,0 +1,25 @@ +html, +body { + height: 100%; +} + +.form-signin { + max-width: 330px; + padding: 1rem; +} + +.form-signin .form-floating:focus-within { + z-index: 2; +} + +.form-signin input[type="text"] { + margin-bottom: -1px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.form-signin input[type="password"] { + margin-bottom: 10px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} \ No newline at end of file diff --git a/src/main/resources/static/css/sign-up.css b/src/main/resources/static/css/sign-up.css new file mode 100644 index 0000000..a37e2c2 --- /dev/null +++ b/src/main/resources/static/css/sign-up.css @@ -0,0 +1,13 @@ +html, +body { + height: 100%; +} + +.form-signup { + max-width: 330px; + padding: 1rem; +} + +.form-signup .form-floating:focus-within { + z-index: 2; +} \ No newline at end of file diff --git a/src/main/resources/static/css/util.css b/src/main/resources/static/css/util.css new file mode 100644 index 0000000..cc01909 --- /dev/null +++ b/src/main/resources/static/css/util.css @@ -0,0 +1,8 @@ +/** + * Skipped minification because the original files appears to be already minified. + * Original file: /npm/@docsearch/css@3.5.2/dist/style.css + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +/*! @docsearch/css 3.5.2 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */ +:root{--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,0.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,0.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,0.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,0.12)}html[data-theme=dark]{--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,0.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,0.3);--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,0.5),0 -4px 8px 0 rgba(0,0,0,0.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}.DocSearch-Button{align-items:center;background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;font-weight:500;height:36px;justify-content:space-between;margin:0 0 0 16px;padding:0 8px;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:none}.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;position:relative;padding:0 0 2px;border:0;top:-1px;width:20px}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:2px;box-shadow:var(--docsearch-key-shadow);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;color:var(--docsearch-muted-color);border:0;width:20px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}} \ No newline at end of file diff --git a/src/main/resources/static/javascript/color-modes.js b/src/main/resources/static/javascript/color-modes.js new file mode 100644 index 0000000..0fc9d66 --- /dev/null +++ b/src/main/resources/static/javascript/color-modes.js @@ -0,0 +1,80 @@ +/*! + * Color mode toggler for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + */ + +(() => { + 'use strict' + + const getStoredTheme = () => localStorage.getItem('theme') + const setStoredTheme = theme => localStorage.setItem('theme', theme) + + const getPreferredTheme = () => { + const storedTheme = getStoredTheme() + if (storedTheme) { + return storedTheme + } + + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' + } + + const setTheme = theme => { + if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.documentElement.setAttribute('data-bs-theme', 'dark') + } else { + document.documentElement.setAttribute('data-bs-theme', theme) + } + } + + setTheme(getPreferredTheme()) + + const showActiveTheme = (theme, focus = false) => { + const themeSwitcher = document.querySelector('#bd-theme') + + if (!themeSwitcher) { + return + } + + const themeSwitcherText = document.querySelector('#bd-theme-text') + const activeThemeIcon = document.querySelector('.theme-icon-active use') + const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`) + const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href') + + document.querySelectorAll('[data-bs-theme-value]').forEach(element => { + element.classList.remove('active') + element.setAttribute('aria-pressed', 'false') + }) + + btnToActive.classList.add('active') + btnToActive.setAttribute('aria-pressed', 'true') + activeThemeIcon.setAttribute('href', svgOfActiveBtn) + const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})` + themeSwitcher.setAttribute('aria-label', themeSwitcherLabel) + + if (focus) { + themeSwitcher.focus() + } + } + + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { + const storedTheme = getStoredTheme() + if (storedTheme !== 'light' && storedTheme !== 'dark') { + setTheme(getPreferredTheme()) + } + }) + + window.addEventListener('DOMContentLoaded', () => { + showActiveTheme(getPreferredTheme()) + + document.querySelectorAll('[data-bs-theme-value]') + .forEach(toggle => { + toggle.addEventListener('click', () => { + const theme = toggle.getAttribute('data-bs-theme-value') + setStoredTheme(theme) + setTheme(theme) + showActiveTheme(theme, true) + }) + }) + }) +})() \ No newline at end of file diff --git a/src/main/resources/static/javascript/panel-script.js b/src/main/resources/static/javascript/panel-script.js new file mode 100644 index 0000000..6d13ef6 --- /dev/null +++ b/src/main/resources/static/javascript/panel-script.js @@ -0,0 +1,256 @@ +function str_toHex(s) { + // utf8 to latin1 + var s = unescape(encodeURIComponent(s)); + var h = ''; + for (var i = 0; i < s.length; i++) { + h += s.charCodeAt(i).toString(16); + } + return h; +} + +function grab_form() { + let arr = []; + $("form#entryForm :input").each(function() { + var input = $(this); + let query = ""; + if(input.attr("type") == "checkbox") { + query = input.attr('id') + "=" + input.is(':checked'); + } else if(input.attr("type") == "text") { + var vv = str_toHex(input.val()); + query = input.attr('id') + "=" + vv; + } else { + query = input.attr('id') + "=" + input.val(); + } + arr.push(query); + }); + arr.push("section=" + new URL(window.location.href).searchParams.get("section")); + return arr.join("&"); +} + +function add_entry_modal() { + $("#modal_submit_edit").css("display", "none"); + $("#modal_submit_add").css("display", ""); +} + +function form_agge(jobj) { + get_text_api(jobj.genderTextId, function(t) { + $("#gender_text").val(t); + }); + $("#ismale").prop('checked', jobj.isMale); + $("#isfemale").prop('checked', jobj.isFemale); + $("#childFree").prop('checked', jobj.isChildfree); + $("#canDie").prop('checked', jobj.canDie); +} + +function form_hobb(jobj) { + get_text_api(jobj.textDescId, function(t) { + $("#hobby_text").val(t); + }); + $("#violenceRange").val(jobj.violence); + $("#powerRange").val(jobj.power); + $("#healRange").val(jobj.heal); + $("#foodRange").val(jobj.food); +} + +function form_lugg(jobj) { + get_text_api(jobj.textNameId, function(t) { + $("#luggage_name_text").val(t); + }); + get_text_api(jobj.textDescId, function(t) { + $("#luggage_desc_text").val(t); + }); + $("#violenceRange").val(jobj.violence); + $("#powerRange").val(jobj.power); + $("#healRange").val(jobj.heal); + $("#foodRange").val(jobj.food); + $("#isgarbage").prop('checked', jobj.garbage); +} + +function form_prof(jobj) { + get_text_api(jobj.textNameId, function(t) { + $("#work_name_text").val(t); + }); + get_text_api(jobj.textDescId, function(t) { + $("#work_desc_text").val(t); + }); + $("#violenceRange").val(jobj.violence); + $("#powerRange").val(jobj.power); + $("#healRange").val(jobj.heal); + $("#foodRange").val(jobj.food); +} + +function form_heal(jobj) { + get_text_api(jobj.textNameId, function(t) { + $("#heal_name_text").val(t); + }); + get_text_api(jobj.textDescId, function(t) { + $("#heal_desc_text").val(t); + }); + $("#health_index").val(jobj.health_index); +} + +function form_disaster(jobj) { + get_text_api(jobj.nameTextId, function(t) { + $("#diss_name_text").val(t); + }); + get_text_api(jobj.descTextId, function(t) { + $("#diss_desc_text").val(t); + }); +} + +function show_modal_edit(jobj, oid) { + var section = new URL(window.location.href).searchParams.get("section"); + + switch(section) { + case "agge": + form_agge(jobj); + break; + case "hobb": + form_hobb(jobj); + break; + case "lugg": + form_lugg(jobj); + break; + case "heal": + form_heal(jobj); + break; + case "prof": + form_prof(jobj); + break; + case "diss": + form_disaster(jobj); + break; + default: + form_disaster(jobj); + break; + } + + $("#modal_submit_edit").css("display", ""); + $("#modal_submit_add").css("display", "none"); + $("#modal_submit_edit").attr("data-entry-id", oid); +} + +function edit_submit_entry(obj) { + $.post("/api/remove_entry", "section="+new URL(window.location.href).searchParams.get("section")+"&entry_id="+($(obj).attr("data-entry-id")), function(data, status) { + $.post("/api/add_entry", grab_form(), function(data, status) { + window.location.reload(); + }); + }); +} + +function edit_entry(obj) { + $.post("/api/edit_entry", "section="+new URL(window.location.href).searchParams.get("section")+"&entry_id="+($(obj).attr("data-id")), function(data, status) { + var jobj = JSON.parse(data); + show_modal_edit(jobj, $(obj).attr("data-id")); + }); +} + +function get_text_api(tid, cb) { + $.post("/api/getTextById", "entry_id="+tid, function(data, status) { + cb(data); + }); +} + +function remove_entry(obj) { + $.post("/api/remove_entry", "section="+new URL(window.location.href).searchParams.get("section")+"&entry_id="+($(obj).attr("data-id")), function(data, status) { + window.location.reload(); + }); +} + +function add_entry() { + $.post("/api/add_entry", grab_form(), function(data, status) { + window.location.reload(); + }); +} + +function add_synergy(obj) { + let firstEntityId = $(obj).attr("data-id"); + let firstEntityType = 0; + let secondEntityId = $("#second_select_vals").val(); + let secondEntityType = $("#second_select_types").val(); + let probabilityValue = $("#synergy_prob_input").val(); + + let section = new URL(window.location.href).searchParams.get("section"); + + switch(section) { + case "agge": + firstEntityType = 0; + break; + case "hobb": + firstEntityType = 2; + break; + case "lugg": + firstEntityType = 3; + break; + case "heal": + firstEntityType = 1; + break; + case "prof": + firstEntityType = 4; + break; + } + let _set = 0; + switch(secondEntityType) { + case "agge": + _set = 0; + break; + case "hobb": + _set = 2; + break; + case "lugg": + _set = 3; + break; + case "heal": + _set = 1; + break; + case "prof": + _set = 4; + break; + } + secondEntityType = _set; + $.post("/api/add_synergy", "first_entity_id="+firstEntityId+"&first_entity_type="+firstEntityType+"&second_entity_id="+secondEntityId+"&second_entity_type="+secondEntityType+"&probability="+probabilityValue, function(data, status) { + window.location.reload(); + }); +} + +function show_synergies_modal(obj) { + $("#add_synergy_button").attr("data-id", $(obj).attr("data-id")); + $(".table_row_generated").remove(); + $.post("/api/get_synergies", "entity_id="+$(obj).attr("data-id")+"&entity_type="+new URL(window.location.href).searchParams.get("section"), function(data, status) { + data = JSON.parse(data); + for( let i = 0; i < data.length; i++ ) { + $("#table_body_modal").append(""+data[i].firstEntityText+""+data[i].firstType+""+data[i].secondEntityText+""+data[i].secondType+""+data[i].probabilityValue+""); + } + }); +} + +function secondTypeChange(obj) { + $.post("/api/get_entries", "section="+($(obj).val()), function(data, status) { + $("#second_select_vals").html(""); + let jobj = JSON.parse(data); + for( let i = 0; i < jobj.length; i++ ) { + let ind = jobj[i]; + let ss = 0; + if( ind.genderTextId != undefined ) { + ss = ind.genderTextId; + } else if( ind.textNameId != undefined ) { + ss = ind.textNameId; + } else if( ind.textDescId != undefined ) { + ss = ind.textDescId; + } + + get_text_api(ss, function(rte) { + $("#second_select_vals").append($('