protected override Task <bool> IsTriggered(ITrigger trigger, RecipeTrigger recipeTrigger,
                                            NBXplorerNewBlockTriggerData triggerData,
                                            NBXplorerNewBlockTriggerParameters parameters)
 {
     return(Task.FromResult(!triggerData.CryptoCode.Equals(parameters.CryptoCode,
                                                           StringComparison.InvariantCultureIgnoreCase)));
 }
示例#2
0
        protected override async Task <bool> IsTriggered(ITrigger trigger, RecipeTrigger recipeTrigger,
                                                         NBXplorerNewTransactionTriggerData triggerData,
                                                         NBXplorerNewTransactionTriggerParameters parameters)
        {
            var walletService = new NBXplorerWalletService(recipeTrigger.ExternalService,
                                                           _nbXplorerPublicWalletProvider, _derivationSchemeParser, _derivationStrategyFactoryProvider,
                                                           _nbXplorerClientProvider);
            var trackedSource = await walletService.ConstructTrackedSource();

            var walletData = walletService.GetData();

            if (!triggerData.CryptoCode.Equals(walletData.CryptoCode,
                                               StringComparison.InvariantCultureIgnoreCase))
            {
                return(false);
            }

            if (triggerData.Event != null && triggerData.Event.TrackedSource == trackedSource)
            {
                return(await UpdateTxToRecipeTrigger(triggerData.Event.TransactionData, recipeTrigger,
                                                     parameters));
            }

            return(false);
        }
        BuildModel(
            NBXplorerNewTransactionViewModel viewModel, RecipeTrigger mainModel)
        {
            if (!ModelState.IsValid)
            {
                var services = await _externalServiceManager.GetExternalServicesData(new ExternalServicesDataQuery()
                {
                    Type   = new[] { NBXplorerWalletService.NBXplorerWalletServiceType },
                    UserId = GetUserId()
                });

                viewModel.ExternalServices = new SelectList(services, nameof(ExternalServiceData.Id),
                                                            nameof(ExternalServiceData.Name), viewModel.ExternalServiceId);

                return(null, viewModel);
            }

            var recipeTrigger = mainModel;
            var oldData       = recipeTrigger.Get <NBXplorerNewTransactionTriggerParameters>();
            var newData       = (NBXplorerNewTransactionTriggerParameters)viewModel;

            newData.Transactions = oldData.Transactions;

            recipeTrigger.ExternalServiceId = viewModel.ExternalServiceId;
            recipeTrigger.Set((NBXplorerNewTransactionTriggerParameters)viewModel);

            return(recipeTrigger, null);
        }
示例#4
0
        private async Task <IActionResult> SetItUp(CreateDCAViewModel vm)
        {
            var presetName = $"Generated_DCA";

            var recipe = new Recipe()
            {
                Name        = presetName,
                Description = "Generated from a preset",
                UserId      = _userManager.GetUserId(User),
                Enabled     = false
            };
            await _recipeManager.AddOrUpdateRecipe(recipe);

            var recipeTrigger = new RecipeTrigger()
            {
                TriggerId = new TimerTrigger().Id,
                RecipeId  = recipe.Id
            };

            recipeTrigger.Set(new TimerTriggerParameters()
            {
                StartOn            = vm.StartOn,
                TriggerEvery       = vm.TriggerEvery,
                TriggerEveryAmount = vm.TriggerEveryAmount
            });
            await _recipeManager.AddOrUpdateRecipeTrigger(recipeTrigger);

            var recipeActionGroup = new RecipeActionGroup()
            {
                RecipeId = recipe.Id
            };

            await _recipeManager.AddRecipeActionGroup(recipeActionGroup);

            var tradeAction = new RecipeAction()
            {
                RecipeId            = recipe.Id,
                RecipeActionGroupId = recipeActionGroup.Id,
                ActionId            = new PlaceOrderDataActionHandler().ActionId,
                ExternalServiceId   = vm.SelectedExchangeServiceId,
                Order    = 0,
                DataJson = JsonConvert.SerializeObject(new PlaceOrderData()
                {
                    Amount       = vm.FiatAmount.ToString(CultureInfo.InvariantCulture),
                    IsBuy        = vm.IsBuy,
                    MarketSymbol = vm.MarketSymbol,
                    OrderType    = OrderType.Market
                })
            };

            await _recipeManager.AddOrUpdateRecipeAction(tradeAction);


            return(RedirectToAction("EditRecipe", "Recipes", new
            {
                id = recipe.Id,
                statusMessage =
                    "Preset generated. Recipe is currently disabled for now. Please verify details are correct before enabling!"
            }));
        }
        protected override Task <bool> IsTriggered(ITrigger trigger, RecipeTrigger recipeTrigger,
                                                   ReceiveWebRequestTriggerData triggerData,
                                                   ReceiveWebRequestTriggerParameters parameters)
        {
            if (!string.IsNullOrEmpty(parameters.Method) && triggerData.Method != parameters.Method)
            {
                return(Task.FromResult(false));
            }

            if (!triggerData.RelativeUrl.Equals(parameters.RelativeUrl, StringComparison.InvariantCultureIgnoreCase))
            {
                return(Task.FromResult(false));
            }

            switch (parameters.BodyComparer)
            {
            case ReceiveWebRequestTriggerParameters.FieldComparer.None:
                return(Task.FromResult(true));

            case ReceiveWebRequestTriggerParameters.FieldComparer.Equals:
                return(Task.FromResult(triggerData.Body.Equals(parameters.Body)));

            case ReceiveWebRequestTriggerParameters.FieldComparer.Contains:
                return(Task.FromResult(triggerData.Body.Contains(parameters.Body)));

            default:
                return(Task.FromResult(true));
            }
        }
