using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using ServerCore; using ServerBase; using ServerCommon; using ServerCommon.BusinessLogDomain; using MetaAssets; namespace GameServer; public class CaliumStorageAction : EntityActionBase { private readonly CaliumStorageCacheRequest m_cache_request; private int m_repeat_count { get; set; } public CaliumStorageAction(CaliumStorageEntity owner) : base(owner) { var server_logic = GameServerApp.getServerLogic(); var redis = server_logic.getRedisConnector(); m_cache_request = new CaliumStorageCacheRequest(redis); } public override async Task onInit() { // 1. fill up 시간 체크 var pivot_date = CaliumStorageHelper.CurrentPivotTimeDate(); var task_date = pivot_date; // 2. repeat count m_repeat_count = 24 / MetaHelper.GameConfigMeta.CaliumConverterCycleTime; // 3. DailyTimeEventManager 등록 string task_name; for (var repeat = 0; repeat < m_repeat_count; repeat++) { var is_first_run = repeat != 0; task_name = "CaliumConverterManage"; task_name = $"{task_name}_{repeat}"; DailyTimeEventManager.Instance.tryAddTask(task_name, task_date, onFillUpDailyCalium, is_first_run); task_date = task_date.AddHours(MetaHelper.GameConfigMeta.CaliumConverterCycleTime); } // 4. 컨버터 동기화 체크 Manager 등록 task_name = "CaliumConverterSyncManage"; DailyTimeEventManager.Instance.tryAddTask(task_name, task_date.AddHours(1), onSyncConverterCalium); return await Task.FromResult(new Result()); } public override void onClear() {} public async Task initStorageAttribute() { var owner = getOwner() as CaliumStorageEntity; NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!"); // 0. Web3 Connection 체크 var web3_action = getOwner().getEntityAction(); NullReferenceCheckHelper.throwIfNull(web3_action, () => $"web3_action is null !!! - {owner.toBasicString()}"); var result = await web3_action.checkWeb3Connection(); if (result.isFail()) return result; // 1. 데이터 로딩 result = await loadStorageAttribute(); if (result.isSuccess()) return result; // 2. Storage Doc 을 찾지 못하는 에러가 아닌 경우 에러 처리 if (result.ErrorCode != ServerErrorCode.DynamoDbQueryNoMatchAttribute) return result; // 3. 신규 데이터 저장 var dynamodb_client = GameServerApp.getServerLogic().getDynamoDbClient(); var doc = new CaliumStorageDoc(); result = await dynamodb_client.simpleInsertDocumentWithDocType(doc); return result; } public double getTotalCalium(CaliumStorageType storageType) { var attribute = getOwner().getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(attribute, () => $"calium_storage_attribute is null !!! - {getOwner().toBasicString()}"); return storageType switch { CaliumStorageType.Converter => attribute.ConverterTotalCalium, CaliumStorageType.Operator => attribute.OperatorTotalCalium, _ => -1 }; } public async Task getCaliumStorageInfo() { await checkNewCaliumStoragePivotTime(); var attribute = getOwner().getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(attribute, () => $"calium_storage_attribute is null !!! - {getOwner().toBasicString()}"); return attribute; } public async Task getCaliumConverterEfficiency() { await checkNewCaliumStoragePivotTime(); var attribute = getOwner().getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(attribute, () => $"calium_storage_attribute is null !!! - {getOwner().toBasicString()}"); return attribute.DailyConvertRate; } public async Task loadStorageAttribute() { var dynamodb_client = GameServerApp.getServerLogic().getDynamoDbClient(); var owner = getOwner() as CaliumStorageEntity; NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!"); var batch = new QueryBatchEx(owner, LogActionType.ConvertCalium, dynamodb_client); batch.addQuery(new DBQCaliumStorageLoad()); var result = await QueryHelper.sendQueryAndBusinessLog(batch); return result; } public void sendChangeStorageInfo() { var server_logic = GameServerApp.getServerLogic(); var rabbit_mq = server_logic.getRabbitMqConnector() as RabbitMQ4Game;; NullReferenceCheckHelper.throwIfNull(rabbit_mq, () => $"rabbit_mq is null !!! - {getOwner().toBasicString()}"); var server_message = new ServerMessage(); server_message.NtfChangeCaliumStorageInfo = new(); rabbit_mq.sendMessageToExchangeAllGame(server_message); } public async Task enableCaliumStorage() { await checkNewCaliumStoragePivotTime(); var result = new Result(); var storage_attribute = getOwner().getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(storage_attribute, () => $"storage_attribute is null !!! - {getOwner().toBasicString()}"); if (storage_attribute.DailyPivotDate < CaliumStorageHelper.CurrentPivotTimeDate()) { var err_msg = $"rollup date is old data !!! : current[{storage_attribute.DailyPivotDate}] / to[{CaliumStorageHelper.CurrentPivotTimeDate()}]"; result.setFail(ServerErrorCode.FailToGetEchoSystemRollUp, err_msg); Log.getLogger().error(result.toBasicString()); } return result; } public async Task checkRetryCaliumEchoSystem() { return await m_cache_request.checkRetryKey(); } private Result initializeStorage(CaliumStorageAttrib attrib, RollUpData? rollUp) { var result = new Result(); if (null == rollUp) { var err_msg = "fail to initialize calium storage : roll up data is null!!"; result.setFail(ServerErrorCode.GetFailEchoSystemResponse, err_msg); Log.getLogger().error(result.toBasicString()); return result; } attrib.DailyEpoch = rollUp.m_epoch - 1; attrib.DailyPivotDate = CaliumStorageHelper.CurrentPivotTimeDate().AddDays(-1); var calium = CaliumStorageHelper.SubTractDoubleByLong(rollUp.m_stack_converter_volume, rollUp.m_convertor_volume); attrib.ConverterStorage.ConverterCumulativeCalium = calium; attrib.ConverterStorage.DailyConvertRate = rollUp.m_daily_converter_rate; attrib.ConverterStorage.TotalCalium = calium; attrib.ConverterStorage.LastFillUpDate = CaliumStorageHelper.CurrentPivotTimeDate().AddHours(-1 * MetaHelper.GameConfigMeta.CaliumConverterCycleTime); attrib.ConverterStorage.DailyFillUpStandardCalium = rollUp.m_convertor_volume; attrib.ExchangerStorage.DailyInflationRate = rollUp.m_daily_inflation_rate; return result; } private async Task changeCaliumConverterTotal(double delta) { var result = new Result(); if (delta == 0) return result; var owner = getOwner() as CaliumStorageEntity; NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!"); // 1. delta 값 변경 var item_request_batch = new QueryBatchEx(owner, LogActionType.ConvertCalium, GameServerApp.getServerLogic().getDynamoDbClient(), true); item_request_batch.addQuery(new DBQStorageCaliumUpdate(CaliumStorageType.Converter, delta, true)); result = await QueryHelper.sendQueryAndBusinessLog(item_request_batch); if (result.isFail()) return result; // 2. calium storage attribute 갱신 _ = loadStorageAttribute(); return result; } private async Task getCaliumStorageDoc() { var server_logic = GameServerApp.getServerLogic(); var dynamodb_client = server_logic.getDynamoDbClient(); var query_config = dynamodb_client.makeQueryConfigForReadByPKOnly(CaliumStorageDoc.pk); var (result, found_doc) = await dynamodb_client.simpleQueryDocTypeWithQueryOperationConfig(query_config); if (result.isFail() || null == found_doc) return null; return found_doc; } private async Task checkNewCaliumStoragePivotTime() { var owner = getOwner() as CaliumStorageEntity; NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!"); var attribute = getOwner().getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(attribute, () => $"calium_storage_attribute is null !!! - {owner.toBasicString()}"); // 1. calium storage daily data 갱신 날짜 체크 if (attribute.DailyPivotDate >= CaliumStorageHelper.CurrentPivotTimeDate()) return; // 2. calium storage 데이터 수정 _ = await loadStorageAttribute(); } public async Task onFillUpDailyCalium() { NullReferenceCheckHelper.throwIfNull(m_cache_request, () => $"m_cache_request is null !!! - {getOwner().toBasicString()}"); // 1. 시작 조건 체크 var is_start = await m_cache_request.startCaliumConverterManage(); if (!is_start) return; // 2. doc 데이터 로딩 var found_doc = await getCaliumStorageDoc(); NullReferenceCheckHelper.throwIfNull(found_doc, () => $"calium_storage_doc is null !!! - {getOwner().toBasicString()}"); var calium_storage_attrib = found_doc.getAttrib(); NullReferenceCheckHelper.throwIfNull(calium_storage_attrib, () => $"calium_storage_attrib is null !!! - {getOwner().toBasicString()}"); // 3. Daily Calium Converter 정보 갱신 처리 var update = await updateDailyCaliumConverter(found_doc); if (false == update.is_success) return; // 4. 미 충전 횟수 체크 var check_fill_up = checkMissFillUpDailyCalium(calium_storage_attrib); // 5. daily calium 충전 var fill_up_calium = await fillUpDailyCalium(calium_storage_attrib, check_fill_up.missFillUpCount, check_fill_up.lastFillUpDate); if (fill_up_calium <= 0) return; // 6. business log 기록 var calium_log_data = new CaliumConverterLogData(); calium_log_data.CurrentDailyCalium = 0; calium_log_data.CurrentTotalCalium = getTotalCalium(CaliumStorageType.Converter); calium_log_data.DeltaDailyCalium = 0; calium_log_data.DeltaTotalCalium = CaliumStorageHelper.AddDoubleByLong(fill_up_calium, update.mis_pivot_calium); calium_log_data.AmountDeltaType = AmountDeltaType.Acquire; var calium_business_log = new CaliumBusinessLog(new LogActionEx(LogActionType.FillupCalium), calium_log_data); var calium_converter = GameServerApp.getServerLogic().findGlobalEntity(); NullReferenceCheckHelper.throwIfNull(calium_converter, () => $"calium_converter is null !!!"); BusinessLogger.collectLog(calium_converter, calium_business_log); } private async Task onSyncConverterCalium() { // 실행 기본 딜레이 처리 await Task.Delay(10_000); var owner = getOwner() as CaliumStorageEntity; NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!"); // 1. 시작 조건 체크 var is_start = await m_cache_request.startCaliumConverterManage(true); if (!is_start) return; // 2. doc 데이터 로딩 var found_doc = await getCaliumStorageDoc(); NullReferenceCheckHelper.throwIfNull(found_doc, () => $"calium_storage_doc is null !!! - {getOwner().toBasicString()}"); var calium_storage_attrib = found_doc.getAttrib(); NullReferenceCheckHelper.throwIfNull(calium_storage_attrib, () => $"calium_storage_attrib is null !!! - {getOwner().toBasicString()}"); // 3. sync 시작 체크 var is_check = checkSyncEchoSystem(calium_storage_attrib); if (is_check) return; // 4. echoSystem 조회 var web3_action = getOwner().getEntityAction(); NullReferenceCheckHelper.throwIfNull(web3_action, () => $"web3_action is null !!! - {getOwner().toBasicString()}"); var (result, msg) = await web3_action.getConverterSyncDataAsync(); if (result.isFail()) { var log = new CaliumEchoSystemFailLogData(); log.FailCode = msg?.m_code ?? string.Empty; log.FailMessages = msg?.m_messages ?? new(); CaliumStorageHelper.writeFailEchoSystemLog(owner, log); Log.getLogger().error($"fail to sync converter from echo system !!! : code[{log.FailCode}] message[{log.FailMessages}]"); return; } NullReferenceCheckHelper.throwIfNull(msg, () => $"web3 response is null !!! - {getOwner().toBasicString()}"); // 5. 동기화 체크 : 적용 회차 if (calium_storage_attrib.DailyEpoch != msg.m_sync?.m_epoch) { var log = new CaliumEchoSystemFailLogData(); log.FailCode = "caliverse_error"; log.FailMessages = new List { $"failed to match epoch!! - current[{calium_storage_attrib.DailyEpoch}] / echoSystem[{msg.m_sync?.m_epoch}]" }; CaliumStorageHelper.writeFailEchoSystemLog(owner, log); Log.getLogger().error($"fail to sync converter from echo system !!! : code[{log.FailCode}] message[{log.FailMessages}]"); return; } // 6. 동기화 체크 : 총 누적 량 if (false == CaliumStorageHelper.compareDoubleByLong(calium_storage_attrib.ConverterStorage.ConverterCumulativeCalium, msg.m_sync.m_stack_calium)) { var log = new CaliumEchoSystemFailLogData(); log.FailCode = "caliverse_error"; log.FailMessages = new List { $"failed to match converter calium!! - current[{calium_storage_attrib.ConverterStorage.ConverterCumulativeCalium}] / echoSystem[{msg.m_sync.m_stack_calium}]" }; CaliumStorageHelper.writeFailEchoSystemLog(owner, log); Log.getLogger().error($"fail to sync converter from echo system !!! : code[{log.FailCode}] message[{log.FailMessages}]"); return; } // 7. Sync Date 수정 var item_request_batch = new QueryBatchEx(owner, LogActionType.CaliumSyncEchoSystem, GameServerApp.getServerLogic().getDynamoDbClient(), true); item_request_batch.addQuery(new DBQStorageCaliumSyncDateUpdate(DateTimeHelper.Current)); _ = await QueryHelper.sendQueryAndBusinessLog(item_request_batch); var success_log = $"success to sync converter from echo system !!! : epoch[{calium_storage_attrib.DailyEpoch}] converter_cumulative_calium[{calium_storage_attrib.ConverterStorage.ConverterCumulativeCalium}]"; Log.getLogger().info(success_log); } private bool checkSyncEchoSystem(CaliumStorageAttrib caliumStorageAttrib) { var current_pivot_date = CaliumStorageHelper.CurrentPivotTimeDate(); if (caliumStorageAttrib.DailyRollUpCheckDate < current_pivot_date.AddHours(1)) return false; return true; } private async Task<(bool is_success, double mis_pivot_calium)> updateDailyCaliumConverter(CaliumStorageDoc originDoc) { var pivot_time = CaliumStorageHelper.CurrentPivotTimeDate(); var calium_storage_attrib = originDoc.getAttrib(); NullReferenceCheckHelper.throwIfNull(calium_storage_attrib, () => $"calium_storage_attrib is null !!! - {getOwner().toBasicString()}"); // 1. Daily Calium Converter 갱신 조건 체크 if (calium_storage_attrib.DailyPivotDate >= pivot_time) return (true, 0); // 2. Daily Calium Roll Up 체크 var (result, mis_pivot_calium) = await checkEchoSystemDailyCaliumAsync(calium_storage_attrib, pivot_time); if (result.isFail()) { // retry 처리 if (result.ErrorCode != ServerErrorCode.GetFailEchoSystemResponse) { await m_cache_request.setRetryKey(); } return (false, mis_pivot_calium); } // 2. doc 갱신 var server_logic = GameServerApp.getServerLogic(); var dynamodb_client = server_logic.getDynamoDbClient(); result = await dynamodb_client.simpleUpdateDocumentWithDocType(originDoc); if (result.isFail()) { var err_msg = $"failed to update daily calium converter info !!! - doc:{originDoc.toBasicString()} / {getOwner().toBasicString()}"; Log.getLogger().error(err_msg); await m_cache_request.setRetryKey(); return (false, -1); } await m_cache_request.deleteRetryKey(); Log.getLogger().debug($"updateDailyCaliumConverter : finished!!! - mis_pivot_calium[{mis_pivot_calium}]"); return (true, mis_pivot_calium); } private async Task<(Result, double mis_pivot_calium)> checkEchoSystemDailyCaliumAsync(CaliumStorageAttrib caliumStorageAttrib, DateTime pivotTime) { var mis_pivot_calium = 0.0; // 1. echoSystem 조회 var web3_action = getOwner().getEntityAction(); NullReferenceCheckHelper.throwIfNull(web3_action, () => $"web3_action is null !!! - {getOwner().toBasicString()}"); var (result, msg) = await web3_action.getDailyRollUpDataAsync(caliumStorageAttrib.DailyEpoch + caliumStorageAttrib.MisEpoch); if (result.isFail() && msg?.m_code != "FIN.WRY.000") return (result, -1); // 1-1. 최초 호출인 경우 데이터 정리 if (caliumStorageAttrib.DailyEpoch <= 0) { result = initializeStorage(caliumStorageAttrib, msg?.m_list?.FirstOrDefault()); if(result.isFail()) return (result, 0); } // 2. Data 를 찾지 못하면, 당일 Rollup 이 되지 않은 상태, 예전 데이터로 채워서 넣어야함. if (msg?.m_code == "FIN.WRY.000") { msg = makePreviousRollUpData(caliumStorageAttrib); caliumStorageAttrib.MisEpoch += 1; result.setSuccess(); } else { caliumStorageAttrib.MisEpoch = 0; } NullReferenceCheckHelper.throwIfNull(msg, () => $"web3 response is null !!! - epoch:{caliumStorageAttrib.DailyEpoch} / {getOwner().toBasicString()}"); NullReferenceCheckHelper.throwIfNull(msg.m_list, () => $"web3 response is null !!! - epoch:{caliumStorageAttrib.DailyEpoch} / {getOwner().toBasicString()}"); Log.getLogger().debug($"checkEchoSystemDailyCaliumAsync : RollUpData Count[{msg.m_list.Count}]"); // 3. Daily 데이터 적용 foreach (var rollup in msg.m_list) { var pivot_calium = supplyRollUpData(caliumStorageAttrib, rollup, mis_pivot_calium, pivotTime); mis_pivot_calium = CaliumStorageHelper.AddDoubleByLong(mis_pivot_calium, pivot_calium); } caliumStorageAttrib.DailyPivotDate = pivotTime; Log.getLogger().debug($"checkEchoSystemDailyCaliumAsync : DailyPivotDate[{pivotTime}] / mis_pivot_calium[{mis_pivot_calium}]"); return (result, mis_pivot_calium); } private CaliumRollUpResponse makePreviousRollUpData(CaliumStorageAttrib attrib) { var response = new CaliumRollUpResponse(); response.m_list = new List(); var rollup = new RollUpData(); rollup.m_create_time = attrib.DailyPivotDate.AddDays(1).AddHours(-1); rollup.m_daily_converter_rate = attrib.ConverterStorage.DailyConvertRate; rollup.m_epoch = attrib.DailyEpoch; rollup.m_daily_inflation_rate = attrib.ExchangerStorage.DailyInflationRate; rollup.m_convertor_volume = attrib.ConverterStorage.DailyFillUpStandardCalium; response.m_list.Add(rollup); return response; } private double supplyRollUpData(CaliumStorageAttrib caliumStorageAttrib, RollUpData rollup, double mis_pivot_calium, DateTime pivotTime) { Log.getLogger().debug($"supplyRollUpData : Attrib [epoch-{caliumStorageAttrib.DailyEpoch}] RollUp [epoch-{rollup.m_epoch}]"); if (rollup.m_epoch != 0 && rollup.m_epoch == caliumStorageAttrib.DailyEpoch) { // 그날의 미지급 Calium 추가 var check_pivot_time = CaliumStorageHelper.CurrentPivotTimeDate(caliumStorageAttrib.ConverterStorage.LastFillUpDate); var data = checkMissFillUpDailyCalium(caliumStorageAttrib, check_pivot_time.AddDays(1).AddSeconds(-1)); var fill_up_calium = calculateFillupCalium(caliumStorageAttrib, data.missFillUpCount, data.lastFillUpDate); mis_pivot_calium = CaliumStorageHelper.AddDoubleByLong(mis_pivot_calium, fill_up_calium); caliumStorageAttrib.ConverterStorage.TotalCalium = CaliumStorageHelper.AddDoubleByLong(caliumStorageAttrib.ConverterStorage.TotalCalium, fill_up_calium); caliumStorageAttrib.ConverterStorage.LastFillUpDate = check_pivot_time.AddHours(MetaHelper.GameConfigMeta.CaliumConverterCycleTime * 2); Log.getLogger().debug($"supplyRollUpData : 1. mis_pivot_calium[{mis_pivot_calium}]"); return mis_pivot_calium; } caliumStorageAttrib.ConverterStorage.ConverterCumulativeCalium = CaliumStorageHelper.AddDoubleByLong(caliumStorageAttrib.ConverterStorage.ConverterCumulativeCalium, rollup.m_convertor_volume); // 1일을 추가한 이유 : create_time 이 전일 23:00:00 ~ 23:59:59 에 생성되기 때문 var check_date = new DateTime(rollup.m_create_time.Year, rollup.m_create_time.Month, rollup.m_create_time.Day, 0, 0, 0); check_date = check_date.AddDays(1); // PivotTime 이 00시 기준이 아닌 경우 체크해야 하기 때문에 시간 추가 check_date = check_date.AddHours(MetaHelper.GameConfigMeta.CaliumConverterPivotTime); if (check_date < pivotTime) { mis_pivot_calium = CaliumStorageHelper.AddDoubleByLong(mis_pivot_calium, rollup.m_convertor_volume); caliumStorageAttrib.ConverterStorage.TotalCalium = CaliumStorageHelper.AddDoubleByLong(caliumStorageAttrib.ConverterStorage.TotalCalium, rollup.m_convertor_volume); caliumStorageAttrib.ConverterStorage.LastFillUpDate = check_date.AddHours(MetaHelper.GameConfigMeta.CaliumConverterCycleTime * 2); } if (caliumStorageAttrib.DailyEpoch >= rollup.m_epoch) { Log.getLogger().debug($"supplyRollUpData : 2. mis_pivot_calium[{mis_pivot_calium}]"); return mis_pivot_calium; } caliumStorageAttrib.DailyEpoch = rollup.m_epoch; caliumStorageAttrib.ConverterStorage.DailyFillUpStandardCalium = rollup.m_convertor_volume; caliumStorageAttrib.ConverterStorage.DailyConvertRate = rollup.m_daily_converter_rate; caliumStorageAttrib.ExchangerStorage.DailyInflationRate = rollup.m_daily_inflation_rate; Log.getLogger().debug($"supplyRollUpData : 3. mis_pivot_calium[{mis_pivot_calium}]"); return mis_pivot_calium; } private (int missFillUpCount, DateTime lastFillUpDate) checkMissFillUpDailyCalium(CaliumStorageAttrib caliumStorageAttrib, DateTime? nextPivotTime = null) { var current = nextPivotTime ?? DateTimeHelper.Current; var miss_fill_up_count = 0; // 1. 마지막 충전 시간 확인 var last_fill_up_date = caliumStorageAttrib.ConverterStorage.LastFillUpDate; var fill_up_date = (last_fill_up_date == DateTimeHelper.MinTime) ? current : last_fill_up_date; var next_fill_up_date = getNextFillDate(caliumStorageAttrib, fill_up_date); // 2. 다음 충전 시간 체크 while (next_fill_up_date <= current) { miss_fill_up_count++; fill_up_date = next_fill_up_date; next_fill_up_date = getNextFillDate(caliumStorageAttrib, fill_up_date); } Log.getLogger().debug($"checkMissFillUpDailyCalium - miss_fill_up_count[{miss_fill_up_count}] / last_fill_up_date[{last_fill_up_date}] / fill_up_date[{fill_up_date}] / next_pivot_time[{nextPivotTime ?? DateTimeHelper.MinTime}]"); return (miss_fill_up_count, fill_up_date); } private DateTime getNextFillDate(CaliumStorageAttrib storageAttrib, DateTime current) { var check = storageAttrib.DailyPivotDate; while (check <= current) { check = check.AddHours(MetaHelper.GameConfigMeta.CaliumConverterCycleTime); } return check; } private async Task fillUpDailyCalium(CaliumStorageAttrib caliumStorageAttrib, int fillUpCount, DateTime lastFillUpDate) { // 1. daily calium 충전량 계산 var fill_up_calium = calculateFillupCalium(caliumStorageAttrib, fillUpCount, lastFillUpDate); // 2. 최초 시작은 기본값으로 채움 if (caliumStorageAttrib.ConverterStorage.LastFillUpDate == DateTimeHelper.MinTime) { fill_up_calium = (double)MetaHelper.GameConfigMeta.CaliumConverterInitialValue; } Log.getLogger().debug($"fillUpDailyCalium - fill_up_calium[{fill_up_calium}] / fillUpCount[{fillUpCount}]"); if (fill_up_calium <= 0) return fill_up_calium; // 3. calium 변경 var result = await changeCaliumConverterTotal(fill_up_calium); if (result.isFail()) return -1; // 4. data 갱신 _ = loadStorageAttribute(); return fill_up_calium; } private double calculateFillupCalium(CaliumStorageAttrib caliumStorageAttrib, int fillUpCount, DateTime lastFillupDate) { // 0. 충전 횟수가 0 이면, 처리 안함 if (fillUpCount <= 0) return 0; var daily_total_calium_long = (long)(caliumStorageAttrib.ConverterStorage.DailyFillUpStandardCalium * EchoSystemHelper.DoubleCalculateDigitsLong); var fill_up_calium_long = daily_total_calium_long / m_repeat_count; var fill_up_leave_long = daily_total_calium_long % m_repeat_count; fill_up_calium_long *= fillUpCount; // 마지막 회차의 경우, 나머지 부분을 추가해줘야 한다. if (lastFillupDate.AddHours(MetaHelper.GameConfigMeta.CaliumConverterCycleTime) >= caliumStorageAttrib.DailyPivotDate.AddDays(1)) { fill_up_calium_long += fill_up_leave_long; } return fill_up_calium_long / (double)EchoSystemHelper.DoubleCalculateDigitsLong; } }