コード例 #1
0
        private static async Task <TaskResult> DoTransaction(TransactionRequest request, VooperContext context)
        {
            if (!request.Force && request.Amount < 0)
            {
                return(new TaskResult(false, "Transaction must be positive."));
            }

            if (request.Amount == 0)
            {
                return(new TaskResult(false, "Transaction must have a value."));
            }

            if (request.FromAccount == request.ToAccount)
            {
                return(new TaskResult(false, $"An entity cannot send credits to itself."));
            }

            Entity fromUser = await Entity.FindAsync(request.FromAccount);

            Entity toUser = await Entity.FindAsync(request.ToAccount);

            if (fromUser == null)
            {
                return(new TaskResult(false, $"Failed to find sender {request.FromAccount}."));
            }
            if (toUser == null)
            {
                return(new TaskResult(false, $"Failed to find reciever {request.ToAccount}."));
            }

            if (!request.Force && fromUser.Credits < request.Amount)
            {
                return(new TaskResult(false, $"{fromUser.Name} cannot afford to send ¢{request.Amount}"));
            }

            GovControls govControls = await GovControls.GetCurrentAsync(context);

            Transaction trans = new Transaction()
            {
                ID       = Guid.NewGuid().ToString(),
                Credits  = request.Amount,
                FromUser = request.FromAccount,
                ToUser   = request.ToAccount,
                Details  = request.Detail,
                Time     = DateTime.Now
            };

            await context.Transactions.AddAsync(trans);

            fromUser.Credits -= request.Amount;
            toUser.Credits   += request.Amount;

            context.Update(fromUser);
            context.Update(toUser);

            await context.SaveChangesAsync();

            if (toUser.Id != VooperiaID)
            {
                if (request.Tax == ApplicableTax.None && toUser is Group && ((Group)toUser).Group_Category == Group.GroupTypes.Company)
                {
                    request.Tax = ApplicableTax.Corporate;
                }

                if (request.Tax == ApplicableTax.Payroll)
                {
                    decimal ntax = request.Amount * (govControls.PayrollTaxRate / 100.0m);

                    govControls.UBIAccount += ntax * (govControls.UBIBudgetPercent / 100.0m);

                    govControls.PayrollTaxRevenue += ntax;

                    RequestTransaction(new TransactionRequest(toUser.Id, VooperiaID, ntax, "Payroll Tax", ApplicableTax.None, true));
                }
                else if (request.Tax == ApplicableTax.Sales)
                {
                    decimal ntax = request.Amount * (govControls.SalesTaxRate / 100.0m);

                    govControls.UBIAccount += ntax * (govControls.UBIBudgetPercent / 100.0m);

                    govControls.SalesTaxRevenue += ntax;

                    RequestTransaction(new TransactionRequest(fromUser.Id, VooperiaID, ntax, "Sales Tax", ApplicableTax.None, true));
                }
                else if (request.Tax == ApplicableTax.Corporate)
                {
                    decimal ntax = request.Amount * (govControls.CorporateTaxRate / 100.0m);

                    govControls.UBIAccount += ntax * (govControls.UBIBudgetPercent / 100.0m);

                    govControls.CorporateTaxRevenue += ntax;

                    RequestTransaction(new TransactionRequest(toUser.Id, VooperiaID, ntax, "Corporate Tax", ApplicableTax.None, true));
                }
                else if (request.Tax == ApplicableTax.CapitalGains)
                {
                    decimal ntax = request.Amount * (govControls.CapitalGainsTaxRate / 100.0m);

                    govControls.UBIAccount += ntax * (govControls.UBIBudgetPercent / 100.0m);

                    govControls.CapitalGainsTaxRevenue += ntax;

                    RequestTransaction(new TransactionRequest(fromUser.Id, VooperiaID, ntax, "Capital Gains Tax", ApplicableTax.None, true));
                }
            }
            else
            {
                if (!request.Detail.Contains("Tax") && !request.Detail.Contains("Stock purchase"))
                {
                    govControls.SalesRevenue += request.Amount;
                    govControls.UBIAccount   += (request.Amount * (govControls.UBIBudgetPercent / 100.0m));
                }
            }

            context.GovControls.Update(govControls);
            await context.SaveChangesAsync();

            return(new TaskResult(true, $"Successfully sent ¢{request.Amount} to {toUser.Name}."));
        }