示例#6
0
 public void LoadRecipe(RecipeTrigger recipeTrigger)
 {
     currentRecipe.dialogue = recipeTrigger.dialogue;
     currentRecipe.RecipeScrollThrough();
     SwitchButtons(recipeUI, false);
     mainButton.interactable = true;
 }
示例#7
0
        private async Task <bool> UpdateTxToRecipeTrigger(TransactionResult transactionResult,
                                                          RecipeTrigger recipeTrigger, NBXplorerNewTransactionTriggerParameters parameters)
        {
            if (parameters.Transactions == null)
            {
                parameters.Transactions = new List <TransactionResult>();
            }
            var matchedIndex = parameters.Transactions.FindIndex(i =>
                                                                 i.TransactionHash == transactionResult.TransactionHash);
            var confirmations = transactionResult.Confirmations;

            if (matchedIndex != -1)
            {
                parameters.Transactions.RemoveAt(matchedIndex);
            }

            var result = parameters.ConfirmationsRequired < confirmations;

            if (!result)
            {
                parameters.Transactions.Add(transactionResult);
            }

            if (!result || matchedIndex != -1)
            {
                recipeTrigger.Set(parameters);
                await _recipeManager.AddOrUpdateRecipeTrigger(recipeTrigger);
            }

            return(result);
        }
 protected override Task <bool> IsTriggered(ITrigger trigger, RecipeTrigger recipeTrigger,
                                            CheckExchangeBalanceTriggerData triggerData,
                                            CheckExchangeBalanceTriggerParameters parameters)
 {
     return(Task.FromResult(recipeTrigger.ExternalServiceId.Equals(triggerData.ExternalServiceId) &&
                            triggerData.Asset.Equals(parameters.Asset, StringComparison.InvariantCultureIgnoreCase) &&
                            IsBalanceWithinCriteria(triggerData, parameters)));
 }
        protected override Task <(RecipeTrigger ToSave, DynamicServiceMarkerTriggerParametersViewModel showViewModel)> BuildModel(
            DynamicServiceMarkerTriggerParametersViewModel viewModel, RecipeTrigger mainModel)
        {
            mainModel.Set(viewModel);

            return(Task.FromResult <(RecipeTrigger ToSave, DynamicServiceMarkerTriggerParametersViewModel showViewModel)>((mainModel,
                                                                                                                           null)));
        }
        private void SetValues(InvoiceStatusChangedTriggerViewModel from, RecipeTrigger to)
        {
            to.ExternalServiceId = from.ExternalServiceId;
            to.RecipeId          = from.RecipeId;
            var currentData = to.Get <InvoiceStatusChangedTriggerParameters>();

            currentData.Status = from.Status;
            to.Set(currentData);
        }
