초기커밋
This commit is contained in:
324
UGQDataAccess/Service/AccountService.cs
Normal file
324
UGQDataAccess/Service/AccountService.cs
Normal file
@@ -0,0 +1,324 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UGQDataAccess.Repository;
|
||||
using UGQDataAccess.Repository.Models;
|
||||
using UGQDatabase.Models;
|
||||
using ServerCore; using ServerBase;
|
||||
using ServerCommon;
|
||||
using UGQDataAccess.Logs;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace UGQDataAccess.Service;
|
||||
|
||||
public class AccountService
|
||||
{
|
||||
readonly QuestIdSequenceRepository _questIdSequenceRepository;
|
||||
readonly QuestContentRepository _questContentRepository;
|
||||
readonly QuestDialogRepository _questDialogRepository;
|
||||
readonly AccountRepository _accountRepository;
|
||||
readonly GameQuestDataRepository _gameQuestDataRepository;
|
||||
readonly CreatorPointHistoryRepository _creatorPointHistoryRepository;
|
||||
readonly NpcNameRepository _npcNameRepository;
|
||||
readonly UgqMetaGenerateService _ugqMetaGenerateService;
|
||||
readonly ReserveAccountGradeRepository _reserveAccountGradeRepository;
|
||||
|
||||
public AccountService(QuestIdSequenceRepository questIdSequenceRepository,
|
||||
QuestContentRepository questContentRepository,
|
||||
QuestDialogRepository questDialogRepository,
|
||||
AccountRepository accountRepository,
|
||||
GameQuestDataRepository gameQuestDataRepository,
|
||||
CreatorPointHistoryRepository creatorPointHistoryRepository,
|
||||
NpcNameRepository npcNameRepository,
|
||||
UgqMetaGenerateService ugqMetaGenerateService,
|
||||
ReserveAccountGradeRepository reserveAccountGradeRepository)
|
||||
{
|
||||
_questIdSequenceRepository = questIdSequenceRepository;
|
||||
_questContentRepository = questContentRepository;
|
||||
_questDialogRepository = questDialogRepository;
|
||||
_accountRepository = accountRepository;
|
||||
_gameQuestDataRepository = gameQuestDataRepository;
|
||||
_creatorPointHistoryRepository = creatorPointHistoryRepository;
|
||||
_npcNameRepository = npcNameRepository;
|
||||
_ugqMetaGenerateService = ugqMetaGenerateService;
|
||||
_reserveAccountGradeRepository = reserveAccountGradeRepository;
|
||||
}
|
||||
|
||||
public async Task<AllAccountQueryResult> getAccounts(int pageNumber, int pageSize, string? searchText, AccountSortType sortType)
|
||||
{
|
||||
return await _accountRepository.getAccounts(pageNumber, pageSize, searchText, sortType);
|
||||
}
|
||||
|
||||
public async Task<long> getAllAccountCount()
|
||||
{
|
||||
return await _accountRepository.getAllCount();
|
||||
}
|
||||
|
||||
|
||||
public async Task<AccountEntity?> getAccount(string userGuid)
|
||||
{
|
||||
return await _accountRepository.get(userGuid);
|
||||
}
|
||||
|
||||
public async Task<AccountEntity?> getAccountByAccountId(string accountId)
|
||||
{
|
||||
return await _accountRepository.getByAccountId(accountId);
|
||||
}
|
||||
|
||||
public async Task<AccountEntity> getOrInsertAccount(string userGuid, string nickname, string accountId)
|
||||
{
|
||||
return await _accountRepository.getOrInsert(userGuid, nickname, accountId);
|
||||
}
|
||||
|
||||
public async Task<AccountEntity?> saveRefreshToken(string userGuid, string refreshToken, DateTime? refreshTokenExpryTime)
|
||||
{
|
||||
return await _accountRepository.saveRefreshToken(userGuid, refreshToken, refreshTokenExpryTime);
|
||||
}
|
||||
|
||||
public async Task<AccountEntity?> deleteRefreshToken(string userGuid)
|
||||
{
|
||||
return await _accountRepository.deleteRefreshToken(userGuid);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, AccountEntity?)> addSlotCount(string userGuid, int count, int? slotCountVersion)
|
||||
{
|
||||
if(count < 1)
|
||||
return (ServerErrorCode.UgqServerException, null);
|
||||
|
||||
// 슬롯 증가는 재시도 없이 변경 못했으면 실패 리턴
|
||||
var updated = await _accountRepository.addSlotCount(userGuid, slotCountVersion, count);
|
||||
if (updated == null)
|
||||
return (ServerErrorCode.UgqExceedTransactionRetry, null);
|
||||
|
||||
return (ServerErrorCode.Success, updated);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, AccountEntity?)> modifySlotCount(string userGuid, int count, string adminUsername)
|
||||
{
|
||||
int retryCount = 0;
|
||||
while (retryCount < UGQConstants.MAX_UPDATE_RETRY_COUNT)
|
||||
{
|
||||
var entity = await _accountRepository.get(userGuid);
|
||||
if (entity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
int haveCount = ServerCommon.MetaHelper.GameConfigMeta.UGQDefaultSlot + entity.AdditionalSlotCount + count;
|
||||
if (haveCount < 0 || haveCount > ServerCommon.MetaHelper.GameConfigMeta.UGQMaximumSlot)
|
||||
return (ServerErrorCode.UgqSlotLimit, null);
|
||||
|
||||
var updated = await _accountRepository.addSlotCount(userGuid, entity.SlotCountVersion, count);
|
||||
if (updated == null)
|
||||
{
|
||||
retryCount++;
|
||||
Log.getLogger().warn($"slotCount version missmatch. retryCount: {retryCount}");
|
||||
continue;
|
||||
}
|
||||
|
||||
List<ILogInvoker> business_logs = [
|
||||
new UgqApiAddSlotBusinessLog(updated.AdditionalSlotCount, adminUsername),
|
||||
];
|
||||
var log_action = new LogActionEx(LogActionType.UgqApiAddSlot);
|
||||
UgqApiBusinessLogger.collectLogs(log_action, updated.UserGuid, business_logs);
|
||||
|
||||
return (ServerErrorCode.Success, updated);
|
||||
}
|
||||
|
||||
return (ServerErrorCode.UgqExceedTransactionRetry, null);
|
||||
}
|
||||
|
||||
|
||||
public async Task<ServerErrorCode> addCreatorPoint(string userGuid, long questId, long revision, double amount, UgqCreatorPointReason reason)
|
||||
{
|
||||
int retryCount = 0;
|
||||
while (retryCount < UGQConstants.MAX_UPDATE_RETRY_COUNT)
|
||||
{
|
||||
var entity = await _accountRepository.getOrInsertForGameUser(userGuid);
|
||||
if (entity == null)
|
||||
return ServerErrorCode.UgqNullEntity;
|
||||
|
||||
var updated = await _accountRepository.incCreatorPoint(userGuid, entity.CreatorPointVersion, amount);
|
||||
if (updated == null)
|
||||
{
|
||||
retryCount++;
|
||||
Log.getLogger().warn($"creatorPoint version missmatch. retryCount: {retryCount}");
|
||||
continue;
|
||||
}
|
||||
|
||||
CreatorPointHistoryEntity historyEntity = new CreatorPointHistoryEntity
|
||||
{
|
||||
UserGuid = userGuid,
|
||||
QuestId = questId,
|
||||
Revision = revision,
|
||||
Kind = CreatorPointHistoryKind.QuestProfit,
|
||||
DetailReason = "Development",
|
||||
Amount = amount,
|
||||
TotalAmount = updated.CreatorPoint,
|
||||
CreatedAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
await _creatorPointHistoryRepository.insert(historyEntity);
|
||||
|
||||
List<ILogInvoker> business_logs = [
|
||||
new UgqApiCreatorPointBusinessLog(amount, questId, revision, "", reason, ""),
|
||||
];
|
||||
var log_action = new LogActionEx(LogActionType.UgqApiCreatorPoint);
|
||||
UgqApiBusinessLogger.collectLogs(log_action, userGuid, business_logs);
|
||||
|
||||
return ServerErrorCode.Success;
|
||||
}
|
||||
|
||||
return ServerErrorCode.UgqExceedTransactionRetry;
|
||||
}
|
||||
|
||||
public async Task<ServerErrorCode> decCreatorPoint(string userGuid, int amount, UgqCreatorPointReason reason)
|
||||
{
|
||||
int retryCount = 0;
|
||||
while (retryCount < UGQConstants.MAX_UPDATE_RETRY_COUNT)
|
||||
{
|
||||
var entity = await _accountRepository.get(userGuid);
|
||||
if (entity == null)
|
||||
return ServerErrorCode.UgqNullEntity;
|
||||
|
||||
// 포인트가 0보다 작아지지 않게 처리해야 한다
|
||||
if (entity.CreatorPoint < amount)
|
||||
return ServerErrorCode.UgqNotEnoughCreatorPoint;
|
||||
|
||||
int creatorPointVersion = entity.CreatorPointVersion ?? 1;
|
||||
|
||||
var updated = await _accountRepository.incCreatorPoint(userGuid, creatorPointVersion, -amount);
|
||||
if (updated == null)
|
||||
{
|
||||
retryCount++;
|
||||
Log.getLogger().warn($"creatorPoint version missmatch. retryCount: {retryCount}");
|
||||
continue;
|
||||
}
|
||||
|
||||
CreatorPointHistoryEntity historyEntity = new CreatorPointHistoryEntity
|
||||
{
|
||||
UserGuid = userGuid,
|
||||
QuestId = 0,
|
||||
Revision = 0,
|
||||
Kind = CreatorPointHistoryKind.SettleUp,
|
||||
DetailReason = "Development",
|
||||
Amount = -amount,
|
||||
TotalAmount = updated.CreatorPoint,
|
||||
CreatedAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
await _creatorPointHistoryRepository.insert(historyEntity);
|
||||
|
||||
List<ILogInvoker> business_logs = [
|
||||
new UgqApiCreatorPointBusinessLog(-amount, 0, 0, "", reason, ""),
|
||||
];
|
||||
var log_action = new LogActionEx(LogActionType.UgqApiCreatorPoint);
|
||||
UgqApiBusinessLogger.collectLogs(log_action, userGuid, business_logs);
|
||||
|
||||
return ServerErrorCode.Success;
|
||||
}
|
||||
|
||||
return ServerErrorCode.UgqExceedTransactionRetry;
|
||||
}
|
||||
|
||||
public async Task<AccountEntity?> modifyAccountGrade(string userGuid, UgqGradeType grade)
|
||||
{
|
||||
return await _accountRepository.modifyAccountGrade(userGuid, grade);
|
||||
}
|
||||
|
||||
public async Task<AccountEntity?> promoteAccountGrade(string userGuid, UgqGradeType before, UgqGradeType after)
|
||||
{
|
||||
return await _accountRepository.promoteAccountGrade(userGuid, before, after);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, AccountEntity?)> modifyCreatorPoint(string userGuid, int amount, string reason, string adminUsername)
|
||||
{
|
||||
int retryCount = 0;
|
||||
while (retryCount < UGQConstants.MAX_UPDATE_RETRY_COUNT)
|
||||
{
|
||||
var entity = await _accountRepository.get(userGuid);
|
||||
if (entity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
// 포인트가 0보다 작아지지 않게 처리해야 한다
|
||||
if (amount < 0 && entity.CreatorPoint < -amount)
|
||||
return (ServerErrorCode.UgqNotEnoughCreatorPoint, null);
|
||||
|
||||
int? creatorPointVersion = entity.CreatorPointVersion;
|
||||
|
||||
var updated = await _accountRepository.incCreatorPoint(userGuid, creatorPointVersion, amount);
|
||||
if (updated == null)
|
||||
{
|
||||
retryCount++;
|
||||
Log.getLogger().warn($"creatorPoint version missmatch. retryCount: {retryCount}");
|
||||
continue;
|
||||
}
|
||||
|
||||
CreatorPointHistoryEntity historyEntity = new CreatorPointHistoryEntity
|
||||
{
|
||||
UserGuid = userGuid,
|
||||
QuestId = 0,
|
||||
Revision = 0,
|
||||
Kind = CreatorPointHistoryKind.Admin,
|
||||
DetailReason = reason,
|
||||
Amount = amount,
|
||||
TotalAmount = updated.CreatorPoint,
|
||||
CreatedAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
await _creatorPointHistoryRepository.insert(historyEntity);
|
||||
|
||||
List<ILogInvoker> business_logs = [
|
||||
new UgqApiCreatorPointBusinessLog(amount, 0, 0, adminUsername, UgqCreatorPointReason.Admin, reason),
|
||||
];
|
||||
var log_action = new LogActionEx(LogActionType.UgqApiCreatorPoint);
|
||||
UgqApiBusinessLogger.collectLogs(log_action, userGuid, business_logs);
|
||||
|
||||
return (ServerErrorCode.Success, updated);
|
||||
}
|
||||
|
||||
return (ServerErrorCode.UgqExceedTransactionRetry, null);
|
||||
}
|
||||
|
||||
public async Task<AllReserveAccountGradeResult> getReserveAccountGrades(int pageNumber, int pageSize, AccountGradeSortType sortType, AccountGradeProcessType processType, string userGuid)
|
||||
{
|
||||
return await _reserveAccountGradeRepository.getAccounts(pageNumber, pageSize, sortType, processType, userGuid);
|
||||
}
|
||||
|
||||
public async Task<long> getAllReserveAccountGradeCount()
|
||||
{
|
||||
return await _reserveAccountGradeRepository.getAllCount();
|
||||
}
|
||||
|
||||
public async Task<ReserveAccountGradeEntity?> getReserveAccountGrade(string userGuid)
|
||||
{
|
||||
return await _reserveAccountGradeRepository.get(userGuid);
|
||||
}
|
||||
|
||||
public async Task<List<ReserveAccountGradeEntity>> getReserveAccountGrade(string userGuid, AccountGradeProcessType processType)
|
||||
{
|
||||
return await _reserveAccountGradeRepository.get(userGuid, processType);
|
||||
}
|
||||
|
||||
public async Task<ReserveAccountGradeEntity> reserveAccountGrade(string userGuid, UgqGradeType beforeGrade, UgqGradeType grade, DateTime reserveTime)
|
||||
{
|
||||
return await _reserveAccountGradeRepository.reserveAccountGrade(userGuid, beforeGrade, grade, reserveTime);
|
||||
}
|
||||
|
||||
public async Task<ReserveAccountGradeEntity> modifyReserveAccountGrade(string reserveId, UgqGradeType grade, DateTime reserveTime)
|
||||
{
|
||||
return await _reserveAccountGradeRepository.modifyReserveAccountGrade(reserveId, grade, reserveTime);
|
||||
}
|
||||
|
||||
public async Task<List<ReserveAccountGradeEntity>> completeReserveAccountGrade()
|
||||
{
|
||||
return await _reserveAccountGradeRepository.completeReserveAccountGrade();
|
||||
}
|
||||
|
||||
public async Task<ServerErrorCode> deleteReserveAccountGrade(string reserveId)
|
||||
{
|
||||
return await _reserveAccountGradeRepository.deleteReserveAccountGrade(reserveId);
|
||||
}
|
||||
}
|
||||
67
UGQDataAccess/Service/AdminService.cs
Normal file
67
UGQDataAccess/Service/AdminService.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UGQDataAccess.Repository.Models;
|
||||
using UGQDataAccess.Repository;
|
||||
using UGQDatabase.Models;
|
||||
using ServerCommon;
|
||||
using StackExchange.Redis;
|
||||
|
||||
namespace UGQDataAccess.Service
|
||||
{
|
||||
public class AdminService
|
||||
{
|
||||
readonly AdminAccountRepository _adminAccountRepository;
|
||||
|
||||
public AdminService(AdminAccountRepository adminAccountRepository)
|
||||
{
|
||||
_adminAccountRepository = adminAccountRepository;
|
||||
}
|
||||
|
||||
public async Task<AdminAccountEntity?> get(string username)
|
||||
{
|
||||
return await _adminAccountRepository.get(username);
|
||||
}
|
||||
|
||||
public async Task<AdminAccountEntity?> signup(string username, string password, UGQAccountRole role)
|
||||
{
|
||||
var passwordHash = BCrypt.Net.BCrypt.HashPassword(password);
|
||||
return await _adminAccountRepository.signup(username, passwordHash, role);
|
||||
}
|
||||
|
||||
public async Task<AdminAccountEntity?> login(string username, string password)
|
||||
{
|
||||
var entity = await _adminAccountRepository.get(username);
|
||||
if (entity == null)
|
||||
return null;
|
||||
|
||||
if (BCrypt.Net.BCrypt.Verify(password, entity.Password) == false)
|
||||
return null;
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public async Task<AdminAccountEntity?> changePassword(string username, string newPassword)
|
||||
{
|
||||
var entity = await _adminAccountRepository.get(username);
|
||||
if (entity == null)
|
||||
return null;
|
||||
|
||||
var passwordHash = BCrypt.Net.BCrypt.HashPassword(newPassword);
|
||||
return await _adminAccountRepository.changePassword(username, passwordHash);
|
||||
}
|
||||
|
||||
public async Task<AdminAccountEntity?> saveRefreshToken(string id, string refreshToken, DateTime? refreshTokenExpryTime)
|
||||
{
|
||||
return await _adminAccountRepository.saveRefreshToken(id, refreshToken, refreshTokenExpryTime);
|
||||
}
|
||||
|
||||
public async Task<AdminAccountEntity?> deleteRefreshToken(string userGuid)
|
||||
{
|
||||
return await _adminAccountRepository.deleteRefreshToken(userGuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
313
UGQDataAccess/Service/InGameService.cs
Normal file
313
UGQDataAccess/Service/InGameService.cs
Normal file
@@ -0,0 +1,313 @@
|
||||
using MongoDB.Driver;
|
||||
using UGQDatabase.Models;
|
||||
using UGQDataAccess.Repository;
|
||||
using UGQDataAccess.Repository.Models;
|
||||
using ServerCommon.UGQ;
|
||||
using ServerCommon.UGQ.Models;
|
||||
using System.Text.Json;
|
||||
using Amazon.DynamoDBv2.Model;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using ServerCommon;
|
||||
using MetaAssets;
|
||||
|
||||
namespace UGQDataAccess.Service;
|
||||
|
||||
|
||||
public class InGameService
|
||||
{
|
||||
readonly QuestContentRepository _questContentRepository;
|
||||
readonly QuestDialogRepository _questDialogRepository;
|
||||
readonly LikeRepository _likeRepository;
|
||||
readonly BookmarkRepository _bookmarkRepository;
|
||||
readonly NpcNameRepository _npcNameRepository;
|
||||
readonly GameQuestDataRepository _gameQuestDataRepository;
|
||||
readonly ReportRepository _reportRepository;
|
||||
readonly AccountRepository _accountRepository;
|
||||
readonly QuestAcceptedRepository _questAccceptedRepository;
|
||||
readonly QuestCompletedRepository _questCompletedRepository;
|
||||
readonly QuestAbortedRepository _questAbortedRepository;
|
||||
readonly CreatorPointHistoryRepository _creatorPointHistoryRepository;
|
||||
|
||||
readonly AccountService _accountService;
|
||||
|
||||
public InGameService(
|
||||
AccountService accountService,
|
||||
QuestContentRepository questContentRepository,
|
||||
QuestDialogRepository questDialogRepository,
|
||||
LikeRepository likeRepository,
|
||||
BookmarkRepository bookmarkRepository,
|
||||
NpcNameRepository npcNameRepository,
|
||||
GameQuestDataRepository gameQuestDataRepository,
|
||||
ReportRepository reportRepository,
|
||||
AccountRepository accountRepository,
|
||||
QuestAcceptedRepository accceptedRepository,
|
||||
QuestCompletedRepository completedRepository,
|
||||
QuestAbortedRepository questAbortedRepository,
|
||||
CreatorPointHistoryRepository creatorPointHistoryRepository)
|
||||
{
|
||||
_accountService = accountService;
|
||||
_questContentRepository = questContentRepository;
|
||||
_questDialogRepository = questDialogRepository;
|
||||
_likeRepository = likeRepository;
|
||||
_bookmarkRepository = bookmarkRepository;
|
||||
_npcNameRepository = npcNameRepository;
|
||||
_gameQuestDataRepository = gameQuestDataRepository;
|
||||
_reportRepository = reportRepository;
|
||||
_accountRepository = accountRepository;
|
||||
|
||||
_questAccceptedRepository = accceptedRepository;
|
||||
_questCompletedRepository = completedRepository;
|
||||
_questAbortedRepository = questAbortedRepository;
|
||||
|
||||
_creatorPointHistoryRepository = creatorPointHistoryRepository;
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, AccountEntity?)> getAccount(string userGuid)
|
||||
{
|
||||
AccountEntity? entity = await _accountRepository.get(userGuid);
|
||||
if (entity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
return (ServerErrorCode.Success, entity);
|
||||
}
|
||||
|
||||
public async Task<List<QuestContentEntity>> getUserQuests(string userGuid, IEnumerable<QuestContentState> states)
|
||||
{
|
||||
return await _questContentRepository.getUserQuests(userGuid, states);
|
||||
}
|
||||
|
||||
public async Task<QuestBoardQueryResult> getQuestBoard(string? userGuid, UgqQuestBoardRequest request, int pageSize)
|
||||
{
|
||||
return await _questContentRepository.getQuestBoard(userGuid, request, pageSize);
|
||||
}
|
||||
|
||||
public async Task<QuestBoardQueryResult> getBookmarkQuests(string userGuid, UgqQuestBoardRequest request, int pageSize)
|
||||
{
|
||||
return await _questContentRepository.getBookmarkQuests(userGuid, request, pageSize);
|
||||
}
|
||||
|
||||
public async Task<QuestBoardSportlightQueryResult> getQuestBoardSpotlight()
|
||||
{
|
||||
return await _questContentRepository.getQuestBoardSpotlight();
|
||||
}
|
||||
|
||||
public async Task<QuestBoardDetailItemResult?> getQuestBoardDetail(string userGuid, long questId, long revision)
|
||||
{
|
||||
return await _questContentRepository.getQuestBoardDetail(userGuid, questId, revision);
|
||||
}
|
||||
|
||||
public async Task<ServerErrorCode> bookmark(long questId, string userGuid)
|
||||
{
|
||||
var entity = await _bookmarkRepository.get(questId, userGuid);
|
||||
if (entity != null)
|
||||
return ServerErrorCode.UgqAlreadyBookmarked;
|
||||
|
||||
return await _bookmarkRepository.insert(questId, userGuid);
|
||||
}
|
||||
|
||||
public async Task<ServerErrorCode> unbookmark(long questId, string userGuid)
|
||||
{
|
||||
var entity = await _bookmarkRepository.get(questId, userGuid);
|
||||
if (entity == null)
|
||||
return ServerErrorCode.UgqNotBookmarked;
|
||||
|
||||
return await _bookmarkRepository.delete(questId, userGuid);
|
||||
}
|
||||
|
||||
public async Task<ServerErrorCode> like(long questId, long revision, string userGuid)
|
||||
{
|
||||
var entity = await _likeRepository.get(questId, userGuid);
|
||||
if (entity != null)
|
||||
return ServerErrorCode.UgqAlreadyLiked;
|
||||
|
||||
return await _likeRepository.insert(questId, revision, userGuid);
|
||||
}
|
||||
|
||||
public async Task<ServerErrorCode> unlike(long questId, long revision, string userGuid)
|
||||
{
|
||||
var entity = await _likeRepository.get(questId, userGuid);
|
||||
if (entity == null)
|
||||
return ServerErrorCode.UgqNotLiked;
|
||||
|
||||
return await _likeRepository.delete(questId, revision, userGuid);
|
||||
}
|
||||
|
||||
public async Task<ServerErrorCode> report(string userGuid, long questId, long revision, string contents)
|
||||
{
|
||||
var entity = await _reportRepository.get(questId, revision, userGuid);
|
||||
if (entity != null)
|
||||
return ServerErrorCode.UgqAlreadyReported;
|
||||
|
||||
await _reportRepository.insert(questId, revision, userGuid, contents);
|
||||
return ServerErrorCode.Success;
|
||||
}
|
||||
|
||||
public async Task<ServerErrorCode> setQuestAccepted(string userGuid, UgqQuestAcceptedRequest request)
|
||||
{
|
||||
var gameQuestData = await _gameQuestDataRepository.get(request.QuestId, request.Revision, QuestContentState.Live);
|
||||
if (gameQuestData == null)
|
||||
return ServerErrorCode.UgqNullEntity;
|
||||
|
||||
string author = gameQuestData.UserGuid;
|
||||
|
||||
await _questAccceptedRepository.insert(request.QuestId, request.Revision, author, request.Reason, userGuid);
|
||||
return ServerErrorCode.Success;
|
||||
}
|
||||
|
||||
public async Task<ServerErrorCode> setQuestCompleted(string userGuid, UgqQuestCompletedRequest request)
|
||||
{
|
||||
var gameQuestData = await _gameQuestDataRepository.get(request.QuestId, request.Revision, QuestContentState.Live);
|
||||
if (gameQuestData == null)
|
||||
return ServerErrorCode.UgqNullEntity;
|
||||
|
||||
string author = gameQuestData.UserGuid;
|
||||
|
||||
await _questCompletedRepository.insert(request.QuestId, request.Revision, author, userGuid);
|
||||
|
||||
double cost = 0.0f;
|
||||
switch (gameQuestData.GradeType)
|
||||
{
|
||||
case UgqGradeType.Amature: cost = MetaHelper.GameConfigMeta.UgqUsageFeeAmateur / 2.0f; break;
|
||||
case UgqGradeType.RisingStar: cost = MetaHelper.GameConfigMeta.UgqUsageFeeRisingStar / 10.0f; break;
|
||||
case UgqGradeType.Master1: cost = MetaHelper.GameConfigMeta.UgqUsageFeeMaster1 / 2.0f; break;
|
||||
case UgqGradeType.Master2: cost = MetaHelper.GameConfigMeta.UgqUsageFeeMaster2 / 2.0f; break;
|
||||
case UgqGradeType.Master3: cost = MetaHelper.GameConfigMeta.UgqUsageFeeMaster3 / 2.0f; break;
|
||||
default:
|
||||
return ServerErrorCode.UgqCurrencyError;
|
||||
}
|
||||
/*
|
||||
long completeCount = await _questCompletedRepository.getCount(author);
|
||||
if(completeCount >= MetaHelper.GameConfigMeta.UGQPromoteConditionRisingstar)
|
||||
{
|
||||
await _accountService.promoteAccountGrade(author, UgqGradeType.Amature, UgqGradeType.RisingStar);
|
||||
}
|
||||
*/
|
||||
|
||||
return await _accountService.addCreatorPoint(author, request.QuestId, request.Revision, cost, UgqCreatorPointReason.QuestCompleted);
|
||||
|
||||
}
|
||||
|
||||
public async Task<ServerErrorCode> setQuestAborted(string userGuid, UgqQuestAbortedRequest request)
|
||||
{
|
||||
var gameQuestData = await _gameQuestDataRepository.get(request.QuestId, request.Revision, QuestContentState.Live);
|
||||
if (gameQuestData == null)
|
||||
return ServerErrorCode.UgqNullEntity;
|
||||
|
||||
string author = gameQuestData.UserGuid;
|
||||
|
||||
await _questAbortedRepository.insert(request.QuestId, request.Revision, author, request.Reason, userGuid);
|
||||
return ServerErrorCode.Success;
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, QuestContentEntity?)> changeQuestStateForInGame(string userGuid,
|
||||
long questId, long revision,
|
||||
IEnumerable<QuestContentState> before, QuestContentState after)
|
||||
{
|
||||
var content = await _questContentRepository.getByQuestIdRevision(questId, revision);
|
||||
if (content == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
var errorCode = ServerErrorCode.Success;
|
||||
QuestContentEntity? updated = null;
|
||||
switch (after)
|
||||
{
|
||||
case QuestContentState.Standby:
|
||||
updated = await _questContentRepository.updateState(content.Id,
|
||||
content.QuestId, content.Revision, before, after);
|
||||
break;
|
||||
case QuestContentState.Editable:
|
||||
updated = await _questContentRepository.updateState(content.Id,
|
||||
content.QuestId, content.Revision, before, after);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> Test <20><><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||||
await _gameQuestDataRepository.delete(content.QuestId, content.Revision, QuestContentState.Test);
|
||||
break;
|
||||
default:
|
||||
errorCode = ServerErrorCode.UgqStateChangeError;
|
||||
break;
|
||||
}
|
||||
|
||||
if (updated == null)
|
||||
return (ServerErrorCode.UgqStateChangeError, null);
|
||||
|
||||
return (errorCode, updated);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, GameQuestDataEntity?)> getTestGameQuestData(string userGuid, long questId, long revision)
|
||||
{
|
||||
GameQuestDataEntity? entity = await _gameQuestDataRepository.get(questId, revision, QuestContentState.Test);
|
||||
if (entity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20>ۼ<EFBFBD><DBBC><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ <20><> Test <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
if (entity.UserGuid != userGuid)
|
||||
return (ServerErrorCode.UgqNotOwnQuest, null);
|
||||
|
||||
return (ServerErrorCode.Success, entity);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, GameQuestDataEntity?)> getGameQuestData(long questId, long revision, QuestContentState state)
|
||||
{
|
||||
GameQuestDataEntity? entity = await _gameQuestDataRepository.get(questId, revision, state);
|
||||
if(entity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
return (ServerErrorCode.Success, entity);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, GameQuestDataEntity?)> getLatestRevisionGameQuestData(long questId)
|
||||
{
|
||||
GameQuestDataEntity? entity = await _gameQuestDataRepository.getLatestRevision(questId);
|
||||
if (entity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
return (ServerErrorCode.Success, entity);
|
||||
}
|
||||
|
||||
public async Task setAuthor()
|
||||
{
|
||||
{
|
||||
var list = await _questAbortedRepository.getAll();
|
||||
foreach (var item in list)
|
||||
{
|
||||
var gameQuestData = await _gameQuestDataRepository.get(item.QuestId, item.Revision, QuestContentState.Live);
|
||||
if (gameQuestData == null)
|
||||
continue;
|
||||
|
||||
string author = gameQuestData.UserGuid;
|
||||
await _questAbortedRepository.setAuthor(item.Id, author);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var list = await _questAccceptedRepository.getAll();
|
||||
foreach (var item in list)
|
||||
{
|
||||
var gameQuestData = await _gameQuestDataRepository.get(item.QuestId, item.Revision, QuestContentState.Live);
|
||||
if (gameQuestData == null)
|
||||
continue;
|
||||
|
||||
string author = gameQuestData.UserGuid;
|
||||
await _questAccceptedRepository.setAuthor(item.Id, author);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var list = await _questCompletedRepository.getAll();
|
||||
foreach (var item in list)
|
||||
{
|
||||
var gameQuestData = await _gameQuestDataRepository.get(item.QuestId, item.Revision, QuestContentState.Live);
|
||||
if (gameQuestData == null)
|
||||
continue;
|
||||
|
||||
string author = gameQuestData.UserGuid;
|
||||
await _questCompletedRepository.setAuthor(item.Id, author);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
499
UGQDataAccess/Service/QuestEditorService.cs
Normal file
499
UGQDataAccess/Service/QuestEditorService.cs
Normal file
@@ -0,0 +1,499 @@
|
||||
using MongoDB.Driver;
|
||||
using ServerCommon;
|
||||
using ServerCore; using ServerBase;
|
||||
using UGQDataAccess.Logs;
|
||||
using UGQDataAccess.Repository;
|
||||
using UGQDataAccess.Repository.Models;
|
||||
using UGQDatabase.Models;
|
||||
|
||||
|
||||
namespace UGQDataAccess.Service;
|
||||
|
||||
|
||||
public class QuestEditorService
|
||||
{
|
||||
readonly QuestIdSequenceRepository _questIdSequenceRepository;
|
||||
readonly QuestContentRepository _questContentRepository;
|
||||
readonly QuestDialogRepository _questDialogRepository;
|
||||
readonly GameQuestDataRepository _gameQuestDataRepository;
|
||||
readonly CreatorPointHistoryRepository _creatorPointHistoryRepository;
|
||||
readonly NpcNameRepository _npcNameRepository;
|
||||
readonly UgqMetaGenerateService _ugqMetaGenerateService;
|
||||
readonly AccountService _accountService;
|
||||
|
||||
public QuestEditorService(
|
||||
AccountService accountService,
|
||||
QuestIdSequenceRepository questIdSequenceRepository,
|
||||
QuestContentRepository questContentRepository,
|
||||
QuestDialogRepository questDialogRepository,
|
||||
GameQuestDataRepository gameQuestDataRepository,
|
||||
CreatorPointHistoryRepository creatorPointHistoryRepository,
|
||||
NpcNameRepository npcNameRepository,
|
||||
UgqMetaGenerateService ugqMetaGenerateService)
|
||||
|
||||
{
|
||||
_accountService = accountService;
|
||||
_questIdSequenceRepository = questIdSequenceRepository;
|
||||
_questContentRepository = questContentRepository;
|
||||
_questDialogRepository = questDialogRepository;
|
||||
_gameQuestDataRepository = gameQuestDataRepository;
|
||||
_creatorPointHistoryRepository = creatorPointHistoryRepository;
|
||||
_npcNameRepository = npcNameRepository;
|
||||
_ugqMetaGenerateService = ugqMetaGenerateService;
|
||||
}
|
||||
|
||||
public async Task<AllSummaryQueryResult> getAllQuests(int pageNumber, int pageSize, QuestContentState state, string? searchText)
|
||||
{
|
||||
return await _questContentRepository.getAllSummaries(pageNumber, pageSize, state, searchText);
|
||||
}
|
||||
|
||||
public async Task<List<QuestContentEntity>> getAll(string userGuid)
|
||||
{
|
||||
return await _questContentRepository.getAll(userGuid);
|
||||
}
|
||||
|
||||
public async Task<long> getAllCount()
|
||||
{
|
||||
return await _questContentRepository.getAllCount();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task<SummaryQueryResult> getSummaries(int pageNumber, int pageSize, string userGuid, QuestContentState state, string? searchText)
|
||||
{
|
||||
return await _questContentRepository.getSummaries(pageNumber, pageSize, userGuid, state, searchText);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, QuestContentEntity?)> addQuest(string userGuid, UGQSaveQuestModel saveQuestModel, string adminUsername)
|
||||
{
|
||||
var accountEntity = await _accountService.getAccount(userGuid);
|
||||
if (accountEntity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
List<QuestContentEntity> quests = await _questContentRepository.getAll(userGuid);
|
||||
|
||||
int slotCount = ServerCommon.MetaHelper.GameConfigMeta.UGQDefaultSlot + accountEntity.AdditionalSlotCount;
|
||||
if (slotCount <= quests.Count)
|
||||
return (ServerErrorCode.UgqNotEnoughQuestSlot, null);
|
||||
|
||||
var State = QuestContentState.Editable;
|
||||
foreach(var task in saveQuestModel.Tasks)
|
||||
{
|
||||
if(task.ActionId == 0)
|
||||
{
|
||||
State = QuestContentState.Uncomplate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QuestContentEntity entity = new()
|
||||
{
|
||||
QuestId = 0,
|
||||
Revision = 0,
|
||||
UserGuid = userGuid,
|
||||
Author = accountEntity.Nickname,
|
||||
|
||||
BeaconId = saveQuestModel.BeaconId,
|
||||
UgcBeaconGuid = saveQuestModel.UgcBeaconGuid,
|
||||
UgcBeaconNickname = saveQuestModel.UgcBeaconNickname,
|
||||
GradeType = accountEntity.GradeType,
|
||||
|
||||
Title = new TextEntity
|
||||
{
|
||||
Kr = saveQuestModel.Title.Kr,
|
||||
En = saveQuestModel.Title.En,
|
||||
Jp = saveQuestModel.Title.Jp,
|
||||
},
|
||||
Langs = saveQuestModel.Languages.ToList(),
|
||||
Description = new TextEntity
|
||||
{
|
||||
Kr = saveQuestModel.Description.Kr,
|
||||
En = saveQuestModel.Description.En,
|
||||
Jp = saveQuestModel.Description.Jp,
|
||||
},
|
||||
UploadCounter = 0,
|
||||
TitleImagePath = string.Empty,
|
||||
BannerImagePath = string.Empty,
|
||||
State = State,
|
||||
Cost = saveQuestModel.Cost,
|
||||
Tasks = saveQuestModel.Tasks.Select(x => new TaskEntity
|
||||
{
|
||||
GoalText = new TextEntity
|
||||
{
|
||||
Kr = x.GoalText.Kr,
|
||||
En = x.GoalText.En,
|
||||
Jp = x.GoalText.Jp,
|
||||
},
|
||||
ActionId = x.ActionId,
|
||||
ActionValue = x.ActionValue,
|
||||
IsShowNpcLocation = x.IsShowNpcLocation,
|
||||
UgcActionValueGuid = x.UgcActionValueGuid,
|
||||
UgcActionValueName = x.UgcActionValueName,
|
||||
}).ToList(),
|
||||
Savelanguage = saveQuestModel.Savelanguage,
|
||||
ContentVersion = 1,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
UpdatedAt = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
await _questContentRepository.insert(entity);
|
||||
|
||||
List<ILogInvoker> business_logs = [
|
||||
new UgqApiQuestCraeteBusinessLog(entity.Id, adminUsername),
|
||||
];
|
||||
var log_action = new LogActionEx(LogActionType.UgqApiQuestCraete);
|
||||
UgqApiBusinessLogger.collectLogs(log_action, userGuid, business_logs);
|
||||
|
||||
return (ServerErrorCode.Success, entity);
|
||||
}
|
||||
|
||||
public async Task<ServerErrorCode> deleteQuest(string userGuid, string questContentId)
|
||||
{
|
||||
return await _questContentRepository.deleteQuest(userGuid, questContentId);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, QuestContentEntity?)> getQuest(string userGuid, string questContentId)
|
||||
{
|
||||
var entity = await _questContentRepository.get(questContentId);
|
||||
if (entity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
if (entity?.UserGuid != userGuid)
|
||||
return (ServerErrorCode.UgqNotOwnQuest, null);
|
||||
|
||||
return (ServerErrorCode.Success, entity);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, QuestContentEntity?)> editQuest(string userGuid, string questContentId)
|
||||
{
|
||||
(ServerErrorCode errorCode, var entity) = await getQuest(userGuid, questContentId);
|
||||
if (errorCode != ServerErrorCode.Success)
|
||||
return (errorCode, null);
|
||||
|
||||
if (entity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
if (entity.State != QuestContentState.Editable &&
|
||||
entity.State != QuestContentState.Uncomplate)
|
||||
return (ServerErrorCode.UgqNotAllowEdit, null);
|
||||
|
||||
return (ServerErrorCode.Success, entity);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, QuestContentEntity?)> saveQuest(string userGuid,
|
||||
string questContentId, UGQSaveQuestModel saveQuestModel)
|
||||
{
|
||||
int retryCount = 0;
|
||||
while (retryCount < UGQConstants.MAX_UPDATE_RETRY_COUNT)
|
||||
{
|
||||
(ServerErrorCode errorCode, var questContentEntity) = await getQuest(userGuid, questContentId);
|
||||
if (errorCode != ServerErrorCode.Success)
|
||||
return (errorCode, null);
|
||||
|
||||
if (questContentEntity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
if (questContentEntity.State != QuestContentState.Editable &&
|
||||
questContentEntity.State != QuestContentState.Uncomplate)
|
||||
return (ServerErrorCode.UgqNotAllowEdit, null);
|
||||
|
||||
List<string> newDialogIds = saveQuestModel.Tasks
|
||||
.Where(x => string.IsNullOrEmpty(x.DialogId) == false)
|
||||
.Select(x => x.DialogId!).ToList();
|
||||
|
||||
HashSet<string> oldDialogIds = questContentEntity.Tasks
|
||||
.Where(x => string.IsNullOrEmpty(x.DialogId) == false)
|
||||
.Select(x => x.DialogId!).ToHashSet();
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><> task<73><6B> dialogId<49><64> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִٸ<D6B4> <20><><EFBFBD><EFBFBD>
|
||||
foreach (var dialogId in newDialogIds)
|
||||
{
|
||||
if (oldDialogIds.Contains(dialogId) == false)
|
||||
return (ServerErrorCode.UgqDialogIsNotInTask, null);
|
||||
}
|
||||
|
||||
int? contentVersion = questContentEntity.ContentVersion;
|
||||
var updated = await _questContentRepository.updateContent(questContentId, saveQuestModel, contentVersion);
|
||||
if (updated == null)
|
||||
{
|
||||
retryCount++;
|
||||
Log.getLogger().warn($"questContent version missmatch. retryCount: {retryCount}");
|
||||
continue;
|
||||
}
|
||||
|
||||
return (ServerErrorCode.Success, updated);
|
||||
}
|
||||
|
||||
return (ServerErrorCode.UgqExceedTransactionRetry, null);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, int)> incUploadCounter(string userGuid, string questContentId)
|
||||
{
|
||||
return await _questContentRepository.incUploadCounter(questContentId);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, QuestContentEntity?)> updateQuestImages(string questContentId, string? titleImage, string? bannerImage)
|
||||
{
|
||||
if (titleImage == null && bannerImage == null)
|
||||
return (ServerErrorCode.UgqRequireImage, null);
|
||||
|
||||
var updated = await _questContentRepository.updateImages(questContentId, titleImage, bannerImage);
|
||||
if (updated == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
return (ServerErrorCode.Success, updated);
|
||||
}
|
||||
|
||||
public async Task<List<QuestDialogEntity>> getQuestDialogs(IEnumerable<string> questDialogIds)
|
||||
{
|
||||
return await _questDialogRepository.get(questDialogIds);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, QuestDialogEntity?)> getQuestDialog(string userGuid, string questContentId, string questDialogId)
|
||||
{
|
||||
(ServerErrorCode errorCode, var questContentEntity) = await getQuest(userGuid, questContentId);
|
||||
if (errorCode != ServerErrorCode.Success)
|
||||
return (errorCode, null);
|
||||
|
||||
if (questContentEntity == null)
|
||||
return (errorCode, null);
|
||||
|
||||
var task = questContentEntity.Tasks.Where(x => x.DialogId == questDialogId).FirstOrDefault();
|
||||
if (task == null)
|
||||
return (ServerErrorCode.UgqDialogIsNotInTask, null);
|
||||
|
||||
QuestDialogEntity? entity = await _questDialogRepository.get(questDialogId);
|
||||
if (entity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
return (ServerErrorCode.Success, entity);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, QuestContentEntity?, QuestDialogEntity?)> addQuestDialog(string userGuid, string questContentId,
|
||||
int taskIndex, List<DialogSequenceEntity> sequences)
|
||||
{
|
||||
QuestDialogEntity dialogEntity = new()
|
||||
{
|
||||
Sequences = sequences,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
UpdatedAt = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
await _questDialogRepository.add(dialogEntity);
|
||||
|
||||
int retryCount = 0;
|
||||
while (retryCount < UGQConstants.MAX_UPDATE_RETRY_COUNT)
|
||||
{
|
||||
(ServerErrorCode errorCode, var questContentEntity) = await getQuest(userGuid, questContentId);
|
||||
if (errorCode != ServerErrorCode.Success)
|
||||
return (errorCode, null, null);
|
||||
|
||||
if (questContentEntity == null)
|
||||
return (errorCode, null, null);
|
||||
|
||||
List<TaskEntity> tasks = questContentEntity.Tasks;
|
||||
if (tasks.Count < taskIndex + 1)
|
||||
{
|
||||
int addCount = (taskIndex + 1) - tasks.Count;
|
||||
for (int i = 0; i < addCount; i++)
|
||||
{
|
||||
TaskEntity emptyTask = new TaskEntity();
|
||||
tasks.Add(emptyTask);
|
||||
}
|
||||
}
|
||||
tasks[taskIndex].DialogId = dialogEntity.Id;
|
||||
|
||||
int? contentVersion = questContentEntity.ContentVersion;
|
||||
var updated = await _questContentRepository.updateTasks(questContentId, tasks, contentVersion);
|
||||
if (updated == null)
|
||||
{
|
||||
retryCount++;
|
||||
Log.getLogger().warn($"questContent version missmatch. retryCount: {retryCount}");
|
||||
continue;
|
||||
}
|
||||
|
||||
return (ServerErrorCode.Success, updated, dialogEntity);
|
||||
}
|
||||
|
||||
return (ServerErrorCode.UgqExceedTransactionRetry, null, null);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, QuestDialogEntity?)> saveQuestDialog(string userGuid, string questContentId,
|
||||
string questDialogId, List<DialogSequenceEntity> sequences)
|
||||
{
|
||||
(ServerErrorCode errorCode, var questContentEntity) = await getQuest(userGuid, questContentId);
|
||||
if (errorCode != ServerErrorCode.Success)
|
||||
return (errorCode, null);
|
||||
|
||||
if (questContentEntity == null)
|
||||
return (errorCode, null);
|
||||
|
||||
var task = questContentEntity.Tasks.Where(x => x.DialogId == questDialogId).FirstOrDefault();
|
||||
if (task == null)
|
||||
return (ServerErrorCode.UgqDialogIsNotInTask, null);
|
||||
|
||||
return await _questDialogRepository.updateSequences(questDialogId, sequences);
|
||||
}
|
||||
|
||||
public async Task<(ServerErrorCode, QuestContentEntity?)> changeQuestStateForEditor(string userGuid,
|
||||
QuestContentEntity content, List<QuestDialogEntity>? dialogs,
|
||||
IEnumerable<QuestContentState> before, QuestContentState after, string adminUsername)
|
||||
{
|
||||
QuestContentState fromState = content.State;
|
||||
QuestContentState toState = after;
|
||||
|
||||
ServerErrorCode errorCode = ServerErrorCode.Success;
|
||||
QuestContentEntity? updated = null;
|
||||
switch (after)
|
||||
{
|
||||
case QuestContentState.Editable:
|
||||
updated = await _questContentRepository.updateState(content.Id,
|
||||
content.QuestId, content.Revision, before, after);
|
||||
break;
|
||||
case QuestContentState.Standby:
|
||||
{
|
||||
var gameQuestEntity = await _gameQuestDataRepository.setShutdown(content.QuestId, content.Revision);
|
||||
if (gameQuestEntity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
updated = await _questContentRepository.updateState(content.Id,
|
||||
content.QuestId, content.Revision, before, after);
|
||||
}
|
||||
break;
|
||||
case QuestContentState.Test:
|
||||
{
|
||||
if (dialogs == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
var accountEntity = await _accountService.getAccount(userGuid);
|
||||
if (accountEntity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
var beforeRevision = content.Revision;
|
||||
if (content.QuestId == 0)
|
||||
{
|
||||
content.QuestId = await _questIdSequenceRepository.getNextSequence();
|
||||
content.Revision = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
content.Revision++;
|
||||
}
|
||||
|
||||
var tasks = content.Tasks;
|
||||
var game_quest_dialog_data_entities = dialogs.Select(x => new GameQuestDialogDataEntity
|
||||
{
|
||||
Id = x.Id,
|
||||
Sequences = x.Sequences,
|
||||
}).ToList();
|
||||
(var result, var quest_metas) = _ugqMetaGenerateService.generateUgqMeta(content);
|
||||
var ugq_game_quest_data_for_client_string = _ugqMetaGenerateService.makeUgqGameQuestDataForClients(content, after, game_quest_dialog_data_entities);
|
||||
|
||||
var gameQuestEntity = await _gameQuestDataRepository.insert(content, QuestContentState.Test,
|
||||
game_quest_dialog_data_entities, quest_metas, ugq_game_quest_data_for_client_string, accountEntity.GradeType);
|
||||
if (gameQuestEntity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
updated = await _questContentRepository.updateState(content.Id,
|
||||
content.QuestId, content.Revision, before, after, accountEntity.GradeType);
|
||||
|
||||
if (updated != null&& beforeRevision != 0)
|
||||
await _gameQuestDataRepository.delete(content.QuestId, beforeRevision, QuestContentState.Test);
|
||||
}
|
||||
break;
|
||||
case QuestContentState.Live:
|
||||
{
|
||||
if (dialogs == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
bool toNextRevision = content.ToNextRevision ?? true;
|
||||
long beforeRevision = content.Revision;
|
||||
content.Revision = toNextRevision == true ? content.Revision + 1 : content.Revision;
|
||||
|
||||
var tasks = content.Tasks;
|
||||
var game_quest_dialog_data_entities = dialogs.Select(x => new GameQuestDialogDataEntity
|
||||
{
|
||||
Id = x.Id,
|
||||
Sequences = x.Sequences,
|
||||
}).ToList();
|
||||
(var result, var quest_metas) = _ugqMetaGenerateService.generateUgqMeta(content);
|
||||
var ugq_game_quest_data_for_client_string = _ugqMetaGenerateService.makeUgqGameQuestDataForClients(content, after, game_quest_dialog_data_entities);
|
||||
|
||||
var gameQuestEntity = await _gameQuestDataRepository.insert(content, QuestContentState.Live, game_quest_dialog_data_entities, quest_metas, ugq_game_quest_data_for_client_string);
|
||||
if (gameQuestEntity == null)
|
||||
return (ServerErrorCode.UgqNullEntity, null);
|
||||
|
||||
updated = await _questContentRepository.updateState(content.Id,
|
||||
content.QuestId, content.Revision, before, after);
|
||||
|
||||
if(updated != null)
|
||||
await _gameQuestDataRepository.delete(content.QuestId, beforeRevision, QuestContentState.Test);
|
||||
}
|
||||
break;
|
||||
case QuestContentState.Shutdown:
|
||||
{
|
||||
await _gameQuestDataRepository.setShutdown(content.QuestId, content.Revision);
|
||||
|
||||
updated = await _questContentRepository.updateState(content.Id,
|
||||
content.QuestId, content.Revision, before, after);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
errorCode = ServerErrorCode.UgqStateChangeError;
|
||||
break;
|
||||
}
|
||||
|
||||
if (updated == null)
|
||||
return (ServerErrorCode.UgqStateChangeError, null);
|
||||
|
||||
if(errorCode == ServerErrorCode.Success)
|
||||
{
|
||||
List<ILogInvoker> business_logs = [
|
||||
new UgqApiChangeStateBusinessLog(updated.Id, fromState.ToString(), toState.ToString(), updated.QuestId, updated.Revision, adminUsername),
|
||||
];
|
||||
var log_action = new LogActionEx(LogActionType.UgqApiChangeState);
|
||||
UgqApiBusinessLogger.collectLogs(log_action, userGuid, business_logs);
|
||||
}
|
||||
|
||||
return (errorCode, updated);
|
||||
}
|
||||
|
||||
public async Task<CreatorPointHistoryQueryResult> getCreatorPointHistories(string userGuid, int pageNumber, int pageSize, CreatorPointHistoryKind kind, DateTimeOffset startDate, DateTimeOffset endDate)
|
||||
{
|
||||
return await _creatorPointHistoryRepository.getList(userGuid, pageNumber, pageSize, kind, startDate, endDate);
|
||||
}
|
||||
|
||||
public async Task<QuestProfitStatsQueryResult> getQuestProfitStats(string userGuid, int pageNumber, int pageSize)
|
||||
{
|
||||
return await _questContentRepository.getQuestProfitStats(userGuid, pageNumber, pageSize);
|
||||
}
|
||||
|
||||
public async Task gameQuestDataFakeUpdate(string userGuid, string questContentId)
|
||||
{
|
||||
(ServerErrorCode errorCode, var questContentEntity) = await getQuest(userGuid, questContentId);
|
||||
if (errorCode != ServerErrorCode.Success)
|
||||
return;
|
||||
|
||||
if (questContentEntity == null)
|
||||
return;
|
||||
|
||||
var questDialogIds = questContentEntity.Tasks
|
||||
.Where(x => string.IsNullOrEmpty(x.DialogId) == false)
|
||||
.Select(x => x.DialogId!)
|
||||
.ToList();
|
||||
var questDialogs = await getQuestDialogs(questDialogIds);
|
||||
|
||||
var tasks = questContentEntity.Tasks;
|
||||
var game_quest_dialog_data_entities = questDialogs.Select(x => new GameQuestDialogDataEntity
|
||||
{
|
||||
Id = x.Id,
|
||||
Sequences = x.Sequences,
|
||||
}).ToList();
|
||||
(var result, var quest_metas) = _ugqMetaGenerateService.generateUgqMeta(questContentEntity);
|
||||
var ugq_game_quest_data_for_client = _ugqMetaGenerateService.makeUgqGameQuestDataForClients(questContentEntity, questContentEntity.State, game_quest_dialog_data_entities);
|
||||
|
||||
var gameQuestEntity = await _gameQuestDataRepository.insert(questContentEntity, QuestContentState.Test, game_quest_dialog_data_entities, quest_metas, ugq_game_quest_data_for_client);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
317
UGQDataAccess/Service/UgqMetaGenerateService.cs
Normal file
317
UGQDataAccess/Service/UgqMetaGenerateService.cs
Normal file
@@ -0,0 +1,317 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
using MongoDB.Bson.IO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
using UGQDatabase.Models;
|
||||
using JsonConvert = MongoDB.Bson.IO.JsonConvert;
|
||||
|
||||
|
||||
namespace UGQDataAccess.Service;
|
||||
|
||||
public class UgqMetaGenerateService
|
||||
{
|
||||
public (Result, List<QuestMetaInfo>) generateUgqMeta(QuestContentEntity content)
|
||||
{
|
||||
var result = new Result();
|
||||
IUgqMetaGenerator? generator = null;
|
||||
List<QuestMetaInfo> script_datas = new();
|
||||
|
||||
for (int i = 0; i < content.Tasks.Count; i++)
|
||||
{
|
||||
QuestMetaInfo meta = new();
|
||||
//첫줄 스크립트 생성
|
||||
var idx = script_datas.Count() + 1;
|
||||
meta.Index = idx;
|
||||
meta.ComposedQuestId = QuestHelper.convertQuestIdAndRevisionToUgqQuestId((UInt32)content.QuestId, (UInt32)content.Revision);
|
||||
meta.EventTarget = EQuestEventTargetType.TASK.ToString();
|
||||
meta.EventName = EQuestEventNameType.ACTIVED.ToString();
|
||||
meta.EventCondition1 = (i + 1).ToString();
|
||||
meta.EventCondition2 = string.Empty;
|
||||
meta.EventCondition3 = string.Empty;
|
||||
meta.FunctionTarget = EQuestFunctionTargetType.TASK.ToString();
|
||||
meta.FunctionName = EQuestFunctionNameType.TITLE_UPDATE.ToString();
|
||||
|
||||
meta.FunctionCondition1 = (i + 1).ToString();
|
||||
meta.FunctionCondition2 = string.Empty;
|
||||
meta.FunctionCondition3 = string.Empty;
|
||||
script_datas.Add(meta);
|
||||
|
||||
|
||||
//태스크 시작에 대한 generator 생성
|
||||
var action_id = content.Tasks[i].ActionId;
|
||||
MetaData.Instance.UGQInputTaskMetaDataById.TryGetValue(action_id, out var task_meta);
|
||||
if (task_meta == null)
|
||||
{
|
||||
result.setFail(ServerErrorCode.MetaInfoException, "");
|
||||
return (result, []);
|
||||
}
|
||||
|
||||
var event_target = task_meta.EventTarget;
|
||||
var event_name = task_meta.Event;
|
||||
|
||||
(result, generator) = getUgqMetaGenerator(event_target, event_name, content, i);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, script_datas);
|
||||
}
|
||||
|
||||
if(generator == null)
|
||||
{
|
||||
result.setFail(ServerErrorCode.MetaInfoException, "");
|
||||
return (result, []);
|
||||
}
|
||||
|
||||
generator.generateMetas(ref script_datas);
|
||||
}
|
||||
//Log.getLogger().info($"generateUgqMeta script_datas : {JsonConvert.SerializeObject(script_datas)}");
|
||||
return (result, script_datas);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private (Result, IUgqMetaGenerator?) getUgqMetaGenerator(string eventTargetType, string eventNameType, QuestContentEntity questContentEntity, int currentIdx)
|
||||
{
|
||||
var result = new Result();
|
||||
if (eventTargetType == EQuestEventTargetType.DIALOGUE.ToString() && eventNameType == EQuestEventNameType.ENDED.ToString())
|
||||
{
|
||||
return (result, new UgqMetaGeneratorDialogueEnded(questContentEntity, currentIdx));
|
||||
}
|
||||
|
||||
if (eventTargetType == EQuestEventTargetType.ITEM.ToString() && eventNameType == EQuestEventNameType.BOUGHT.ToString())
|
||||
{
|
||||
return (result, new UgqMetaGeneratorItemBought(questContentEntity, currentIdx));
|
||||
}
|
||||
|
||||
if (eventTargetType == EQuestEventTargetType.COSTUME.ToString() && eventNameType == EQuestEventNameType.EQUIPED.ToString())
|
||||
{
|
||||
return (result, new UgqMetaGeneratorCostumeEquiped(questContentEntity, currentIdx));
|
||||
}
|
||||
|
||||
if (eventTargetType == EQuestEventTargetType.ITEM.ToString() && eventNameType == EQuestEventNameType.SOLD.ToString())
|
||||
{
|
||||
return (result, new UgqMetaGeneratorItemSold(questContentEntity, currentIdx));
|
||||
}
|
||||
|
||||
if (eventTargetType == EQuestEventTargetType.TOOL.ToString() && eventNameType == EQuestEventNameType.ACTIVED.ToString())
|
||||
{
|
||||
return (result, new UgqMetaGeneratorToolActived(questContentEntity, currentIdx));
|
||||
}
|
||||
|
||||
var err_msg = $"implemented IUgqGenerator not exist eventTargetType : {eventTargetType}, eventNameType : {eventNameType}";
|
||||
result.setFail(ServerErrorCode.UgqMetaGeneratorNotExist, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
public string makeUgqGameQuestDataForClients(QuestContentEntity content, QuestContentState after, List<GameQuestDialogDataEntity> dialogues, bool isRevisionUpdated = false)
|
||||
{
|
||||
UgqGameQuestDataForClient data = new();
|
||||
|
||||
UInt32 revision = (UInt32)content.Revision;
|
||||
if (isRevisionUpdated)
|
||||
{
|
||||
revision += 1;
|
||||
}
|
||||
|
||||
var composed_quest_id = QuestHelper.convertQuestIdAndRevisionToUgqQuestId((UInt32)content.QuestId, revision);
|
||||
data.ComposedQuestId = composed_quest_id;
|
||||
data.Author = content.Author;
|
||||
data.AuthorGuid = content.UserGuid;
|
||||
data.BeaconId = content.BeaconId;
|
||||
data.UgcBeaconGuid = content.UgcBeaconGuid ?? "";
|
||||
data.UgcBeaconNickname = content.UgcBeaconNickname ?? "";
|
||||
data.Title = new();
|
||||
data.Title.Kr = content.Title.Kr;
|
||||
data.Title.En = content.Title.En;
|
||||
data.Title.Jp = content.Title.Jp;
|
||||
data.Task.AddRange(makeUgqGameTaskForClient(content));
|
||||
data.Dialogues.AddRange(makeUgqGameDialogueForClient(dialogues));
|
||||
data.UgqStateType = QuestHelper.convertQuestContentStateToUgqStateType(after);
|
||||
|
||||
return Newtonsoft.Json.JsonConvert.SerializeObject(data);
|
||||
|
||||
//return data;
|
||||
}
|
||||
|
||||
private List<UgqGameQuestDialogue> makeUgqGameDialogueForClient(List<GameQuestDialogDataEntity> dialogues)
|
||||
{
|
||||
List<UgqGameQuestDialogue> datas = new();
|
||||
|
||||
foreach (var dialogue in dialogues)
|
||||
{
|
||||
UgqGameQuestDialogue data = new();
|
||||
data.DialogueId = dialogue.Id;
|
||||
data.Sequences.AddRange(makeUgqGameDialogueSequences(dialogue));
|
||||
data.Returns.AddRange(makeUgqGameDialogueReturns(dialogue));
|
||||
datas.Add(data);
|
||||
}
|
||||
return datas;
|
||||
}
|
||||
|
||||
private List<UgqDialogueReturns> makeUgqGameDialogueReturns(GameQuestDialogDataEntity dialogue)
|
||||
{
|
||||
List<UgqDialogueReturns> datas = new();
|
||||
|
||||
foreach (var seq in dialogue.Sequences)
|
||||
{
|
||||
|
||||
foreach(var action in seq.Actions)
|
||||
{
|
||||
if (action.NextSequence == -1)
|
||||
{
|
||||
UgqDialogueReturns data = new();
|
||||
data.ReturnIdx = 1;
|
||||
|
||||
/*
|
||||
//송팀장님과 나눈 내용 정리 (24-08-15)
|
||||
원레 시스템 퀘스트는 Returns값을 만들기 위해 ActionIndex를 -1을 사용하지 않고 현재 사용중인 sequenceId에 +1을 해서 사용하고(미사용sequenceId를 할당하는 개념)
|
||||
미사용sequenceId 로 returns를 만들어사 사용했음
|
||||
그러나 현재 webtool에서는 명시적으로 대화가 종료되는 것을 -1로 명시한 상태에서 action.NextSequence 가 -1일 경우 ActionIndex를 current SequenceId 설정 했음
|
||||
그래서 아래와 같이 코드를 추가했다.
|
||||
추후에 내용을 바꾸려고 할경우 해당 경우 클라와 협의해서 변경해야된다. 임의로 바꾸면 안된다.
|
||||
*/
|
||||
data.ActionIndex = seq.SequenceId;
|
||||
datas.Add(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return datas;
|
||||
}
|
||||
|
||||
private List<UgqDialogueSequences> makeUgqGameDialogueSequences(GameQuestDialogDataEntity dialogue)
|
||||
{
|
||||
List<UgqDialogueSequences> datas = new();
|
||||
|
||||
foreach (var seq in dialogue.Sequences)
|
||||
{
|
||||
UgqDialogueSequences data = new();
|
||||
data.SequenceId = seq.SequenceId;
|
||||
data.Actions.AddRange(makeUgqDialogueSequenceActions(seq.Actions));
|
||||
datas.Add(data);
|
||||
}
|
||||
|
||||
return datas;
|
||||
}
|
||||
|
||||
private List<UgqDialogSequenceAction> makeUgqDialogueSequenceActions(List<DialogSequenceActionEntity> actions)
|
||||
{
|
||||
List<UgqDialogSequenceAction> datas = new();
|
||||
|
||||
foreach (var act in actions)
|
||||
{
|
||||
UgqDialogSequenceAction data = new();
|
||||
data.Talker = ConvertDialogueTalkerToUgqDialogueTalker(act.Talker);
|
||||
data.Contition = makeConditionString(act); //act.Type 으로 가공해야된다.;
|
||||
data.ActionType = 4;
|
||||
data.SubType = 0;
|
||||
data.ActionNumber = act.ConditionValue;
|
||||
data.ActionIndex = act.NextSequence;
|
||||
data.Talk = new();
|
||||
data.Talk.Kr = act.Talk.Kr;
|
||||
data.Talk.En = act.Talk.En;
|
||||
data.Talk.Jp = act.Talk.Jp;
|
||||
if (data.Talker == UgqDialogueTalker.Player) data.IsDialogue = 0;
|
||||
else data.IsDialogue = 1;
|
||||
data.NpcAction = act.NpcAction;
|
||||
|
||||
datas.Add(data);
|
||||
}
|
||||
return datas;
|
||||
}
|
||||
|
||||
private string makeConditionString(DialogSequenceActionEntity action)
|
||||
{
|
||||
MetaData.Instance.UGQInputDialogMetaDataListbyId.TryGetValue(action.Type, out UGQInputDialogMetaData? input_meta);
|
||||
if(input_meta == null)
|
||||
return "";
|
||||
|
||||
if (ServerCommon.Constant.UGQ_INPUT_DATA_TYPE_NAME_TEXT.Equals(input_meta.TypeName))
|
||||
{
|
||||
return "text";
|
||||
}
|
||||
|
||||
if (ServerCommon.Constant.UGQ_INPUT_DATA_TYPE_NAME_ATTRIBUTE.Equals(input_meta.TypeName) || input_meta.ConditionSource == EUGQValueSource.UGQ_ATTRIBUTE_DEFINITION)
|
||||
{
|
||||
//id로 가져오는 Meta 가 없어서 우선 loop 처리
|
||||
foreach (var definition_meta in MetaData.Instance._AttributeDefinitionMetaTable)
|
||||
{
|
||||
if (definition_meta.Value.ID == action.Condition)
|
||||
{
|
||||
return definition_meta.Key;
|
||||
}
|
||||
}
|
||||
|
||||
Log.getLogger().warn($"makeConditionString error input_meta {input_meta.ConditionSource}");
|
||||
return "";
|
||||
}
|
||||
|
||||
if (ServerCommon.Constant.UGQ_INPUT_DATA_TYPE_NAME_ITEM.Equals(input_meta.TypeName))
|
||||
{
|
||||
return "item";
|
||||
}
|
||||
|
||||
if (ServerCommon.Constant.UGQ_INPUT_DATA_TYPE_NAME_EMOTE.Equals(input_meta.TypeName))
|
||||
{
|
||||
return "emote";
|
||||
}
|
||||
|
||||
Log.getLogger().warn($"makeConditionString error input_meta {input_meta.ConditionSource}");
|
||||
return "";
|
||||
}
|
||||
|
||||
private UgqDialogueTalker ConvertDialogueTalkerToUgqDialogueTalker(DialogTalker talker)
|
||||
{
|
||||
return talker switch
|
||||
{
|
||||
DialogTalker.Player => UgqDialogueTalker.Player,
|
||||
DialogTalker.Npc => UgqDialogueTalker.Npc,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
}
|
||||
|
||||
private List<UgqGameTaskDataForClient> makeUgqGameTaskForClient(QuestContentEntity content)
|
||||
{
|
||||
List<UgqGameTaskDataForClient> tasks = new();
|
||||
|
||||
int i = 1;
|
||||
foreach (var t in content.Tasks)
|
||||
{
|
||||
|
||||
UgqGameTaskDataForClient data = new();
|
||||
data.TaskNum = i;
|
||||
data.GoalText = new();
|
||||
data.GoalText.Kr = t.GoalText.Kr;
|
||||
data.GoalText.En = t.GoalText.En;
|
||||
data.GoalText.Jp = t.GoalText.Jp;
|
||||
data.DialogueId = t.DialogId ?? "";
|
||||
data.UgcBeaconGuid = t.UgcActionValueGuid ?? "";
|
||||
data.UgcBeaconNickname = t.UgcActionValueName ?? "";
|
||||
data.ActionId = t.ActionId;
|
||||
data.ActionValue = t.ActionValue;
|
||||
data.IsShowNpcLocation = t.IsShowNpcLocation == true ? BoolType.True : BoolType.False;
|
||||
tasks.Add(data);
|
||||
i++;
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user