コード例 #2
0
        public static async Task RunTrades()
        {
#if DEBUG
            // Prevent local testing from running the stock exchange
            return;
#endif
            using (VooperContext context = new VooperContext(VooperContext.DBOptions))
            {
                foreach (StockDefinition def in context.StockDefinitions)
                {
                    StockOffer sell = await GetLowestSellOffer(def.Ticker, context);

                    StockOffer buy = await GetHighestBuyOffer(def.Ticker, context);

                    // If buy > sell, trade occurs
                    if (buy != null &&
                        sell != null &&
                        buy.Target >= sell.Target)
                    {
                        GovControls gov = await context.GovControls.AsQueryable().FirstAsync();

                        int remainder = buy.Amount - sell.Amount;

                        decimal beforePrice = def.Current_Value;

                        decimal tradePrice = buy.Target;

                        int tradeAmount = Math.Min(buy.Amount, sell.Amount);

                        string buyer  = buy.Owner_Id;
                        string seller = sell.Owner_Id;

                        string buyId  = buy.Id;
                        string sellId = sell.Id;

                        // If remainder is 0, they cancel out perfectly
                        // If remainder > 0, the buy order is not finished and sell is deleted
                        // If remainder < 0, the sell order is not finished and the buy is deleted
                        if (remainder == 0)
                        {
                            context.StockOffers.Remove(sell);
                            context.StockOffers.Remove(buy);
                        }
                        else if (remainder > 0)
                        {
                            context.StockOffers.Remove(sell);
                            buy.Amount = buy.Amount - sell.Amount;
                            context.StockOffers.Update(buy);
                        }
                        else
                        {
                            context.StockOffers.Remove(buy);
                            sell.Amount = sell.Amount - buy.Amount;
                            context.StockOffers.Update(sell);
                        }

                        // Volume stuff
                        if (VolumesMinute.ContainsKey(def.Ticker))
                        {
                            VolumesMinute[def.Ticker] += tradeAmount;
                            VolumesHour[def.Ticker]   += tradeAmount;
                            VolumesDay[def.Ticker]    += tradeAmount;
                        }
                        else
                        {
                            VolumesMinute.Add(def.Ticker, tradeAmount);
                            VolumesHour.Add(def.Ticker, tradeAmount);
                            VolumesDay.Add(def.Ticker, tradeAmount);
                        }
                        // End volume stuff

                        decimal totalTrade = tradeAmount * tradePrice;
                        decimal tax        = totalTrade * (gov.CapitalGainsTaxRate / 100);

                        await new TransactionRequest(EconomyManager.VooperiaID, sell.Owner_Id, totalTrade - tax, $"Stock sale: {tradeAmount} {def.Ticker}@¢{tradePrice.Round()}", ApplicableTax.None, true).Execute();
                        gov.CapitalGainsTaxRevenue += tax;
                        gov.UBIAccount             += (tax * (gov.UBIBudgetPercent / 100.0m));

                        context.GovControls.Update(gov);

                        await context.SaveChangesAsync();

                        await AddStock(def.Ticker, tradeAmount, buyer, context);

                        Console.WriteLine($"Processed Stock sale: {tradeAmount} {def.Ticker}@¢{tradePrice.Round()}");

                        decimal trueValue = 0.0m;

                        StockOffer nextBuy = await GetHighestBuyOffer(def.Ticker, context);

                        StockOffer nextSell = await GetLowestSellOffer(def.Ticker, context);

                        if (nextBuy == null && nextSell == null)
                        {
                            trueValue = tradePrice;
                        }
                        else if (nextBuy == null)
                        {
                            trueValue = nextSell.Target;
                        }
                        else if (nextSell == null)
                        {
                            trueValue = nextBuy.Target;
                        }
                        else
                        {
                            trueValue = (nextBuy.Target + nextSell.Target) / 2;
                        }

                        StockTradeModel noti = new StockTradeModel()
                        {
                            Ticker     = def.Ticker,
                            Amount     = tradeAmount,
                            Price      = tradePrice,
                            True_Price = trueValue,
                            From       = sell.Owner_Id,
                            To         = buy.Owner_Id,
                            Buy_Id     = buyId,
                            Sell_Id    = sellId
                        };

                        def.Current_Value = noti.True_Price;
                        context.StockDefinitions.Update(def);

                        Entity sellAccount = await Entity.FindAsync(seller);

                        sellAccount.Credits_Invested -= totalTrade;
                        if (sellAccount is User)
                        {
                            context.Users.Update((User)sellAccount);
                        }
                        else if (sellAccount is Group)
                        {
                            context.Groups.Update((Group)sellAccount);
                        }


                        Entity buyAccount = await Entity.FindAsync(buyer);

                        buyAccount.Credits_Invested += totalTrade;
                        if (buyAccount is User)
                        {
                            context.Users.Update((User)buyAccount);
                        }
                        else if (buyAccount is Group)
                        {
                            context.Groups.Update((Group)buyAccount);
                        }

                        await context.SaveChangesAsync();

                        await ExchangeHub.Current.Clients.All.SendAsync("StockTrade", JsonConvert.SerializeObject(noti));

                        if (trueValue < beforePrice)
                        {
                            VoopAI.ecoChannel.SendMessageAsync($":chart_with_downwards_trend: ({def.Ticker}) Trade: {tradeAmount}@{buy.Target}, price drop to ¢{trueValue.Round()}");
                        }
                        else if (trueValue > beforePrice)
                        {
                            VoopAI.ecoChannel.SendMessageAsync($":chart_with_upwards_trend: ({def.Ticker}) Trade: {tradeAmount}@{buy.Target}, price increase to ¢{trueValue.Round()}");
                        }
                    }

                    // Otherwise move on to the next stock
                }
            }
        }
