resultMap = new LinkedHashMap<>();
+ resultMap.put("userId", userId);
+ resultMap.put("userGameOption", userGameOption.get());
+ String json = mapper.write(resultMap);
+ logger.info("Response: " + json);
+ return json;
+ }
+
+ return null;
+ }
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserPreviewHandler.java b/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserPreviewHandler.java
new file mode 100644
index 0000000..cb159d3
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserPreviewHandler.java
@@ -0,0 +1,90 @@
+package icu.samnyan.aqua.sega.chunithm.handler.impl;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import icu.samnyan.aqua.sega.chunithm.handler.BaseHandler;
+import icu.samnyan.aqua.sega.chunithm.model.response.GetUserPreviewResp;
+import icu.samnyan.aqua.sega.chunithm.model.userdata.UserCharacter;
+import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
+import icu.samnyan.aqua.sega.chunithm.model.userdata.UserGameOption;
+import icu.samnyan.aqua.sega.chunithm.service.UserCharacterService;
+import icu.samnyan.aqua.sega.chunithm.service.UserDataService;
+import icu.samnyan.aqua.sega.chunithm.service.UserGameOptionService;
+import icu.samnyan.aqua.sega.util.jackson.StringMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * The handler for loading basic profile information.
+ *
+ * return null if no profile exist
+ *
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Component
+public class GetUserPreviewHandler implements BaseHandler {
+
+ private static final Logger logger = LoggerFactory.getLogger(GetUserPreviewHandler.class);
+
+ private final StringMapper mapper;
+
+ private final UserDataService userDataService;
+ private final UserCharacterService userCharacterService;
+ private final UserGameOptionService userGameOptionService;
+
+ @Autowired
+ public GetUserPreviewHandler(StringMapper mapper, UserDataService userDataService, UserCharacterService userCharacterService, UserGameOptionService userGameOptionService) {
+ this.mapper = mapper;
+ this.userDataService = userDataService;
+ this.userCharacterService = userCharacterService;
+ this.userGameOptionService = userGameOptionService;
+ }
+
+ @Override
+ public String handle(Map request) throws JsonProcessingException {
+ String userId = (String) request.get("userId");
+
+ Optional userData = userDataService.getUserByExtId(userId);
+
+ if (userData.isEmpty()) {
+ return null;
+ }
+
+
+ UserData user = userData.get();
+
+ GetUserPreviewResp resp = new GetUserPreviewResp();
+ resp.setUserId(userId);
+ resp.setLogin(false);
+ resp.setLastLoginDate(user.getLastLoginDate());
+ resp.setUserName(user.getUserName());
+ resp.setReincarnationNum(user.getReincarnationNum());
+ resp.setLevel(user.getLevel());
+ resp.setExp(user.getExp());
+ resp.setPlayerRating(user.getPlayerRating());
+ resp.setLastGameId(user.getLastGameId());
+ resp.setLastRomVersion(user.getLastRomVersion());
+ resp.setLastDataVersion(user.getLastDataVersion());
+ resp.setLastPlayDate(user.getLastPlayDate());
+ resp.setTrophyId(user.getTrophyId());
+
+ Optional userCharacterOptional = userCharacterService.getByUserAndCharacterId(user, user.getCharacterId());
+ userCharacterOptional.ifPresent(resp::setUserCharacter);
+
+ Optional userGameOptionOptional = userGameOptionService.getByUser(user);
+ userGameOptionOptional.ifPresent(userGameOption -> {
+ resp.setPlayerLevel(userGameOption.getPlayerLevel());
+ resp.setRating(userGameOption.getRating());
+ resp.setHeadphone(userGameOption.getHeadphone());
+ });
+
+ String json = mapper.write(resp);
+ logger.info("Response: " + json);
+ return json;
+
+ }
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserRecentRatingHandler.java b/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserRecentRatingHandler.java
new file mode 100644
index 0000000..ccbcc8c
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserRecentRatingHandler.java
@@ -0,0 +1,56 @@
+package icu.samnyan.aqua.sega.chunithm.handler.impl;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import icu.samnyan.aqua.sega.chunithm.handler.BaseHandler;
+import icu.samnyan.aqua.sega.chunithm.model.response.data.UserRecentRating;
+import icu.samnyan.aqua.sega.chunithm.model.userdata.UserPlaylog;
+import icu.samnyan.aqua.sega.chunithm.service.UserPlaylogService;
+import icu.samnyan.aqua.sega.util.jackson.StringMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Return the recent play to calculate rating. Rating base on top 30 songs plus top 10 in recent 30 plays.
+ *
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Component
+public class GetUserRecentRatingHandler implements BaseHandler {
+
+ private static final Logger logger = LoggerFactory.getLogger(GetUserRecentRatingHandler.class);
+
+ private final StringMapper mapper;
+
+ private final UserPlaylogService userPlaylogService;
+
+ @Autowired
+ public GetUserRecentRatingHandler(StringMapper mapper, UserPlaylogService userPlaylogService) {
+ this.mapper = mapper;
+ this.userPlaylogService = userPlaylogService;
+ }
+
+ @Override
+ public String handle(Map request) throws JsonProcessingException {
+ String userId = (String) request.get("userId");
+
+ List top = userPlaylogService.getRecent30Plays(userId);
+ List rating = top.stream().map(log -> new UserRecentRating(log.getMusicId(), log.getLevel(), "1030000", log.getScore()))
+ .collect(Collectors.toList());
+
+ Map resultMap = new LinkedHashMap<>();
+ resultMap.put("userId", userId);
+ resultMap.put("length", rating.size());
+ resultMap.put("userRecentRatingList", rating);
+
+ String json = mapper.write(resultMap);
+ logger.info("Response: " + json);
+ return json;
+ }
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserRegionHandler.java b/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserRegionHandler.java
new file mode 100644
index 0000000..56b4fe4
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserRegionHandler.java
@@ -0,0 +1,46 @@
+package icu.samnyan.aqua.sega.chunithm.handler.impl;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import icu.samnyan.aqua.sega.chunithm.handler.BaseHandler;
+import icu.samnyan.aqua.sega.util.jackson.StringMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Component
+public class GetUserRegionHandler implements BaseHandler {
+
+ private static final Logger logger = LoggerFactory.getLogger(GetUserRegionHandler.class);
+
+ private final StringMapper mapper;
+
+ @Autowired
+ public GetUserRegionHandler(StringMapper mapper) {
+ this.mapper = mapper;
+ }
+
+ @Override
+ public String handle(Map request) throws JsonProcessingException {
+ String userId = (String) request.get("userId");
+
+ List