示例#11
0
 // Use this for initialization
 void Start()
 {
     gameScript         = FindObjectOfType <GameController>().gameObject.GetComponent <GameController>();
     dTrigger           = GetComponent <TutorialTrigger>();
     currentRecipe      = GetComponent <RecipeTrigger>();
     dScript            = GetComponent <DialogueManager>();
     tvPos              = transform.position;
     transform.position = new Vector3(transform.position.x, transform.position.y - 1, transform.position.z);
 }
        private void SetValues(RecipeTrigger from, InvoiceStatusChangedTriggerViewModel to)
        {
            to.RecipeId          = from.RecipeId;
            to.ExternalServiceId = from.ExternalServiceId;
            var fromData = from.Get <InvoiceStatusChangedTriggerParameters>();

            to.Status   = fromData.Status;
            to.Statuses = new SelectList(AllowedStatuses, "Value", "Text", fromData.Status);
        }
 public Task <IViewComponentResult> InvokeAsync(RecipeTrigger recipeTrigger)
 {
     return(Task.FromResult <IViewComponentResult>(View(new ViewRecipeTriggerViewModel()
     {
         RecipeTrigger = recipeTrigger,
         ExternalServiceData = recipeTrigger.ExternalService,
         TriggerDescriptor =
             _triggerDescriptors.SingleOrDefault(descriptor => descriptor.TriggerId == recipeTrigger.TriggerId)
     })));
 }
        private void SetValues(RecipeTrigger from, ReceivedEmailViewModel to)
        {
            to.RecipeId          = from.RecipeId;
            to.ExternalServiceId = from.ExternalServiceId;
            var fromData = from.Get <ReceivedEmailTriggerParameters>();

            to.Body            = fromData.Body;
            to.Subject         = fromData.Subject;
            to.FromEmail       = fromData.FromEmail;
            to.BodyComparer    = fromData.BodyComparer;
            to.SubjectComparer = fromData.SubjectComparer;
        }
        protected override Task <bool> IsTriggered(ITrigger trigger, RecipeTrigger recipeTrigger,
                                                   InvoiceStatusChangedTriggerData triggerData,
                                                   InvoiceStatusChangedTriggerParameters parameters)
        {
            if (string.IsNullOrEmpty(parameters.Status))
            {
                return(Task.FromResult(true));
            }

            return(Task.FromResult(triggerData.Invoice.Status.Equals(parameters.Status,
                                                                     StringComparison.InvariantCultureIgnoreCase)));
        }
示例#16
0
        protected override Task <NBXplorerNewBlockViewModel> BuildViewModel(RecipeTrigger data)
        {
            var innerData = data.Get <NBXplorerNewBlockTriggerParameters>();

            return(Task.FromResult(new NBXplorerNewBlockViewModel()
            {
                CryptoCodes = new SelectList(_options.Cryptos?.ToList() ?? new List <string>(), innerData.CryptoCode),

                RecipeId = data.RecipeId,
                CryptoCode = innerData.CryptoCode
            }));
        }
示例#17
0
        protected override Task <(RecipeTrigger ToSave, NBXplorerNewBlockViewModel showViewModel)> BuildModel(
            NBXplorerNewBlockViewModel viewModel, RecipeTrigger mainModel)
        {
            if (!ModelState.IsValid)
            {
                viewModel.CryptoCodes = new SelectList(_options.Cryptos?.ToList() ?? new List <string>(), viewModel.CryptoCode);
                return(Task.FromResult <(RecipeTrigger ToSave, NBXplorerNewBlockViewModel showViewModel)>((null, viewModel)));
            }

            var recipeTrigger = mainModel;

            recipeTrigger.Set((NBXplorerNewBlockTriggerParameters)viewModel);
            return(Task.FromResult <(RecipeTrigger ToSave, NBXplorerNewBlockViewModel showViewModel)>((recipeTrigger, null)));
        }
        public Task <bool> IsTriggered(ITrigger trigger, RecipeTrigger recipeTrigger)
        {
            if (recipeTrigger.TriggerId != trigger.Id || trigger.Id != TriggerId)
            {
                return(Task.FromResult(false));
            }

            var triggerData = trigger.Get <TTriggerData>();

            if (typeof(TTriggerParameters).IsAssignableFrom(typeof(IUseExternalService)) &&
                ((IUseExternalService)triggerData).ExternalServiceId != recipeTrigger.ExternalServiceId)
            {
                return(Task.FromResult(false));
            }

            return(IsTriggered(trigger, recipeTrigger, triggerData, recipeTrigger.Get <TTriggerParameters>()));
        }
