using MetaAssets; using ServerBase; using ServerCommon; using ServerCore; namespace BrokerApiCore; public class PlanetItemExchangeService { readonly PlanetUserEntity m_planet_user; private readonly IOrderStrategyProvider m_strategies; private readonly BrokerMetaTableRef m_meta_table_ref; private readonly PlanetItemExchangeOrderRepo m_planet_item_exchange_repo; private readonly DynamoDbClient m_dynamo_db_client; public PlanetItemExchangeService( IServerLogic serverLogic, PlanetUserEntity planetUser, IOrderStrategyProvider strategies, BrokerMetaTableRef metaTableRef, PlanetItemExchangeOrderRepo planetItemExchangeOrderRepo) { m_planet_user = planetUser; m_strategies = strategies; m_meta_table_ref = metaTableRef; m_planet_user.onInit().Wait(); m_planet_item_exchange_repo = planetItemExchangeOrderRepo; m_dynamo_db_client = serverLogic.getDynamoDbClient(); } public PlanetUserEntity PlanetUser => m_planet_user; //=================================================================================================== // 로그아웃 여부만 체크 //=================================================================================================== public bool isUserLoggedIn() { var user_attribute = m_planet_user.getEntityAttributeNotNull(); return user_attribute.GameLoginDateTime > user_attribute.GameLogoutDateTime; } //=================================================================================================== // 유저 인증 및 account, user, nickname 정보 읽음 //=================================================================================================== public async Task validateAndGetUser( string accountId, string userGuid, string planetId ) { m_planet_user.setPlanetId(planetId); var action = m_planet_user.getEntityActionNotNull(); if (!string.IsNullOrEmpty(accountId)) { var result = await action.findAndSetAllAttributeByAccountId(accountId); Guard.Against.resultFail(result); } else { var result = await action.findAndSetAllAttributeByUserGuid(userGuid); Guard.Against.resultFail(result); } } //============================================================================================= // 현재 재화 요청 //============================================================================================= public async Task getCurrencyAmount(string currencyTypeString) { var currency_type = currencyTypeString.convertEnumTypeAndValueStringToEnum(CurrencyType.None); Guard.Against.isFalse(currency_type != CurrencyType.None, ServerErrorCode.InvalidRequest, () => "Invalid currency type"); CurrencyControlHelper.setDbConnector(m_dynamo_db_client); var user_guid = m_planet_user.getEntityAttributeNotNull().UserGuid; var (result, current_sapphire_amount_double) = await CurrencyControlHelper.getMoneyByUserGuid(user_guid, currency_type); Guard.Against.resultFail(result); return current_sapphire_amount_double; } //============================================================================================= // 교환 주문 조회 //============================================================================================= public async Task<(IEnumerable, int)> findOrderList( string planetId, string metaId, string seasonId, string userGuid, ExchangeOrderStatus? orderStatus = null, int pageIndex = 1, int pageSize = 20, string sortOrder = "asc", CancellationToken cancellationToken = default) { var (result, orders, total_count) = await m_planet_item_exchange_repo.findList( planetId, metaId, seasonId, userGuid, orderStatus, pageIndex, pageSize, sortOrder, cancellationToken); Guard.Against.resultFail(result, ServerErrorCode.RdbError, () => result.ResultString); Guard.Against.isNull(orders, ServerErrorCode.RdbError, () => result.ResultString); return (orders, total_count); } //============================================================================================= // 교환 주문 생성 //============================================================================================= public async Task<(Result, PlanetItemExchangeOrder)> createOrder( string planetId, string seasonId, string planetServerType, string exchangeMetaId, int exchangeMetaAmount, CancellationToken cancellationToken = default) { // 메타 테이블에서 교환 정보 가져오기 m_meta_table_ref.MetaTable.PlanetItemExchangePolicyMetaTable.PlanetItemExchangePolicyDataListbyID .TryGetValue(exchangeMetaId, out var exchange_policy); Guard.Against.isNull(exchange_policy, ServerErrorCode.MetaIdInvalid, () => $"Invalid ExchangeMetaId:{exchangeMetaId}"); // 주문 내역 생성 var order = makeExchangeOrderInfo(planetId, seasonId, exchange_policy, exchangeMetaAmount); // 아이템 유형에 따라 전략 선택 var caliverse_item_type = exchange_policy.CaliverseItemType.convertEnumTypeAndValueStringToEnum(CaliverseItemType.None); var strategy = m_strategies.getCreationStrategy(caliverse_item_type); Guard.Against.isNull(strategy, ServerErrorCode.InternalServerError, () => "createOrder Invalid Item Type Strategy"); var (result, order_info) = await strategy.createOrder(order, planetServerType, exchange_policy, cancellationToken); Guard.Against.resultFail(result, ServerErrorCode.InternalServerError, () => result.ResultString); // 비즈니스 로그 작성 BusinessLogger.collectLog(m_planet_user, new PlanetItemExchangeBusinessLog(new LogActionEx(LogActionType.BrokerApiUserExchangeOrderCreated), Helpers.createFromExchangeOrderLog(order))); return (result, order_info); } //============================================================================================= // 교환 주문 완료 // 주문 상태가 Pending 이어야 한다. //============================================================================================= public async Task completeOrder( string orderId, CancellationToken cancellationToken = default) { // 생성 주문 조회 var (result, order_created) = await m_planet_item_exchange_repo.findOne(orderId, ExchangeOrderStatus.Pending, cancellationToken); Guard.Against.resultFail(result); Guard.Against.isNull(order_created, ServerErrorCode.ExchangeOrderIdNotFound, () => "Invalid Order Id"); // 주문 타입에 맞는 전략 선택 후 완료 처리 var strategy = m_strategies.getCompletionStrategy(order_created.CaliverseItemType); Guard.Against.isNull(strategy, ServerErrorCode.InternalServerError, () => "completeOrder Invalid Order Type"); var order_completed = await strategy.completeOrder(m_planet_user, order_created, cancellationToken); // 비즈니스 로그 작성 BusinessLogger.collectLog(m_planet_user, new PlanetItemExchangeBusinessLog(new LogActionEx(LogActionType.BrokerApiUserExchangeOrderCompleted), Helpers.createFromExchangeOrderLog(order_completed))); return order_completed; } private PlanetItemExchangeOrder makeExchangeOrderInfo( string planetId, string seasonId, PlanetItemExchangePolicyMetaData exchangePolicy, int exchangeMetaAmount) { var now = DateTime.UtcNow; return new PlanetItemExchangeOrder { OrderId = $"{now:yyMMdd}{Guid.NewGuid():N}", OrderStatus = ExchangeOrderStatus.Pending, SeasonId = seasonId, PlanetId = planetId, AccountId = m_planet_user.AccountId, UserGuid = m_planet_user.UserGuid, Nickname = m_planet_user.Nickname, CaliverseItemType = exchangePolicy.CaliverseItemType.convertEnumTypeAndValueStringToEnum(CaliverseItemType.None), CaliverseItemId = exchangePolicy.CaliverseItemId, CaliverseItemDeltaAmount = exchangeMetaAmount * exchangePolicy.CaliverseItemAmount, PlanetItemType = exchangePolicy.PlanetItemType.convertEnumTypeAndValueStringToEnum(PlanetItemType.None), PlanetItemId = exchangePolicy.PlanetItemId, PlanetItemDeltaAmount = exchangeMetaAmount * exchangePolicy.PlanetItemAmount, CreatedAt = now, CompletedAt = null, ExchangeMetaId = exchangePolicy.ID, ExchangeMetaAmount = exchangeMetaAmount, }; } }