/// <summary> /// Tell the flipper that an auction was sold /// </summary> /// <param name="auction"></param> public void AuctionSold(SaveAuction auction) { if (!FlipIdLookup.ContainsKey(auction.UId)) { return; } SoldAuctions[auction.UId] = auction.End; var auctionUUid = auction.Uuid; NotifySubsInactiveAuction(auctionUUid); }
private bool GetAuctionToCheckFlipability(out SaveAuction auction) { // mix in lowerPrice if (_auctionCounter++ % 3 != 0) { if (PotetialFlipps.TryDequeue(out auction)) { return(true); } } return(LowPriceQueue.TryDequeue(out auction)); }
public async Task <(List <SaveAuction>, DateTime)> GetRelevantAuctions(SaveAuction auction, HypixelContext context) { var itemData = auction.NbtData.Data; var clearedName = auction.Reforge != ItemReferences.Reforge.None ? ItemReferences.RemoveReforge(auction.ItemName) : auction.ItemName; var itemId = ItemDetails.Instance.GetItemIdForName(auction.Tag, false); var youngest = DateTime.Now; var relevantEnchants = auction.Enchantments?.Where(e => UltimateEnchants.ContainsKey(e.Type) || e.Level >= 6).ToList(); var matchingCount = relevantEnchants.Count > 2 ? relevantEnchants.Count / 2 : relevantEnchants.Count; var ulti = relevantEnchants.Where(e => UltimateEnchants.ContainsKey(e.Type)).FirstOrDefault(); var highLvlEnchantList = relevantEnchants.Where(e => !UltimateEnchants.ContainsKey(e.Type)).Select(a => a.Type).ToList(); var oldest = DateTime.Now - TimeSpan.FromHours(1); IQueryable <SaveAuction> select = GetSelect(auction, context, clearedName, itemId, youngest, matchingCount, ulti, highLvlEnchantList, oldest, auction.Reforge, 10); var relevantAuctions = await select .ToListAsync(); if (relevantAuctions.Count < 9) { // to few auctions in last hour, try a whole day oldest = DateTime.Now - TimeSpan.FromDays(1.5); relevantAuctions = await GetSelect(auction, context, clearedName, itemId, youngest, matchingCount, ulti, highLvlEnchantList, oldest, auction.Reforge) .ToListAsync(); if (relevantAuctions.Count < 50 && PotetialFlipps.Count < 2000) { // to few auctions in a day, query a week oldest = DateTime.Now - TimeSpan.FromDays(8); relevantAuctions = await GetSelect(auction, context, clearedName, itemId, youngest, matchingCount, ulti, highLvlEnchantList, oldest, auction.Reforge, 120) .ToListAsync(); if (relevantAuctions.Count < 10 && clearedName.Contains("✪")) { clearedName = clearedName.Replace("✪", "").Trim(); relevantAuctions = await GetSelect(auction, context, clearedName, itemId, youngest, matchingCount, ulti, highLvlEnchantList, oldest, auction.Reforge, 120) .ToListAsync(); } } } /* got replaced with average overall lookup * if (relevantAuctions.Count < 3 && PotetialFlipps.Count < 100) * { * oldest = DateTime.Now - TimeSpan.FromDays(25); * relevantAuctions = await GetSelect(auction, context, null, itemId, youngest, matchingCount, ulti, ultiList, highLvlEnchantList, oldest) * .ToListAsync(); * } */ return(relevantAuctions, oldest); }
private static IQueryable <SaveAuction> AddPetLvlSelect(SaveAuction auction, IQueryable <SaveAuction> select) { var sb = new StringBuilder(auction.ItemName); if (sb[6] == ']') { sb[5] = '_'; } else { sb[6] = '_'; } select = select.Where(a => EF.Functions.Like(a.ItemName, sb.ToString())); return(select); }
public PreditionInput Map(SaveAuction auction, DateTime time) { return(new PreditionInput() { AnvilUses = auction.AnvilUses, Bin = auction.Bin, Category = auction.Category, End = time, HighestBid = auction.HighestBidAmount, ItemId = auction.ItemId, Rarity = (int)auction.Tier, Reforge = (int)auction.Reforge, Start = auction.Start, StartingBid = (int)auction.StartingBid, Enchantments = auction.Enchantments.Select(e => ((byte)e.Type, (int)e.Level)).ToList(), NbtData = auction.NBTLookup.Select(l => { if (KeysToInclude.TryGetValue(l.KeyId, out short mapped)) { return (mapped, l.Value); } return ((short)0, 0L); }).Where(el => el.Item1 != 0).ToList() });
private static IQueryable <SaveAuction> AddEnchantmentSubselect(SaveAuction auction, int matchingCount, List <Enchantment.EnchantmentType> highLvlEnchantList, IQueryable <SaveAuction> select, byte ultiLevel, Enchantment.EnchantmentType ultiType) { var maxImportantEnchants = highLvlEnchantList.Count() + 1 + (ultiType == Enchantment.EnchantmentType.unknown ? 0 : 1); if (matchingCount > 0) { select = select.Where(a => a.Enchantments .Where(e => (e.Level > 5 && highLvlEnchantList.Contains(e.Type) || e.Type == ultiType && e.Level == ultiLevel)).Count() >= matchingCount && a.Enchantments.Where(e => UltiEnchantList.Contains(e.Type) || e.Level > 5).Count() <= maxImportantEnchants); } else if (auction.Enchantments?.Count == 1) { select = select.Where(a => a.Enchantments != null && a.Enchantments.Any() && a.Enchantments.First().Type == auction.Enchantments.First().Type && a.Enchantments.First().Level == auction.Enchantments.First().Level); } else if (auction.Enchantments?.Count == 2) { select = select.Where(a => a.Enchantments != null && a.Enchantments.Count() == 2 && a.Enchantments.Where(e => e.Type == auction.Enchantments[0].Type && e.Level == auction.Enchantments[0].Level || e.Type == auction.Enchantments[1].Type && e.Level == auction.Enchantments[1].Level).Count() == 2); } // make sure we exclude special enchants to get a reasonable price else if (auction.Enchantments.Any()) { select = select.Where(a => !a.Enchantments.Where(e => UltiEnchantList.Contains(e.Type) || e.Level > 5).Any()); } else if (auction.Category == Category.WEAPON || auction.Category == Category.ARMOR) // || auction.Tag == "ENCHANTED_BOOK") { select = select.Where(a => !a.Enchantments.Any()); } return(select); }
private static IQueryable <SaveAuction> GetSelect( SaveAuction auction, HypixelContext context, string clearedName, int itemId, DateTime youngest, int matchingCount, Enchantment ulti, List <Enchantment.EnchantmentType> highLvlEnchantList, DateTime oldest, ItemReferences.Reforge reforge, int limit = 60) { var select = context.Auctions .Where(a => a.ItemId == itemId) .Where(a => a.HighestBidAmount > 0) .Where(a => a.Tier == auction.Tier); byte ultiLevel = 127; Enchantment.EnchantmentType ultiType = Enchantment.EnchantmentType.unknown; if (ulti != null) { ultiLevel = ulti.Level; ultiType = ulti.Type; } if (relevantReforges.Contains(reforge)) { select = select.Where(a => a.Reforge == reforge); } if (auction.ItemName != clearedName && clearedName != null) { select = select.Where(a => EF.Functions.Like(a.ItemName, "%" + clearedName)); } else if (auction.Tag.StartsWith("PET")) { select = AddPetLvlSelect(auction, select); } else { select = select.Where(a => a.ItemName == clearedName); } if (auction.Tag == "MIDAS_STAFF" || auction.Tag == "MIDAS_SWORD") { try { var val = (long)auction.NbtData.Data["winning_bid"]; var keyId = NBT.GetLookupKey(auction.Tag); select = select.Where(a => a.NBTLookup.Where(n => n.KeyId == keyId && n.Value > val - 2_000_000 && n.Value < val + 2_000_000).Any()); oldest -= TimeSpan.FromDays(10); } catch {} } select = AddEnchantmentSubselect(auction, matchingCount, highLvlEnchantList, select, ultiLevel, ultiType); if (limit == 0) { return(select); } return(select .Where(a => a.End > oldest && a.End < youngest) //.OrderByDescending(a=>a.Id) //.Include(a => a.NbtData) .Take(limit)); }
public async System.Threading.Tasks.Task NewAuction(SaveAuction auction, HypixelContext context) { if (!Program.Migrated) { if (auction.UId % 20 == 0) // don't spam the log { Console.WriteLine("not yet migrated skiping flip"); } return; } if (diabled && auction.UId % 5 != 0) { return; // don't run on full cap on my dev machine :D } var price = (auction.HighestBidAmount == 0 ? auction.StartingBid : (auction.HighestBidAmount * 1.1)) / auction.Count; // if(auction.Enchantments.Count == 0 && auction.Reforge == ItemReferences.Reforge.None) // Console.WriteLine("easy item"); var(relevantAuctions, oldest) = await GetRelevantAuctions(auction, context); long medianPrice = 0; if (relevantAuctions.Count < 2) { Console.WriteLine($"Could not find enough relevant auctions for {auction.ItemName} {auction.Uuid} ({auction.Enchantments.Count} {relevantAuctions.Count})"); var itemId = ItemDetails.Instance.GetItemIdForName(auction.Tag, false); medianPrice = (long)(await ItemPrices.GetLookupForToday(itemId)).Prices.Average(p => p.Avg * 0.8 + p.Min * 0.2); } else { medianPrice = relevantAuctions .OrderByDescending(a => a.HighestBidAmount) .Select(a => a.HighestBidAmount / a.Count) .Skip(relevantAuctions.Count / 2) .FirstOrDefault(); } var recomendedBuyUnder = medianPrice * 0.8; if (price > recomendedBuyUnder) // at least 20% profit { return; // not a good flip } relevantAuctionIds[auction.UId] = relevantAuctions.Select(a => a.UId == 0 ? AuctionService.Instance.GetId(a.Uuid) : a.UId).ToList(); if (relevantAuctionIds.Count > 10000) { relevantAuctionIds.Clear(); } var query = new ActiveItemSearchQuery() { Order = SortOrder.LOWEST_PRICE, Limit = 1, Filter = new Dictionary <string, string>() { { "Bin", "true" } }, name = auction.Tag }; var lowestBin = Server.ExecuteCommandWithCache <ActiveItemSearchQuery, List <ItemPrices.AuctionPreview> >("activeAuctions", query); var flip = new FlipInstance() { MedianPrice = (int)medianPrice, Name = auction.ItemName, Uuid = auction.Uuid, LastKnownCost = (int)price, Volume = (float)(relevantAuctions.Count / (DateTime.Now - oldest).TotalDays), Tag = auction.Tag, Bin = auction.Bin, UId = auction.UId, SellerName = await PlayerSearch.Instance.GetNameWithCacheAsync(auction.AuctioneerId), LowestBin = (await lowestBin).FirstOrDefault()?.Price }; FlippFound(flip); if (auction.Uuid[0] == 'a') // reduce saves { await CacheService.Instance.SaveInRedis(FoundFlippsKey, Flipps); } }