示例#19
0
        public async Task <bool> IsTriggered(ITrigger trigger, RecipeTrigger recipeTrigger)
        {
            if (recipeTrigger.TriggerId != trigger.Id || trigger.Id != TriggerId)
            {
                return(false);
            }

            var triggerData = await GetTriggerData(trigger);

            if (typeof(IUseExternalService).IsAssignableFrom(typeof(TTriggerData)) &&
                ((IUseExternalService)triggerData).ExternalServiceId != recipeTrigger.ExternalServiceId)
            {
                return(false);
            }

            return(await IsTriggered(trigger, recipeTrigger, triggerData, recipeTrigger.Get <TTriggerParameters>()));
        }
示例#20
0
        protected override Task <(RecipeTrigger ToSave, TimerTriggerViewModel showViewModel)> BuildModel(
            TimerTriggerViewModel viewModel, RecipeTrigger mainModel)
        {
            if (viewModel.TriggerEveryAmount <= 0)
            {
                ModelState.AddModelError(nameof(TimerTriggerViewModel.TriggerEveryAmount),
                                         "Amount needs to be at least 1");
            }

            if (!ModelState.IsValid)
            {
                return(Task.FromResult <(RecipeTrigger ToSave, TimerTriggerViewModel showViewModel)>((null, viewModel)));
            }

            mainModel.Set((TimerTriggerParameters)viewModel);

            return(Task.FromResult <(RecipeTrigger ToSave, TimerTriggerViewModel showViewModel)>((mainModel, null)));
        }
        public Task <IActionResult> EditData(RecipeTrigger data)
        {
            using (var scope = DependencyHelper.ServiceScopeFactory.CreateScope())
            {
                var identifier  = $"{Guid.NewGuid()}";
                var memoryCache = scope.ServiceProvider.GetService <IMemoryCache>();
                memoryCache.Set(identifier, data, new MemoryCacheEntryOptions()
                {
                    SlidingExpiration = TimeSpan.FromMinutes(60)
                });

                return(Task.FromResult <IActionResult>(new RedirectToActionResult(
                                                           nameof(InvoiceStatusChangedController.EditData),
                                                           "InvoiceStatusChanged", new
                {
                    identifier
                })));
            }
        }
        protected override async Task <bool> IsTriggered(ITrigger trigger, RecipeTrigger recipeTrigger,
                                                         NBXplorerBalanceTriggerData triggerData,
                                                         NBXplorerBalanceTriggerParameters parameters)
        {
            var walletService = new NBXplorerWalletService(recipeTrigger.ExternalService,
                                                           _nbXplorerPublicWalletProvider,
                                                           _derivationSchemeParser,
                                                           _nbXplorerClientProvider);

            var walletData = walletService.GetData();

            if (!triggerData.CryptoCode.Equals(walletData.CryptoCode,
                                               StringComparison.InvariantCultureIgnoreCase))
            {
                return(false);
            }

            return(await walletService.ConstructTrackedSource() == triggerData.TrackedSource && IsBalanceWithinCriteria(triggerData, parameters));
        }
示例#23
0
        protected override async Task <CheckExchangeBalanceViewModel> BuildViewModel(RecipeTrigger data)
        {
            var innerData = data.Get <CheckExchangeBalanceTriggerParameters>();
            var services  = await _externalServiceManager.GetExternalServicesData(new ExternalServicesDataQuery()
            {
                Type   = new[] { ExchangeService.ExchangeServiceType },
                UserId = GetUserId()
            });

            return(new CheckExchangeBalanceViewModel()
            {
                RecipeId = data.RecipeId,
                ExternalServiceId = data.ExternalServiceId,
                ExternalServices = new SelectList(services, nameof(ExternalServiceData.Id),
                                                  nameof(ExternalServiceData.Name), data.ExternalServiceId),
                BalanceValue = innerData.BalanceValue,
                BalanceComparer = innerData.BalanceComparer,
                Asset = innerData.Asset
            });
        }
