public static List <IItem> AvailableToBuy(this ItemManager manager, StructFlag <BuyGroup> filter) { return(manager.Keys() .Select(manager.Get) .Where(item => item?.Price != null && item.Group.Intersects(filter)) .ToList()); }
public void CompareDifferentProperties() { // Bigger by health, smaller by mana, equal by intelligence var a = new StatsEffect(ChangeType.Add, new Dictionary <StatsProperty, decimal> { { StatsProperty.Health, 5 }, { StatsProperty.Mana, 3 }, { StatsProperty.Intelligence, 1 } }); // Smaller by health, bigger by mana, equal by intelligence var b = new StatsEffect(ChangeType.Add, new Dictionary <StatsProperty, decimal> { { StatsProperty.Health, 3 }, { StatsProperty.Mana, 5 }, { StatsProperty.Intelligence, 1 } }); var health = new StructFlag <StatsProperty>(StatsProperty.Health); Assert.Equal(-1, StatsEffect.Compare(health, a, b)); var mana = new StructFlag <StatsProperty>(StatsProperty.Mana); Assert.Equal(1, StatsEffect.Compare(mana, a, b)); var intelligence = new StructFlag <StatsProperty>(StatsProperty.Intelligence); Assert.Equal(0, StatsEffect.Compare(intelligence, a, b)); }
private void Shop(User user, ReceivedMessage message) { var items = GetAllItems(); var flag = new StructFlag <BuyGroup>(BuyGroup.Merchant, BuyGroup.Market); var available = items.Keys() .Select(id => items.Get(id)) .Where(item => item?.Price != null && item.Group.Intersects(flag)) .ToArray(); foreach (var item in available) { SendMessage(user, $"<b>{item.Name}</b> (x{ItemCount}) [{item.Price * ItemCount}]\n{item.Description}"); } SendMessage( user, "— За звонкую монету можно приобрести все, что угодно!", available .Select(item => new[] { item.Name }) .Concat(new[] { new[] { "Ничего" } }) .ToArray() ); SwitchAction(user, Shop2); }
private static IReadOnlyDictionary <StructFlag <StatsProperty>, MustBeOrderedList <ItemInfo> > GroupByStats( IEnumerable <ItemInfo> items) { var result = new Dictionary <StructFlag <StatsProperty>, List <ItemInfo> >(); foreach (var item in items) { var combined = new StructFlag <StatsProperty>(); Debug.Assert(item.Item.Effect != null, "item.Item.Effect != null"); foreach (var effectKey in item.Item.Effect.Effect.Keys) { combined = new StructFlag <StatsProperty>(combined.Values.Add(effectKey)); } if (result.TryGetValue(combined, out var list)) { list.Add(item); } else { result[combined] = new List <ItemInfo> { item }; } } return(result.ToDictionary( kv => kv.Key, kv => new MustBeOrderedList <ItemInfo>(kv.Value .OrderBy(i => i.Item.Effect, StatsEffect.CreateComparer(kv.Key))) )); }
public void CompareDifferent() { var props = new StructFlag <StatsProperty>(StatsProperty.Health); var comparer = StatsEffect.CreateComparer(props); // Bigger var a = new StatsEffect(ChangeType.Add, new Dictionary <StatsProperty, decimal> { { StatsProperty.Health, 5 } }); // Smaller var b = new StatsEffect(ChangeType.Add, new Dictionary <StatsProperty, decimal> { { StatsProperty.Health, 3 } }); // Bigger first Assert.Equal(-1, comparer.Compare(a, b)); Assert.Equal(-1, StatsEffect.Compare(props, a, b)); // Smaller first Assert.Equal(1, comparer.Compare(b, a)); Assert.Equal(1, StatsEffect.Compare(props, b, a)); }
private void EditStats(User user, RecivedMessage message) { var splitted = message.Text.Split(' '); if (splitted[0] == "Закончить") { SwitchAction(user, null); SendMessage(user, "Тебе надоело рыться в карманах", GetButtons(user)); return; } // Handle change var reverse = Stats.Emojis.ToDictionary(kv => kv.Value, kv => kv.Key); var changed = false; var flag = new StructFlag <StatsProperty>(); foreach (var propEmoji in splitted[0].Split(',')) { if (reverse.TryGetValue(propEmoji, out var prop)) { flag |= new StructFlag <StatsProperty>(prop); } } var count = 0; if (!flag.Values.IsEmpty && int.TryParse(splitted[1], out count)) { user.ActiveItemsManager.ChangeProportion(flag, count); changed = true; } // Show current stats ShowStats(user); // Show current proportions var current = new StringBuilder().AppendLine("Текущее распределение:"); foreach (var proportion in user.ActiveItemsManager.ActiveProportions) { var emoji = string.Join(",", proportion.Key.Values.Select(k => Stats.Emojis[k])); current.Append(emoji).Append(": ").Append(proportion.Value); if (changed && flag.Equals(proportion.Key)) { current.Append($" _({count:+#.##;-#.##;0})_"); } current.AppendLine(); } SendMessage(user, current.ToString(), EditButtons(user)); // Show how many available var used = user.ActiveItemsManager.ActiveProportions.Select(kv => kv.Value).Sum(); var total = user.ActiveItemsManager.ActiveLimit; SendMessage(user, $"Распределено {used} из {total}. Доступно {total - used} активных предметов"); }
public static int Compare(StructFlag<StatsProperty> props, StatsEffect self, StatsEffect other) { var result = 0m; foreach (var property in props.Values) { result += other.Effect.GetValueOrDefault(property) - self.Effect.GetValueOrDefault(property); } return Math.Sign(result); }
private bool DetectUseSet(StructFlag <StatsProperty> prop, IDictionary <ChangeType, MustBeOrderedList <ItemInfo> > items) { if (items.TryGetValue(ChangeType.Set, out var setItems)) { // Returns is best "set" item better than BaseStats return(StatsEffect.Compare(prop, User.Info.BaseStats, TakeBest(1, setItems).First().Item.Effect) == 1); } return(false); }
public void CompareSame() { var props = new StructFlag <StatsProperty>(StatsProperty.Health); var comparer = StatsEffect.CreateComparer(props); var a = new StatsEffect(ChangeType.Add, new Dictionary <StatsProperty, decimal> { { StatsProperty.Health, 5 } }); var b = new StatsEffect(ChangeType.Add, new Dictionary <StatsProperty, decimal> { { StatsProperty.Health, 5 } }); Assert.Equal(0, comparer.Compare(a, b)); Assert.Equal(0, StatsEffect.Compare(props, a, b)); }
public void ChangeProportion(StructFlag <StatsProperty> property, int count) { var currentSum = ActiveProportions.Values.Sum(); var available = ActiveLimit - currentSum; var toAdd = Math.Min(count, available); // User cannot add more items than ActiveLimit var currentValue = ActiveProportions.GetValueOrDefault(property); var newValue = currentValue + toAdd; if (newValue <= 0) { Proportions.Remove(property); } else { Proportions[property] = newValue; } RecalculateActive(); }
public static List <ItemInfo> AvailableToSell(this IEnumerable <ItemInfo> items, StructFlag <BuyGroup> filter) { return(items .Where(item => item.Item.Price != null && item.Item.Group.Intersects(filter)) .ToList()); }
public static IComparer<StatsEffect> CreateComparer(StructFlag<StatsProperty> props) { return Comparer<StatsEffect>.Create((a, b) => Compare(props, a, b)); }
private List <ItemInfo> ActivateItems(StructFlag <StatsProperty> prop, MustBeOrderedList <ItemInfo> items) { if (!ActiveProportions.TryGetValue(prop, out var limit)) { return(new List <ItemInfo>()); } var groups = GroupByChangeType(items); var useSet = DetectUseSet(prop, groups); var max = limit; if (useSet) { max--; } var selectedItems = new List <ItemInfo>(); if (useSet) { selectedItems.AddRange(TakeBest(1, groups[ChangeType.Set])); } if (!groups.ContainsKey(ChangeType.Add) && !groups.ContainsKey(ChangeType.Multiply)) { // No multiplication and addition. Only set, maybe. // So just do nothing, because DetectUseSet() will handle set. return(selectedItems); } if (!groups.ContainsKey(ChangeType.Add)) { // Only multiplication (and set, maybe) selectedItems.AddRange(TakeBest(max, groups[ChangeType.Multiply])); return(selectedItems); } if (!groups.ContainsKey(ChangeType.Multiply)) { // Only addition (and set, maybe) selectedItems.AddRange(TakeBest(max, groups[ChangeType.Add])); return(selectedItems); } // Both multiplication and addition (and set, maybe) /* * Наилучшая комбинация будет если сначала складывать, а потом умножать, т.к. (x + a) * b > (x * b) + a * Этот алгоритм сначала пробует взять максимальное количество умножения, * потом в каждой итерации добавляет одно сложение. В конце концов пробует только сложения. * Работает за O(N^2), где N -- max (ActiveProportions[prop]) */ var selectedItemsBase = selectedItems.ToList(); var bestStats = User.Info.BaseStats; var bestItems = new List <ItemInfo>(); for (var addCount = 0; addCount < max; addCount++) { selectedItems = selectedItemsBase.ToList(); var mulCount = max - addCount; selectedItems.AddRange(TakeBest(addCount, groups[ChangeType.Add])); selectedItems.AddRange(TakeBest(mulCount, groups[ChangeType.Multiply])); var currentStats = UserInfo.ApplyItems(User.Info.BaseStats, selectedItems); if (StatsEffect.Compare(prop, bestStats, currentStats) == 1) { bestStats = currentStats; bestItems = selectedItems.ToList(); } } return(bestItems); }