コード例 #3
0
        public async void UpdateRanks()
        {
            Console.WriteLine("Doing rank job");

            using (VooperContext context = new VooperContext(DBOptions))
            {
                Group government = context.Groups.AsQueryable().FirstOrDefault(x => x.Name == "Vooperia");

                if (government == null)
                {
                    Console.WriteLine("Holy f**k something is wrong.");
                }

                leaderboard = context.Users.AsEnumerable().Where(u => u.Email != u.UserName).OrderByDescending(u => u.GetTotalXP()).ToList();

                List <SocketGuildUser> userList = new List <SocketGuildUser>();

                // Add connected users
                foreach (User userData in leaderboard)
                {
                    SocketGuildUser user = null;

                    if (userData.discord_id != null)
                    {
                        //user = server.Users.FirstOrDefault(x => x.Id == (ulong)userData.discord_id);
                        user = server.GetUser((ulong)userData.discord_id);
                    }

                    if (user != null)
                    {
                        // Clear roles if muted
                        if (userData.GetDiscordRoles().Any(r => r.Name == "Muted"))
                        {
                            if (user.Roles.Contains(spleenRole))
                            {
                                await user.RemoveRoleAsync(spleenRole);
                            }
                            if (user.Roles.Contains(crabRole))
                            {
                                await user.RemoveRoleAsync(crabRole);
                            }
                            if (user.Roles.Contains(gatyRole))
                            {
                                await user.RemoveRoleAsync(gatyRole);
                            }
                            if (user.Roles.Contains(corgiRole))
                            {
                                await user.RemoveRoleAsync(corgiRole);
                            }
                            if (user.Roles.Contains(oofRole))
                            {
                                await user.RemoveRoleAsync(oofRole);
                            }
                        }
                        else
                        {
                            userList.Add(user);
                        }
                    }
                }

                int counter = 0;

                int totalUsers = userList.Count;


                GovControls govControls = await GovControls.GetCurrentAsync(context);

                decimal UBITotal = govControls.UBIAccount;
                govControls.UBIAccount = 0;

                context.GovControls.Update(govControls);
                await context.SaveChangesAsync();


                int spleenUserCount = totalUsers / 100;
                int crabUserCount   = (totalUsers / 20) - spleenUserCount;
                int gatyUserCount   = (totalUsers / 10) - spleenUserCount - crabUserCount;
                int corgiUserCount  = (totalUsers / 4) - spleenUserCount - crabUserCount - gatyUserCount;
                int oofUserCount    = (totalUsers / 2) - spleenUserCount - crabUserCount - gatyUserCount - corgiUserCount;

                int unrankedCount = totalUsers - spleenUserCount - crabUserCount - gatyUserCount - corgiUserCount - oofUserCount;

                decimal spleenPay   = 0.0m;
                decimal crabPay     = 0.0m;
                decimal gatyPay     = 0.0m;
                decimal corgiPay    = 0.0m;
                decimal oofPay      = 0.0m;
                decimal unrankedPay = 0.0m;

                if (spleenUserCount > 0)
                {
                    spleenPay = (UBITotal * (govControls.SpleenPayPercent / 100.0m)) / spleenUserCount;
                }
                if (crabUserCount > 0)
                {
                    crabPay = (UBITotal * (govControls.CrabPayPercent / 100.0m)) / crabUserCount;
                }
                if (gatyUserCount > 0)
                {
                    gatyPay = (UBITotal * (govControls.GatyPayPercent / 100.0m)) / gatyUserCount;
                }
                if (corgiUserCount > 0)
                {
                    corgiPay = (UBITotal * (govControls.CorgiPayPercent / 100.0m)) / corgiUserCount;
                }
                if (oofUserCount > 0)
                {
                    oofPay = (UBITotal * (govControls.OofPayPercent / 100.0m)) / oofUserCount;
                }
                if (unrankedCount > 0)
                {
                    unrankedPay = (UBITotal * (govControls.UnrankedPayPercent / 100.0m)) / unrankedCount;
                }

                foreach (SocketGuildUser discordUser in userList)
                {
                    User webUser = context.Users.FirstOrDefault(u => u.discord_id == discordUser.Id);

                    // Update pfp in storage
                    webUser.Image_Url = webUser.GetPfpUrl();
                    context.Update(webUser);
                    await context.SaveChangesAsync();

                    bool hasSpleen = discordUser.Roles.Contains(spleenRole);
                    bool hasCrab   = discordUser.Roles.Contains(crabRole);
                    bool hasGaty   = discordUser.Roles.Contains(gatyRole);
                    bool hasCorgi  = discordUser.Roles.Contains(corgiRole);
                    bool hasOof    = discordUser.Roles.Contains(oofRole);

                    bool hasCitizen  = discordUser.Roles.Contains(patreonCitizen) || discordUser.Roles.Contains(youtubeCitizen);
                    bool hasSoldier  = discordUser.Roles.Contains(patreonSoldier);
                    bool hasLoyalist = discordUser.Roles.Contains(patreonLoyalist);
                    bool hasHero     = discordUser.Roles.Contains(patreonHero);
                    bool hasMadlad   = discordUser.Roles.Contains(patreonMadlad);

                    bool patron = hasCitizen || hasSoldier || hasLoyalist || hasHero || hasMadlad;

                    // Inactivity tax
                    if (Math.Abs(webUser.Discord_Last_Message_Time.Subtract(DateTime.UtcNow).TotalDays) > 14 && !patron)
                    {
                        decimal tax = webUser.Credits * (govControls.InactivityTaxRate / 100.0M);

                        TransactionRequest req = new TransactionRequest(webUser.Id, EconomyManager.VooperiaID, tax, "Inactivity Tax", ApplicableTax.None, true);

                        TaskResult result = await req.Execute();

                        if (result.Succeeded)
                        {
                            govControls.InactivityTaxRevenue += tax;

                            // Add to UBI
                            govControls.UBIAccount += tax * (govControls.UBIBudgetPercent / 100.0M);

                            context.GovControls.Update(govControls);

                            await context.SaveChangesAsync();
                        }

                        // Remove last role
                        if (hasSpleen)
                        {
                            await discordUser.RemoveRoleAsync(spleenRole);
                        }
                        if (hasCrab)
                        {
                            await discordUser.RemoveRoleAsync(crabRole);
                        }
                        if (hasGaty)
                        {
                            await discordUser.RemoveRoleAsync(gatyRole);
                        }
                        if (hasCorgi)
                        {
                            await discordUser.RemoveRoleAsync(corgiRole);
                        }
                        if (hasOof)
                        {
                            await discordUser.RemoveRoleAsync(oofRole);
                        }

                        continue;
                    }

                    // Set district
                    if (!String.IsNullOrWhiteSpace(webUser.district))
                    {
                        var oldDistrictRoles = discordUser.Roles.Where(x => x.Name.Contains("District") && !x.Name.Contains(webUser.district));

                        if (oldDistrictRoles.Count() > 0)
                        {
                            await discordUser.RemoveRolesAsync(oldDistrictRoles);
                        }

                        if (!discordUser.Roles.Any(x => x.Name == webUser.district + " District"))
                        {
                            await discordUser.AddRoleAsync(districtRoles[webUser.district + " District"]);
                        }
                    }

                    // Spleen rank
                    if (counter <= spleenUserCount)
                    {
                        // Add new role
                        if (!hasSpleen)
                        {
                            await discordUser.AddRoleAsync(spleenRole);
                        }

                        // Remove last role
                        if (hasCrab)
                        {
                            await discordUser.RemoveRoleAsync(crabRole);
                        }
                        if (hasGaty)
                        {
                            await discordUser.RemoveRoleAsync(gatyRole);
                        }
                        if (hasCorgi)
                        {
                            await discordUser.RemoveRoleAsync(corgiRole);
                        }
                        if (hasOof)
                        {
                            await discordUser.RemoveRoleAsync(oofRole);
                        }

                        if (webUser != null)
                        {
                            //TransactionRequest transaction = new TransactionRequest(webUser.economy_id, government.economy_id, 238827, "UBI Mistake Fix", ApplicableTax.None, true);
                            TransactionRequest transaction = new TransactionRequest(government.Id, webUser.Id, spleenPay, "UBI Payment", ApplicableTax.None, true);
                            EconomyManager.RequestTransaction(transaction);
                        }
                    }
                    // Crab rank
                    else if (counter <= spleenUserCount + crabUserCount)
                    {
                        // Add new role
                        if (!hasCrab)
                        {
                            await discordUser.AddRoleAsync(crabRole);
                        }

                        // Remove last role
                        if (hasSpleen)
                        {
                            await discordUser.RemoveRoleAsync(spleenRole);
                        }
                        if (hasGaty)
                        {
                            await discordUser.RemoveRoleAsync(gatyRole);
                        }
                        if (hasCorgi)
                        {
                            await discordUser.RemoveRoleAsync(corgiRole);
                        }
                        if (hasOof)
                        {
                            await discordUser.RemoveRoleAsync(oofRole);
                        }

                        if (webUser != null)
                        {
                            //TransactionRequest transaction = new TransactionRequest(webUser.economy_id, government.economy_id, 146267, "UBI Mistake Fix", ApplicableTax.None, true);
                            TransactionRequest transaction = new TransactionRequest(government.Id, webUser.Id, crabPay, "UBI Payment", ApplicableTax.None, true);
                            EconomyManager.RequestTransaction(transaction);
                        }
                    }
                    // Gaty rank
                    else if (counter <= spleenUserCount + crabUserCount + gatyUserCount)
                    {
                        // Add new role
                        if (!hasGaty)
                        {
                            await discordUser.AddRoleAsync(gatyRole);
                        }

                        // Remove last role
                        if (hasSpleen)
                        {
                            await discordUser.RemoveRoleAsync(spleenRole);
                        }
                        if (hasCrab)
                        {
                            await discordUser.RemoveRoleAsync(crabRole);
                        }
                        if (hasCorgi)
                        {
                            await discordUser.RemoveRoleAsync(corgiRole);
                        }
                        if (hasOof)
                        {
                            await discordUser.RemoveRoleAsync(oofRole);
                        }

                        if (webUser != null)
                        {
                            //TransactionRequest transaction = new TransactionRequest(webUser.economy_id, government.economy_id, 125698, "UBI Mistake Fix", ApplicableTax.None, true);
                            TransactionRequest transaction = new TransactionRequest(government.Id, webUser.Id, gatyPay, "UBI Payment", ApplicableTax.None, true);
                            EconomyManager.RequestTransaction(transaction);
                        }
                    }
                    // Corgi rank
                    else if (counter <= spleenUserCount + crabUserCount + gatyUserCount + corgiUserCount)
                    {
                        // Add new role
                        if (!hasCorgi)
                        {
                            await discordUser.AddRoleAsync(corgiRole);
                        }

                        // Remove last role
                        if (hasSpleen)
                        {
                            await discordUser.RemoveRoleAsync(spleenRole);
                        }
                        if (hasCrab)
                        {
                            await discordUser.RemoveRoleAsync(crabRole);
                        }
                        if (hasGaty)
                        {
                            await discordUser.RemoveRoleAsync(gatyRole);
                        }
                        if (hasOof)
                        {
                            await discordUser.RemoveRoleAsync(oofRole);
                        }

                        if (webUser != null)
                        {
                            //TransactionRequest transaction = new TransactionRequest(webUser.economy_id, government.economy_id, 110369, "UBI Mistake Fix", ApplicableTax.None, true);
                            TransactionRequest transaction = new TransactionRequest(government.Id, webUser.Id, corgiPay, "UBI Payment", ApplicableTax.None, true);
                            EconomyManager.RequestTransaction(transaction);
                        }
                    }
                    // Oof rank
                    else if (counter <= spleenUserCount + crabUserCount + gatyUserCount + corgiUserCount + oofUserCount)
                    {
                        // Add new role
                        if (!hasOof)
                        {
                            await discordUser.AddRoleAsync(oofRole);
                        }

                        // Remove last role
                        if (hasSpleen)
                        {
                            await discordUser.RemoveRoleAsync(spleenRole);
                        }
                        if (hasCrab)
                        {
                            await discordUser.RemoveRoleAsync(crabRole);
                        }
                        if (hasGaty)
                        {
                            await discordUser.RemoveRoleAsync(gatyRole);
                        }
                        if (hasCorgi)
                        {
                            await discordUser.RemoveRoleAsync(corgiRole);
                        }

                        if (webUser != null)
                        {
                            //TransactionRequest transaction = new TransactionRequest(webUser.economy_id, government.economy_id, 91085, "UBI Mistake Fix", ApplicableTax.None, true);
                            TransactionRequest transaction = new TransactionRequest(government.Id, webUser.Id, oofPay, "UBI Payment", ApplicableTax.None, true);
                            EconomyManager.RequestTransaction(transaction);
                        }
                    }
                    // Unranked
                    else
                    {
                        // Remove last role
                        if (hasSpleen)
                        {
                            await discordUser.RemoveRoleAsync(spleenRole);
                        }
                        if (hasCrab)
                        {
                            await discordUser.RemoveRoleAsync(crabRole);
                        }
                        if (hasGaty)
                        {
                            await discordUser.RemoveRoleAsync(gatyRole);
                        }
                        if (hasCorgi)
                        {
                            await discordUser.RemoveRoleAsync(corgiRole);
                        }
                        if (hasOof)
                        {
                            await discordUser.RemoveRoleAsync(oofRole);
                        }

                        if (webUser != null)
                        {
                            //TransactionRequest transaction = new TransactionRequest(webUser.economy_id, government.economy_id, 125698, "UBI Mistake Fix", ApplicableTax.None, true);
                            TransactionRequest transaction = new TransactionRequest(government.Id, webUser.Id, unrankedPay, "UBI Payment", ApplicableTax.None, true);
                            EconomyManager.RequestTransaction(transaction);
                        }
                    }

                    if (patron)
                    {
                        webUser = await context.Users.FindAsync(webUser.Id);

                        if (hasMadlad)
                        {
                            webUser.Credits += 500;
                        }
                        else if (hasHero)
                        {
                            webUser.Credits += 350;
                        }
                        else if (hasLoyalist)
                        {
                            webUser.Credits += 175;
                        }
                        else if (hasSoldier)
                        {
                            webUser.Credits += 60;
                        }
                        else if (hasCitizen)
                        {
                            webUser.Credits += 20;
                        }

                        context.Update(webUser);
                        await context.SaveChangesAsync();
                    }

                    counter++;
                }
            }


            Console.WriteLine("Finished rank system");
        }