示例#24
0
        protected override async Task <NBXplorerBalanceViewModel> BuildViewModel(RecipeTrigger data)
        {
            var innerData = data.Get <NBXplorerBalanceTriggerParameters>();
            var services  = await _externalServiceManager.GetExternalServicesData(new ExternalServicesDataQuery()
            {
                Type   = new[] { NBXplorerWalletService.NBXplorerWalletServiceType },
                UserId = GetUserId()
            });

            return(new NBXplorerBalanceViewModel()
            {
                RecipeId = data.RecipeId,
                ExternalServiceId = data.ExternalServiceId,
                ExternalServices = new SelectList(services, nameof(ExternalServiceData.Id),
                                                  nameof(ExternalServiceData.Name), data.ExternalServiceId),
                BalanceComparer = innerData.BalanceComparer,
                BalanceValue = innerData.Balance?.ToUnit(MoneyUnit.BTC) ?? 0,
                BalanceMoneyUnit = MoneyUnit.BTC
            });
        }
示例#25
0
        BuildModel(
            InvoiceStatusChangedTriggerViewModel viewModel, RecipeTrigger mainModel)
        {
            if (viewModel.Action != "EditData" || !ModelState.IsValid)
            {
                var btcPayServices = await _externalServiceManager.GetExternalServicesData(
                    new ExternalServicesDataQuery()
                {
                    Type   = new[] { BtcPayServerService.BtcPayServerServiceType },
                    UserId = GetUserId()
                });

                viewModel.ExternalServices = new SelectList(btcPayServices, nameof(ExternalServiceData.Id),
                                                            nameof(ExternalServiceData.Name), viewModel.ExternalServiceId);


                if (viewModel.Action.StartsWith("add-condition", StringComparison.InvariantCultureIgnoreCase))
                {
                    viewModel.Conditions.Add(new InvoiceStatusChangeCondition()
                    {
                        Status            = GetAvailableStatuses(viewModel.Conditions.Select(condition => condition.Status).ToArray()).FirstOrDefault()?.Value ?? Invoice.STATUS_NEW,
                        ExceptionStatuses = new List <string>()
                        {
                            Invoice.EXSTATUS_FALSE
                        }
                    });
                }

                if (viewModel.Action.StartsWith("remove-condition", StringComparison.InvariantCultureIgnoreCase))
                {
                    var index = int.Parse(viewModel.Action.Substring(viewModel.Action.IndexOf(":", StringComparison.InvariantCultureIgnoreCase) + 1));
                    viewModel.Conditions.RemoveAt(index);
                }

                return(null, viewModel);
            }

            mainModel.ExternalServiceId = viewModel.ExternalServiceId;
            mainModel.Set((InvoiceStatusChangedTriggerParameters)viewModel);
            return(mainModel, null);
        }
示例#26
0
        protected override Task <(RecipeTrigger ToSave, ReceiveWebRequestTriggerViewModel showViewModel)> BuildModel(
            ReceiveWebRequestTriggerViewModel viewModel, RecipeTrigger mainModel)
        {
            if (!string.IsNullOrEmpty(viewModel.Body) &&
                viewModel.BodyComparer == ReceiveWebRequestTriggerParameters.FieldComparer.None)
            {
                ModelState.AddModelError(nameof(ReceiveWebRequestTriggerViewModel.BodyComparer),
                                         "Please choose a comparison type or leave field blank");
            }

            if (!ModelState.IsValid)
            {
                return(Task.FromResult <(RecipeTrigger ToSave, ReceiveWebRequestTriggerViewModel showViewModel)>((null,
                                                                                                                  viewModel)));
            }

            mainModel.Set((ReceiveWebRequestTriggerParameters)viewModel);

            return(Task.FromResult <(RecipeTrigger ToSave, ReceiveWebRequestTriggerViewModel showViewModel)>((mainModel,
                                                                                                              null)));
        }
