인스턴스 메타데이터 조회

This commit is contained in:
2025-11-24 16:32:37 +09:00
parent 2dd935d80e
commit 715bfc490d
11 changed files with 646 additions and 145 deletions

View File

@@ -70,4 +70,16 @@ public class DictionaryController {
@RequestParam Map<String, String> requestParams){
metaDataService.craftExcelExport(response, requestParams);
}
@GetMapping("/instance/list")
public ResponseEntity<DictionaryResponse> instanceList(
@RequestParam Map<String, String> requestParams){
return ResponseEntity.ok().body( metaDataService.getInstanceDictList(requestParams));
}
@GetMapping("/instance/excel-export")
public void instanceExcelExport(HttpServletResponse response,
@RequestParam Map<String, String> requestParams){
metaDataService.instanceExcelExport(response, requestParams);
}
}

View File

@@ -1,6 +1,5 @@
package com.caliverse.admin.domain.cache;
import com.caliverse.admin.domain.datacomponent.MetaDataFileLoader;
import com.caliverse.admin.domain.request.LogGenericRequest;
import com.caliverse.admin.logs.logservice.businesslogservice.BusinessLogGenericService;
import lombok.extern.slf4j.Slf4j;

View File

@@ -30,6 +30,109 @@ public class JsonFileReader {
this.objectMapper = new ObjectMapper();
}
@SuppressWarnings("unchecked")
public <T> List<T> readJsonArray(String metaName, Class<T> targetClass) {
try {
File metaFile = new File(metaDataPath, metaName);
log.info("Trying to load data from: {}", metaFile.getPath());
List<T> resultList = new ArrayList<>();
if (metaFile.isDirectory()) {
// 디렉토리인 경우 모든 JSON 파일을 읽어서 결과를 합침
log.info("Found directory: {}, reading all JSON files", metaFile.getPath());
try (Stream<Path> paths = Files.walk(metaFile.toPath())) {
List<File> jsonFiles = paths
.filter(Files::isRegularFile)
.filter(p -> p.toString().toLowerCase().endsWith(".json"))
.map(Path::toFile)
.toList();
if (jsonFiles.isEmpty()) {
log.warn("No JSON files found in directory: {}", metaFile.getPath());
return new ArrayList<>();
}
for (File jsonFile : jsonFiles) {
log.info("Processing JSON file: {}", jsonFile.getPath());
List<T> fileResult = parseJsonFileToClass(jsonFile, targetClass);
if (fileResult != null) {
resultList.addAll(fileResult);
}
}
}
} else {
// 일반 파일인 경우
String jsonFileName = metaName + "Data.json";
metaFile = new File(metaDataPath, jsonFileName);
log.info("Original path not found, trying: {}", metaFile.getPath());
if (!metaFile.exists()) {
log.error("Neither directory nor file found: {} or {}", metaName, jsonFileName);
return new ArrayList<>();
}
resultList = parseJsonFileToClass(metaFile, targetClass);
}
log.info("Successfully loaded {} items of type {} from {}",
resultList.size(), targetClass.getSimpleName(), metaName);
return resultList;
} catch (IOException e) {
log.error("Failed to read from path: {}", metaName, e);
throw new MetaDataException("Failed to read from path: " + metaName, e);
}
}
@SuppressWarnings("unchecked")
private <T> List<T> parseJsonFileToClass(File file, Class<T> targetClass) {
try {
log.debug("Parsing JSON file: {} to class: {}", file.getPath(), targetClass.getSimpleName());
String fileContent = readFileAsString(file);
JsonNode rootNode = objectMapper.readTree(fileContent);
if (!rootNode.isEmpty()) {
String firstFieldName = rootNode.fieldNames().next();
JsonNode firstNode = rootNode.get(firstFieldName);
// Special handling for String class (like BanWord)
if (targetClass == String.class) {
if (firstNode.isArray()) {
List<T> resultList = new ArrayList<>();
for (JsonNode node : firstNode) {
resultList.add((T) node.asText());
}
return resultList;
} else {
return List.of((T) firstNode.asText());
}
}
// For other classes, use Jackson's type conversion
List<T> resultList = objectMapper.readValue(
firstNode.toString(),
objectMapper.getTypeFactory().constructCollectionType(List.class, targetClass)
);
log.debug("Successfully parsed JSON file: {}, first field: {}, items count: {}",
file.getName(), firstFieldName, resultList.size());
return resultList;
} else {
log.warn("No fields found in JSON file: {}", file.getPath());
return new ArrayList<>();
}
} catch (JsonProcessingException e) {
log.error("Failed to parse JSON from file: {} to class: {}", file.getName(), targetClass.getSimpleName(), e);
throw new MetaDataException("Failed to parse JSON from file: " + file.getName() + " to class: " + targetClass.getSimpleName(), e);
} catch (IOException e) {
log.error("Failed to read file: {}", file.getName(), e);
throw new MetaDataException("Failed to read file: " + file.getName(), e);
}
}
public List<Map<String, Object>> readJsonFile(String metaName) {
List<Map<String, Object>> resultMap = new ArrayList<>();

View File

@@ -1,8 +1,7 @@
package com.caliverse.admin.domain.datacomponent;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import com.caliverse.admin.domain.entity.metaEnum.EJoinInProgressType;
@@ -11,7 +10,6 @@ import com.caliverse.admin.domain.entity.metadata.*;
import com.caliverse.admin.global.common.exception.MetaDataException;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.caliverse.admin.domain.entity.EMetaData;
@@ -23,20 +21,36 @@ import static com.caliverse.admin.global.common.utils.DataHelper.parseFloat;
@Slf4j
public class MetaDataFileLoader {
private final JsonFileReader jsonFileReader;
private final Map<Integer, MetaItemData> items;
private final Map<String, MetaTextStringData> textStrings;
private final Map<Integer, MetaClothTypeData> clothTypes;
private final Map<Integer, MetaToolData> toolItems;
private final Map<Integer, String> banWords;
private final Map<MetaQuestKey, MetaQuestData> quests;
private final Map<Integer, MetaBuildingData> buildings;
private final Map<Integer, MetaLandData> lands;
private final Map<Integer, MetaGameModeData> gameModes;
private final Map<Integer, MetaGameFFAConfigData> gameFFAConfigs;
private final Map<Integer, MetaBattleConfigData> battleConfigs;
private final Map<Integer, MetaBattleRewardData> battleRewards;
private final Map<String, MetaSystemMailData> systemMails;
private final Map<Integer, MetaGameModeMatchData> gameModeMatches;
// private final Map<Integer, MetaItemData> items;
// private final Map<String, MetaTextStringData> textStrings;
// private final Map<Integer, MetaClothTypeData> clothTypes;
// private final Map<Integer, MetaToolData> toolItems;
// private final Map<Integer, String> banWords;
// private final Map<MetaQuestKey, MetaQuestData> quests;
// private final Map<Integer, MetaBuildingData> buildings;
// private final Map<Integer, MetaLandData> lands;
// private final Map<Integer, MetaGameModeData> gameModes;
// private final Map<Integer, MetaGameFFAConfigData> gameFFAConfigs;
// private final Map<Integer, MetaBattleConfigData> battleConfigs;
// private final Map<Integer, MetaBattleRewardData> battleRewards;
// private final Map<String, MetaSystemMailData> systemMails;
// private final Map<Integer, MetaGameModeMatchData> gameModeMatches;
private final List<MetaItemData> items;
private final List<MetaTextStringData> textStrings;
private final List<MetaClothTypeData> clothTypes;
private final List<MetaToolData> toolItems;
private final List<String> banWords;
private final List<MetaQuestData> quests;
private final List<MetaBuildingData> buildings;
private final List<MetaLandData> lands;
private final List<MetaGameModeData> gameModes;
private final List<MetaGameFFAConfigData> gameFFAConfigs;
private final List<MetaBattleConfigData> battleConfigs;
private final List<MetaBattleRewardData> battleRewards;
private final List<MetaSystemMailData> systemMails;
private final List<MetaGameModeMatchData> gameModeMatches;
private final List<MetaBuffData> buffs;
private final List<MetaGachaData> gachas;
private final List<MetaItemSetData> itemSets;
@@ -47,23 +61,26 @@ public class MetaDataFileLoader {
private final List<MetaCurrencyData> currencies;
private final List<MetaRankingData> rankings;
private final List<MetaEventActionScoreData> eventActionScoreDatas;
private final List<MetaInstanceData> instances;
public MetaDataFileLoader(JsonFileReader jsonFileReader) {
public MetaDataFileLoader(JsonFileReader jsonFileReader, List<MetaInstanceData> instances) {
this.jsonFileReader = jsonFileReader;
this.gameModes = new ConcurrentHashMap<>();
this.items = new ConcurrentHashMap<>();
this.textStrings = new ConcurrentHashMap<>();
this.clothTypes = new ConcurrentHashMap<>();
this.toolItems = new ConcurrentHashMap<>();
this.banWords = new ConcurrentHashMap<>();
this.quests = new ConcurrentHashMap<>();
this.buildings = new ConcurrentHashMap<>();
this.lands = new ConcurrentHashMap<>();
this.battleConfigs = new ConcurrentHashMap<>();
this.battleRewards = new ConcurrentHashMap<>();
this.systemMails = new ConcurrentHashMap<>();
this.gameFFAConfigs = new ConcurrentHashMap<>();
this.gameModeMatches = new ConcurrentHashMap<>();
this.instances = instances;
this.gameModes = new ArrayList<>();
this.items = new ArrayList<>();
this.textStrings = new ArrayList<>();
this.clothTypes = new ArrayList<>();
this.toolItems = new ArrayList<>();
this.banWords = new ArrayList<>();
this.quests = new ArrayList<>();
this.buildings = new ArrayList<>();
this.lands = new ArrayList<>();
this.battleConfigs = new ArrayList<>();
this.battleRewards = new ArrayList<>();
this.systemMails = new ArrayList<>();
this.gameFFAConfigs = new ArrayList<>();
this.gameModeMatches = new ArrayList<>();
this.buffs = new ArrayList<>();
this.gachas = new ArrayList<>();
this.itemSets = new ArrayList<>();
@@ -76,23 +93,70 @@ public class MetaDataFileLoader {
this.eventActionScoreDatas = new ArrayList<>();
}
@PostConstruct
public void initialize(){
loadMetaData();
}
@Scheduled(fixedDelayString = "${caliverse.metadata.reload.interval}")
public void reloadMetaData() {
private void loadMetaData() {
try {
log.info("Starting metadata reload");
loadMetaData();
log.info("Metadata reload completed");
} catch (Exception e) {
log.error("Failed to reload metadata", e);
for (EMetaData metaData : EMetaData.values()) {
//임시
if(!metaData.equals(EMetaData.INSTANCE_DATA)) continue;
if (metaData != EMetaData.NONE && metaData.getDataClass() != null) {
try {
log.debug("Loading metadata: {}", metaData.getFileName());
loadGenericMetaData(metaData);
log.debug("Successfully loaded metadata: {}", metaData.getFileName());
} catch (Exception e) {
if (metaData.getIsRequired()) {
log.error("Failed to load required metadata: {}", metaData.getFileName(), e);
throw new MetaDataException("필수 메타데이터 로드 실패: " + metaData.getFileName(), e);
} else {
log.warn("Failed to load optional metadata: {}, continuing...", metaData.getFileName(), e);
}
}
}
}
} catch (MetaDataException e) {
log.error("Failed to initialize metadata", e);
throw e;
}
}
private void loadMetaData(){
@SuppressWarnings("unchecked")
private void loadGenericMetaData(EMetaData metaData) {
try {
// JSON 파일 읽기
List<?> dataList = jsonFileReader.readJsonArray(metaData.getFileName(), metaData.getDataClass());
// 리플렉션을 통해 필드에 데이터 설정
Field field = this.getClass().getDeclaredField(metaData.getFieldName());
field.setAccessible(true);
List<Object> targetList = (List<Object>) field.get(this);
targetList.clear();
targetList.addAll(dataList);
} catch (Exception e) {
throw new MetaDataException("메타데이터 로드 실패: " + metaData.getFileName(), e);
}
}
// @Scheduled(fixedDelayString = "${caliverse.metadata.reload.interval}")
// public void reloadMetaData() {
// try {
// log.info("Starting metadata reload");
// loadMetaData();
// log.info("Metadata reload completed");
// } catch (Exception e) {
// log.error("Failed to reload metadata", e);
// }
// }
@PostConstruct
public void initialize(){
loadMetaData();
loadMetaDataSingle();
}
private void loadMetaDataSingle(){
try{
loadTextStrings();
loadQuests();
@@ -127,18 +191,14 @@ public class MetaDataFileLoader {
public Optional<MetaTextStringData> getName(String text){
if(text == null) return Optional.empty();
return Optional.ofNullable(textStrings.get(text));
return textStrings.stream().filter(data -> data.getKey().equals(text)).findFirst();
}
//아이템 가져오기
public Optional<MetaItemData> getMetaItem(int itemId) {
if(itemId == 0) return Optional.empty();
return Optional.ofNullable(items.get(itemId));
}
public List<MetaItemData> getMetaItems() {
return new ArrayList<>(items.values());
return items.stream().filter(data -> data.getItemId() == itemId).findFirst();
}
//의상 타입 가져오기
@@ -159,9 +219,8 @@ public class MetaDataFileLoader {
public List<MetaQuestData> getMetaQuests(int id) {
if(id == 0) return Collections.emptyList();
return quests.entrySet().stream()
.filter(entry -> entry.getKey().getQeustId().equals(id))
.map(Map.Entry::getValue)
return quests.stream()
.filter(quest -> quest.getQuestId().equals(id))
.collect(Collectors.toList());
}
@@ -175,7 +234,7 @@ public class MetaDataFileLoader {
}
public List<MetaBuildingData> getMetaBuildings() {
return new ArrayList<>(buildings.values());
return new ArrayList<>(buildings);
}
//랜드 정보 가져오기
@@ -268,29 +327,34 @@ public class MetaDataFileLoader {
}
//////////////// 리스트 조회
public List<MetaItemData> getMetaItems() {
return new ArrayList<>(items);
}
public List<MetaLandData> getMetaLands() {
return new ArrayList<>(lands.values());
return new ArrayList<>(lands);
}
public List<MetaGameModeData> getMetaGameModes() {
return new ArrayList<>(gameModes.values());
return new ArrayList<>(gameModes);
}
public List<MetaGameFFAConfigData> getMetaGameFFAConfigs() {
return new ArrayList<>(gameFFAConfigs.values());
return new ArrayList<>(gameFFAConfigs);
}
public List<MetaGameModeMatchData> getMetaGameModeMatchs() {
return new ArrayList<>(gameModeMatches.values());
return new ArrayList<>(gameModeMatches);
}
// 추후 없어질것
public List<MetaBattleConfigData> getMetaBattleConfigs() {
return new ArrayList<>(battleConfigs.values());
return new ArrayList<>(battleConfigs);
}
// 추후 없어질것
public List<MetaBattleRewardData> getMetaBattleRewards() {
return battleRewards.values().stream()
return battleRewards.stream()
.collect(Collectors.groupingBy(MetaBattleRewardData::getGroupID)) // groupId로 그룹화
.values().stream() // 그룹화된 리스트들의 스트림
.map(group -> group.get(0)) // 각 그룹의 첫 번째 항목만 선택
@@ -299,15 +363,15 @@ public class MetaDataFileLoader {
}
public List<MetaSystemMailData> getMetaSystemMail() {
return new ArrayList<>(systemMails.values());
return new ArrayList<>(systemMails);
}
public List<MetaBrandData> getMetaBrand() {
return brands;
return new ArrayList<>(brands);
}
public List<MetaRankingData> getMetaRanking() {
return rankings;
return new ArrayList<>(rankings);
}
public List<MetaEventActionScoreData> getMetaEventActionScore() {
@@ -320,7 +384,11 @@ public class MetaDataFileLoader {
}
public List<MetaCraftingData> getMetaCrafting() {
return craftings;
return new ArrayList<>(craftings);
}
public List<MetaInstanceData> getMetaInstance() {
return new ArrayList<>(instances);
}
@@ -337,12 +405,12 @@ public class MetaDataFileLoader {
}
metaList.forEach(meta -> {
MetaTextStringData textString = new MetaTextStringData();
textString.setKey((String) meta.get("Key"));
textString.setKor((String) meta.get("SourceString"));
textString.setEn((String) meta.get("en"));
textString.setJa((String) meta.get("ja"));
textStrings.put(textString.getKey(), textString);
MetaTextStringData item = new MetaTextStringData();
item.setKey((String) meta.get("Key"));
item.setKor((String) meta.get("SourceString"));
item.setEn((String) meta.get("en"));
item.setJa((String) meta.get("ja"));
textStrings.add(item);
});
log.info("loadTextStrings {} Load Complete",EMetaData.TEXT_STRING_DATA.getFileName());
@@ -441,7 +509,7 @@ public class MetaDataFileLoader {
item.setBeaconShopGoldFee((Integer) meta.get("BeaconShopGoldFee"));
item.setIsBeaconShop((Boolean) meta.get("is_BeaconShop"));
items.put(item.getItemId(), item);
items.add(item);
});
log.info("loadItems {} Load Complete", EMetaData.ITEM_DATA.getFileName());
@@ -461,7 +529,7 @@ public class MetaDataFileLoader {
item.setMetaId((Integer)meta.get("Meta_id"));
item.setSmallType((String)meta.get("SmallType"));
item.setEquipSlotType((String)meta.get("EquipSlotType"));
clothTypes.put(item.getMetaId(), item);
clothTypes.add(item);
});
log.info("loadClothType {} Load Complete", EMetaData.CLOTH_TYPE_DATA.getFileName());
@@ -479,7 +547,7 @@ public class MetaDataFileLoader {
MetaToolData item = new MetaToolData();
item.setToolId((Integer)meta.get("tool_id"));
item.setToolName((String)meta.get("tool_name"));
toolItems.put(item.getToolId(), item);
toolItems.add(item);
});
log.info("loadToolItems {} Load Complete", EMetaData.TOOL_DATA.getFileName());
@@ -494,7 +562,7 @@ public class MetaDataFileLoader {
}
metaList.forEach(meta -> {
banWords.put((Integer)meta.get("Id"), (String)meta.get("Ban_Word"));
banWords.add((String)meta.get("Ban_Word"));
});
log.info("loadBanWord {} Load Complete", EMetaData.BAN_WORD_DATA.getFileName());
@@ -516,7 +584,7 @@ public class MetaDataFileLoader {
item.setTaskNum(taskNum);
item.setTaskName((String)meta.get("TaskName"));
item.setCounter((Integer) meta.get("SetCounter"));
quests.put(new MetaQuestKey(questId, taskNum), item);
quests.add(item);
});
log.info("loadQuests {} Load Complete", EMetaData.QUEST_DATA.getFileName());
@@ -542,7 +610,7 @@ public class MetaDataFileLoader {
item.setBuildingDesc((String)meta.get("BuildingDesc"));
item.setBuildingSize((String)meta.get("BuildingSize"));
item.setInstanceSocket((Integer)meta.get("InstanceSocket"));
buildings.put((Integer)meta.get("BuildingId"), item);
buildings.add(item);
});
log.info("loadBuilding {} Load Complete", EMetaData.BUILDING_DATA.getFileName());
@@ -577,7 +645,7 @@ public class MetaDataFileLoader {
item.setBuildingArea((String)meta.get("BuildingArea"));
item.setBuildingId((Integer)meta.get("BuildingId"));
item.setBuildingSocket((Integer)meta.get("BuildingSocket"));
lands.put((Integer)meta.get("LandId"), item);
lands.add(item);
});
log.info("loadLand {} Load Complete", EMetaData.LAND_DATA.getFileName());
@@ -605,7 +673,7 @@ public class MetaDataFileLoader {
item.setModeOptionId((Integer)meta.get("GameModeOptionID"));
item.setModeStartId((Integer)meta.get("GameModeStartID"));
item.setModeTeamId((Integer)meta.get("GameModeTeamID"));
gameModes.put((Integer)meta.get("GameModeID"), item);
gameModes.add(item);
});
log.info("loadGameMode {} Load Complete", EMetaData.GAME_MODE_DATA.getFileName());
@@ -633,7 +701,7 @@ public class MetaDataFileLoader {
item.setJoinInProgress(EJoinInProgressType.valueOf((String)meta.get("JoinInProgress")));
item.setJoinInMaxTimeSec((Integer)meta.get("JoinInMaxTimeSec"));
item.setEntranceClosingTime((Integer)meta.get("EntranceClosingTime"));
gameModeMatches.put((Integer)meta.get("GameModeMatchID"), item);
gameModeMatches.add(item);
});
log.info("loadGameModeMatch {} Load Complete", EMetaData.GAME_MODE_DATA.getFileName());
@@ -657,36 +725,12 @@ public class MetaDataFileLoader {
item.setNextRoundWaitTime((Integer)meta.get("NextRoundWaitTime"));
item.setResultUIWaitTime((Integer)meta.get("ResultUIWaitTime"));
item.setGetRewardTime((Integer)meta.get("GetRewardTime"));
gameFFAConfigs.put((Integer)meta.get("GameModeTpsFfaID"), item);
gameFFAConfigs.add(item);
});
log.info("loadGameModeFFAConfig {} Load Complete", EMetaData.GAME_MODE_FFA_DATA.getFileName());
}
// 게임 TPS_TDM 설정 데이터 로드
public void loadGameModeTDMConfig(){
List<Map<String, Object>> metaList = jsonFileReader.readJsonFile(EMetaData.GAME_MODE_TDM_DATA.getFileName());
if(metaList == null || metaList.isEmpty()) {
log.warn("Battle config data is empty or file not found: {}", EMetaData.GAME_MODE_TDM_DATA.getFileName());
return;
}
metaList.forEach(meta -> {
MetaBattleConfigData item = new MetaBattleConfigData();
item.setId((Integer)meta.get("Id"));
item.setDesc((String)meta.get("Description"));
item.setPlayerRespawnTime((Integer)meta.get("PlayerRespawnTime"));
item.setDefaultRoundCount((Integer)meta.get("DefaultRoundCount"));
item.setRoundTime((Integer)meta.get("RoundTime"));
item.setNextRoundWaitTime((Integer)meta.get("NextRoundWaitTime"));
item.setResultUIWaitTime((Integer)meta.get("ResultUIWaitTime"));
item.setGetRewardTime((Integer)meta.get("GetRewardTime"));
battleConfigs.put((Integer)meta.get("Id"), item);
});
log.info("loadBattleConfig {} Load Complete", EMetaData.GAME_MODE_TDM_DATA.getFileName());
}
// 전투 설정 데이터 로드
public void loadBattleConfig(){
List<Map<String, Object>> metaList = jsonFileReader.readJsonFile(EMetaData.BATTLE_CONFIG_DATA.getFileName());
@@ -705,7 +749,7 @@ public class MetaDataFileLoader {
item.setNextRoundWaitTime((Integer)meta.get("NextRoundWaitTime"));
item.setResultUIWaitTime((Integer)meta.get("ResultUIWaitTime"));
item.setGetRewardTime((Integer)meta.get("GetRewardTime"));
battleConfigs.put((Integer)meta.get("Id"), item);
battleConfigs.add(item);
});
log.info("loadBattleConfig {} Load Complete", EMetaData.BATTLE_CONFIG_DATA.getFileName());
@@ -728,7 +772,7 @@ public class MetaDataFileLoader {
item.setChargeTime((Integer)meta.get("ChargeTime"));
item.setRewardItemID((Integer)meta.get("RewardItemID"));
item.setRewardCount((Integer)meta.get("RewardCount"));
battleRewards.put((Integer)meta.get("Id"), item);
battleRewards.add(item);
});
log.info("loadBattleReward {} Load Complete", EMetaData.BATTLE_REWARD_DATA.getFileName());
@@ -748,7 +792,7 @@ public class MetaDataFileLoader {
item.setMailTitle((String)meta.get("Mail_Title"));
item.setMailDesc((String)meta.get("Mail_Desc"));
item.setSender((String)meta.get("Sender"));
systemMails.put((String)meta.get("Key"), item);
systemMails.add(item);
});
log.info("loadSystemMail {} Load Complete", EMetaData.SYSTEM_MAIL_DATA.getFileName());

View File

@@ -158,6 +158,9 @@ public class MetaDataHandler {
public List<MetaCraftingData> getMetaCraftingListData() {
return metadataFileLoader.getMetaCrafting();
}
public List<MetaInstanceData> getMetaInstanceListData(){
return metadataFileLoader.getMetaInstance();
}
}

View File

@@ -1,42 +1,48 @@
package com.caliverse.admin.domain.entity;
import com.caliverse.admin.domain.entity.metadata.*;
public enum EMetaData {
NONE("", false),
ITEM_DATA("Item", true),
CLOTH_TYPE_DATA("ClothEquipType", true),
TOOL_DATA("Tool", true),
BAN_WORD_DATA("BanWord", true),
TEXT_STRING_DATA("TextString", true),
QUEST_DATA("Quest", true),
LAND_DATA("Land", true),
BUILDING_DATA("Building", true),
GAME_MODE_DATA("GameMode", true),
GAME_MODE_FFA_DATA("GameModeTpsFfa", true),
GAME_MODE_TDM_DATA("GameModeTpsTdm", true),
GAME_MODE_MATCH_DATA("GameModeMatch", true),
BATTLE_CONFIG_DATA("BattleFFAConfig", true),
BATTLE_REWARD_DATA("BattleFFAReward", true),
SYSTEM_MAIL_DATA("SystemMail", true),
BRAND_DATA("Brand", true),
BUFF_DATA("Buff", true),
ITEM_SET_DATA("ItemSet", true),
WEB_LINK_DATA("WeblinkLocalize", true),
ATTRIBUTE_RANDOM_GROUP_DATA("AttributeRandomGroup", true),
CRAFTING_DATA("Crafting", true),
CURRENCY_DATA("Currency", true),
GACHA_DATA("Gacha", true),
RANKING_DATA("Ranking", true),
EVENT_ACTION_SCORE_DATA("EventActionScore", true)
NONE("", false, null, null),
ITEM_DATA("Item", true, MetaItemData.class, "items"),
CLOTH_TYPE_DATA("ClothEquipType", true, MetaClothTypeData.class, "clothTypes"),
TOOL_DATA("Tool", true, MetaToolData.class, "toolItems"),
BAN_WORD_DATA("BanWord", true, String.class, "banWords"),
TEXT_STRING_DATA("TextString", true, MetaTextStringData.class, "textStrings"),
QUEST_DATA("Quest", true, MetaQuestData.class, "quests"),
LAND_DATA("Land", true, MetaLandData.class, "lands"),
BUILDING_DATA("Building", true, MetaBuildingData.class, "buildings"),
GAME_MODE_DATA("GameMode", true, MetaGameModeData.class, "gameModes"),
GAME_MODE_FFA_DATA("GameModeTpsFfa", true, MetaGameFFAConfigData.class, "gameFFAConfigs"),
GAME_MODE_MATCH_DATA("GameModeMatch", true, MetaGameModeMatchData.class, "gameModeMatches"),
BATTLE_CONFIG_DATA("BattleFFAConfig", true, MetaBattleConfigData.class, "battleConfigs"),
BATTLE_REWARD_DATA("BattleFFAReward", true, MetaBattleRewardData.class, "battleRewards"),
SYSTEM_MAIL_DATA("SystemMail", true, MetaSystemMailData.class, "systemMails"),
BRAND_DATA("Brand", true, MetaBrandData.class, "brands"),
BUFF_DATA("Buff", true, MetaBuffData.class, "buffs"),
ITEM_SET_DATA("ItemSet", true, MetaItemSetData.class, "itemSets"),
WEB_LINK_DATA("WeblinkLocalize", true, MetaWebLinkData.class, "webLinks"),
ATTRIBUTE_RANDOM_GROUP_DATA("AttributeRandomGroup", true, MetaAttributeRandomGroupData.class, "attributeRandomGroups"),
CRAFTING_DATA("Crafting", true, MetaCraftingData.class, "craftings"),
CURRENCY_DATA("Currency", true, MetaCurrencyData.class, "currencies"),
GACHA_DATA("Gacha", true, MetaGachaData.class, "gachas"),
RANKING_DATA("Ranking", true, MetaRankingData.class, "rankings"),
EVENT_ACTION_SCORE_DATA("EventActionScore", true, MetaEventActionScoreData.class, "eventActionScoreDatas"),
INSTANCE_DATA("Instance", true, MetaInstanceData.class, "instances")
;
private String fileName;
private boolean isRequired;
EMetaData(String fileName, boolean isRequired) {
private final String fileName;
private final boolean isRequired;
private final Class<?> dataClass;
private final String fieldName;
EMetaData(String fileName, boolean isRequired, Class<?> dataClass, String fieldName) {
this.fileName = fileName;
this.isRequired = isRequired;
this.dataClass = dataClass;
this.fieldName = fieldName;
}
public String getFileName(){
@@ -47,6 +53,14 @@ public enum EMetaData {
return isRequired;
}
public Class<?> getDataClass() {
return dataClass;
}
public String getFieldName() {
return fieldName;
}
public static boolean getIsRequired(String fileName) {
for (EMetaData metaData : EMetaData.values()) {
if (metaData.getFileName().equals(fileName)) {

View File

@@ -0,0 +1,49 @@
package com.caliverse.admin.domain.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class InstanceDict {
//인스턴스아이디
@JsonProperty("instance_id")
private Integer instanceId;
//인스턴스명
@JsonProperty("instance_name")
private String instanceName;
//소유권
@JsonProperty("owner")
private String owner;
//빌딩 ID
@JsonProperty("building_id")
private Integer buildingId;
//빌딩 소켓 넘버
@JsonProperty("building_socket")
private Integer buildingSocket;
//컨텐츠 타입
@JsonProperty("contents_type")
private String contentsType;
//맵 ID
@JsonProperty("map_id")
private Integer mapId;
//제한 인원 수
@JsonProperty("limit_count")
private Integer limitCount;
//정원 초과 시 추가 생성 여부
@JsonProperty("over_limit")
private Integer overLimit;
//입장방식
@JsonProperty("access_type")
private String accessType;
//입장시 필요 아이템
@JsonProperty("access_id")
private Integer accessId;
//음성채팅 옵션
@JsonProperty("voice_chat")
private String voiceChat;
//시야타입
@JsonProperty("view_type")
private String viewType;
}

View File

@@ -0,0 +1,61 @@
package com.caliverse.admin.domain.entity.metadata;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class MetaInstanceData {
@JsonProperty("Id")
private Integer id;
@JsonProperty("Owner")
private String owner;
@JsonProperty("Building_Id")
private Integer buildingId;
@JsonProperty("Building_Socket")
private Integer buildingSocket;
@JsonProperty("Name")
private String name;
@JsonProperty("Description")
private String description;
@JsonProperty("ListThumbnail")
private String listThumbnail;
@JsonProperty("DetailThumbnail")
private String detailThumbnail;
@JsonProperty("ContentsType")
private String contentsType;
@JsonProperty("Map_Id")
private Integer mapId;
@JsonProperty("LimitCount")
private Integer limitCount;
@JsonProperty("OverLimit")
private Integer overLimit;
@JsonProperty("AccessType")
private String accessType;
@JsonProperty("Access_Id")
private Integer accessId;
@JsonProperty("VoiceChat")
private String voiceChat;
@JsonProperty("ViewType")
private String viewType;
@JsonProperty("RoomFile")
private String roomFile;
}

View File

@@ -1,6 +1,7 @@
package com.caliverse.admin.domain.response;
import com.caliverse.admin.domain.entity.CraftingDict;
import com.caliverse.admin.domain.entity.InstanceDict;
import com.caliverse.admin.domain.entity.ItemDict;
import com.caliverse.admin.domain.entity.metadata.*;
import com.fasterxml.jackson.annotation.JsonInclude;
@@ -34,6 +35,9 @@ public class DictionaryResponse {
@JsonProperty("crafting_list")
private CraftingList craftingList;
@JsonProperty("instance_list")
private InstanceList instanceList;
@JsonProperty("brand_list")
private List<MetaBrandData> brandList;
@@ -52,6 +56,8 @@ public class DictionaryResponse {
@JsonProperty("event_action_list")
private List<MetaEventActionScoreData> eventActionList;
private List<?> dataList;
private String message;
private int total;
@@ -90,5 +96,19 @@ public class DictionaryResponse {
private List<CraftingDict> ja;
}
@Data
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class InstanceList {
@JsonProperty("ko")
private List<InstanceDict> ko;
@JsonProperty("en")
private List<InstanceDict> en;
@JsonProperty("ja")
private List<InstanceDict> ja;
}
}

View File

@@ -802,6 +802,19 @@ public class ExcelService {
translations.put("country", "Count");
translations.put("maxCount", "최대 보유 가능 수량");
translations.put("stackMaxCount", "최대 스택 가능 수량");
translations.put("instanceId", "인스턴스 ID");
translations.put("instanceName", "인스턴스명");
translations.put("owner", "소유권");
translations.put("buildingId", "빌딩 ID");
translations.put("buildingSocket", "빌딩 소켓 넘버");
translations.put("contentsType", "컨텐츠 타입");
translations.put("mapId", "맵 ID");
translations.put("limitCount", "제한 인원 수");
translations.put("overLimit", "정원 초과 시 추가 생성 여부");
translations.put("accessType", "입장 방식");
translations.put("accessId", "입장시 필요 아이템");
translations.put("voiceChat", "음성채팅 옵션");
translations.put("viewType", "시야 타입");
return translations;
}

View File

@@ -2,11 +2,7 @@ package com.caliverse.admin.domain.service;
import com.caliverse.admin.domain.datacomponent.MetaDataHandler;
import com.caliverse.admin.domain.entity.*;
import com.caliverse.admin.domain.entity.excel.ExcelBusinessLog;
import com.caliverse.admin.domain.entity.log.GenericLog;
import com.caliverse.admin.domain.entity.metadata.*;
import com.caliverse.admin.domain.request.LogGenericRequest;
import com.caliverse.admin.domain.response.BattleEventResponse;
import com.caliverse.admin.domain.response.DictionaryResponse;
import com.caliverse.admin.global.common.annotation.RequestLog;
import com.caliverse.admin.global.common.code.CommonCode;
@@ -17,11 +13,9 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.UncategorizedMongoDbException;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@@ -556,4 +550,193 @@ public class MetaDataService {
})
.collect(Collectors.toList());
}
//제작 백과사전
@RequestLog
public DictionaryResponse getInstanceDictList(@RequestParam Map<String, String> requestParam){
String searchType = requestParam.get("search_type");
String searchData = requestParam.get("search_data").trim();
String contentsType = requestParam.get("contents_type");
String accessType = requestParam.get("access_type");
String orderBy = requestParam.get("orderby");
String pageNo = requestParam.get("page_no");
String pageSize = requestParam.get("page_size");
List<MetaInstanceData> items = metaDataHandler.getMetaInstanceListData();
List<InstanceDict> instanceDictListKo = createInstanceDictList(items, LANGUAGETYPE.KO, searchType, searchData, contentsType, accessType);
List<InstanceDict> instanceDictListEn = createInstanceDictList(items, LANGUAGETYPE.EN, searchType, searchData, contentsType, accessType);
List<InstanceDict> instanceDictListJa = createInstanceDictList(items, LANGUAGETYPE.JA, searchType, searchData, contentsType, accessType);
int totalAll = instanceDictListKo.size();
if(orderBy != null && !orderBy.isEmpty()) {
Comparator<InstanceDict> comparator = null;
if(orderBy.equalsIgnoreCase("ASC")) {
comparator = Comparator.comparing(InstanceDict::getInstanceId);
} else if(orderBy.equalsIgnoreCase("DESC")) {
comparator = Comparator.comparing(InstanceDict::getInstanceId).reversed();
}
if(comparator != null) {
instanceDictListKo = instanceDictListKo.stream().sorted(comparator).toList();
instanceDictListEn = instanceDictListEn.stream().sorted(comparator).toList();
instanceDictListJa = instanceDictListJa.stream().sorted(comparator).toList();
}
}
// 페이징 처리
int currentPageNo = 1;
int currentPageSize = 10; // 기본값
if(pageNo != null && !pageNo.isEmpty()) {
try {
currentPageNo = Integer.parseInt(pageNo);
} catch(NumberFormatException e) {
currentPageNo = 1;
}
}
if(pageSize != null && !pageSize.isEmpty()) {
try {
currentPageSize = Integer.parseInt(pageSize);
} catch(NumberFormatException e) {
currentPageSize = 10;
}
}
// offset 계산
int offset = (currentPageNo - 1) * currentPageSize;
// 페이징 적용
List<InstanceDict> pagedInstanceDictListKo = instanceDictListKo.stream()
.skip(offset)
.limit(currentPageSize)
.toList();
List<InstanceDict> pagedInstanceDictListEn = instanceDictListEn.stream()
.skip(offset)
.limit(currentPageSize)
.toList();
List<InstanceDict> pagedInstanceDictListJa = instanceDictListJa.stream()
.skip(offset)
.limit(currentPageSize)
.toList();
DictionaryResponse.InstanceList itemTotalList = DictionaryResponse.InstanceList.builder()
.ko(pagedInstanceDictListKo)
.en(pagedInstanceDictListEn)
.ja(pagedInstanceDictListJa)
.build();
return DictionaryResponse.builder()
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())
.resultData(DictionaryResponse.ResultData.builder()
.instanceList(itemTotalList)
.totalAll(totalAll)
.total(pagedInstanceDictListKo.size())
.pageNo(currentPageNo)
.build()
)
.build();
}
public void instanceExcelExport(HttpServletResponse response, @RequestParam Map<String, String> requestParam){
String searchType = requestParam.get("search_type");
String searchData = requestParam.get("search_data").trim();
String contentsType = requestParam.get("contents_type");
String accessType = requestParam.get("access_type");
String taskId = requestParam.get("task_id");
String lang = requestParam.get("lang");
if(taskId == null || taskId.isEmpty() || taskId.equals("undefined")){
log.error("craftExcelExport Excel Export taskId is null or empty");
throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_EXCEL_DOWN.toString());
}
LANGUAGETYPE languageType = LANGUAGETYPE.valueOf(lang.toUpperCase());
progressTracker.updateProgress(taskId, 5, 100, "엑셀 생성 준비 중...");
List<MetaInstanceData> items = metaDataHandler.getMetaInstanceListData();
List<InstanceDict> instanceDictList = createInstanceDictList(items, languageType, searchType, searchData, contentsType, accessType);
progressTracker.updateProgress(taskId, 30, 100, "데이터 생성완료");
try{
excelService.generateExcelToResponse(
response,
instanceDictList,
"Instance Dictionary Data",
"sheet1",
taskId
);
}catch (Exception e){
log.error("Excel Export Create Error", e);
throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_EXCEL_DOWN.toString());
}
}
private List<InstanceDict> createInstanceDictList(List<MetaInstanceData> items, LANGUAGETYPE languageType,
String searchType, String searchData, String contentsType, String accessType) {
return items.stream()
.filter(data -> {
boolean result = true;
if(!contentsType.equals("ALL")){
result = result && data.getContentsType().equals(contentsType);
}
if(!accessType.equals("ALL")){
result = result && data.getAccessType().equals(accessType);
}
return result;
})
.map(item -> {
String instanceName = metaDataHandler.getTextStringData(item.getName(), languageType);
return InstanceDict.builder()
.instanceId(item.getId())
.instanceName(instanceName == null || instanceName.isEmpty() ? item.getName() : instanceName)
.owner(item.getOwner())
.buildingId(item.getBuildingId())
.buildingSocket(item.getBuildingSocket())
.contentsType(item.getContentsType())
.mapId(item.getMapId())
.limitCount(item.getLimitCount())
.overLimit(item.getOverLimit())
.accessId(item.getAccessId())
.accessType(item.getAccessType())
.voiceChat(item.getVoiceChat())
.viewType(item.getViewType())
.build();
}).filter(data -> {
boolean result = true;
if(!searchData.isEmpty()){
if(searchType.equals("NAME")){
result = data.getInstanceName().contains(searchData);
}
if(searchType.equals("ID")){
result = data.getInstanceId().toString().equals(searchData);
}
if(searchType.equals("BUILDING")){
result = data.getBuildingId().toString().equals(searchData);
}
}
return result;
})
.collect(Collectors.toList());
}
}