示例#27
0
        protected override Task <bool> IsTriggered(ITrigger trigger, RecipeTrigger recipeTrigger,
                                                   TimerTriggerData triggerData,
                                                   TimerTriggerParameters parameters)
        {
            if (parameters.StartOn.HasValue && parameters.StartOn < DateTime.Now)
            {
                return(Task.FromResult(false));
            }

            if (!parameters.LastTriggered.HasValue)
            {
                return(Task.FromResult(true));
            }

            switch (parameters.TriggerEvery)
            {
            case TimerTriggerParameters.TimerResetEvery.Minute:
                return(Task.FromResult(DateTime.Now.Subtract(parameters.LastTriggered.Value).TotalMinutes >=
                                       parameters.TriggerEveryAmount));

            case TimerTriggerParameters.TimerResetEvery.Hour:
                return(Task.FromResult(DateTime.Now.Subtract(parameters.LastTriggered.Value).TotalHours >=
                                       parameters.TriggerEveryAmount));

            case TimerTriggerParameters.TimerResetEvery.Day:
                return(Task.FromResult(DateTime.Now.Subtract(parameters.LastTriggered.Value).TotalDays >=
                                       parameters.TriggerEveryAmount));

            case TimerTriggerParameters.TimerResetEvery.Month:
                return(Task.FromResult(parameters.LastTriggered.Value.MonthDifference(DateTime.Now) >=
                                       parameters.TriggerEveryAmount));

            case TimerTriggerParameters.TimerResetEvery.Year:
                return(Task.FromResult(parameters.LastTriggered.Value.YearDifference(DateTime.Now) >=
                                       parameters.TriggerEveryAmount));

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
        public async Task <IActionResult> EditRecipeTrigger(string id, string recipeTriggerId,
                                                            EditRecipeTriggerViewModel model)
        {
            var recipe = await _recipeManager.GetRecipe(id, _userManager.GetUserId(User));

            if (recipe == null)
            {
                return(GetNotFoundActionResult());
            }


            if (!ModelState.IsValid)
            {
                model.RecipeTrigger = model.RecipeTrigger;
                model.Triggers      = new SelectList(_triggerDescriptors, nameof(ITriggerDescriptor.TriggerId),
                                                     nameof(ITriggerDescriptor.Name), model.TriggerId);

                return(View(model));
            }

            var recipeTrigger = recipe.RecipeTrigger;

            if (string.IsNullOrEmpty(recipeTriggerId) || recipe.RecipeTrigger.TriggerId != model.TriggerId)
            {
                recipeTrigger = new RecipeTrigger()
                {
                    Id        = recipeTriggerId,
                    RecipeId  = id,
                    TriggerId = model.TriggerId,
                };
            }

            var serviceDescriptor =
                _triggerDescriptors.Single(descriptor =>
                                           descriptor.TriggerId == recipeTrigger.TriggerId);

            return(await serviceDescriptor.EditData(recipeTrigger));
        }
        protected override Task <bool> IsTriggered(ITrigger trigger, RecipeTrigger recipeTrigger,
                                                   InvoiceStatusChangedTriggerData triggerData,
                                                   InvoiceStatusChangedTriggerParameters parameters)
        {
            var exceptionStatus = Invoice.EXSTATUS_FALSE;

            if (triggerData.Invoice.ExceptionStatus.Type == JTokenType.String)
            {
                exceptionStatus = triggerData.Invoice.ExceptionStatus.Value <string>();
            }
            var status = triggerData.Invoice.Status;

            foreach (var condition in parameters.Conditions)
            {
                if (condition.Status.Equals(status, StringComparison.InvariantCultureIgnoreCase) &&
                    condition.ExceptionStatuses.Contains(exceptionStatus))
                {
                    return(Task.FromResult(true));
                }
            }

            return(Task.FromResult(false));
        }
示例#30
0
        protected override async Task <(RecipeTrigger ToSave, ReceivedLightningPaymentViewModel showViewModel)> BuildModel(
            ReceivedLightningPaymentViewModel viewModel, RecipeTrigger mainModel)
        {
            if (!ModelState.IsValid)
            {
                var pop3Services = await _externalServiceManager.GetExternalServicesData(new ExternalServicesDataQuery()
                {
                    Type   = new[] { LightningNodeService.LightningNodeServiceType },
                    UserId = GetUserId()
                });


                viewModel.ExternalServices = new SelectList(pop3Services, nameof(ExternalServiceData.Id),
                                                            nameof(ExternalServiceData.Name), viewModel.ExternalServiceId);
                return(null, viewModel);
            }

            var recipeTrigger = mainModel;

            recipeTrigger.ExternalServiceId = viewModel.ExternalServiceId;
            recipeTrigger.Set((ReceivedLightningPaymentTriggerParameters)viewModel);
            return(recipeTrigger, null);
        }