summaryrefslogtreecommitdiff
path: root/Assets/Scripts
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/Scripts')
-rw-r--r--Assets/Scripts/Tag/TaggedItemSelector.cs152
1 files changed, 151 insertions, 1 deletions
diff --git a/Assets/Scripts/Tag/TaggedItemSelector.cs b/Assets/Scripts/Tag/TaggedItemSelector.cs
index 87a563e..0179bf4 100644
--- a/Assets/Scripts/Tag/TaggedItemSelector.cs
+++ b/Assets/Scripts/Tag/TaggedItemSelector.cs
@@ -1,9 +1,159 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
using UnityEngine;
namespace Tag
{
public class TaggedItemSelector : MonoBehaviour
{
+ public List<TaggedItemInfo> infos;
+ public TagPool pool;
+ public int minEyeCount = 3;
+ public int minElbowCount = 3;
+ public int minNorseCount = 2;
+ public int minMouseCount = 2;
+ public int minAccessoriesCount = 4;
+
+ private void Start()
+ {
+ }
+
+ public List<TaggedItemInfo> FilterByQuestion(Question question)
+ {
+ // 1. 先按类型分组
+ var groupedByType = infos.GroupBy(info => info.itemType)
+ .ToDictionary(g => g.Key, g => g.ToList());
+
+ // 2. 计算每种类型需要的最小数量
+ var minCounts = new Dictionary<ItemType, int>
+ {
+ { ItemType.Eye, minEyeCount },
+ { ItemType.Elbow, minElbowCount },
+ { ItemType.Norse, minNorseCount },
+ { ItemType.Mouse, minMouseCount },
+ { ItemType.Accessories, minAccessoriesCount }
+ };
+
+ // 3. 先收集Need中每个tag需要的数量
+ var tagRequirements = new Dictionary<string, int>();
+ foreach (var tag in question.Need)
+ {
+ if (tagRequirements.ContainsKey(tag))
+ tagRequirements[tag]++;
+ else
+ tagRequirements[tag] = 1;
+ }
+
+ // 4. 筛选结果列表
+ var result = new List<TaggedItemInfo>();
+ var usedItems = new HashSet<TaggedItemInfo>();
+
+ // 5. 先满足Need中的tag要求
+ foreach (var tagRequirement in tagRequirements)
+ {
+ var tag = tagRequirement.Key;
+ var requiredCount = tagRequirement.Value;
+ var foundCount = 0;
+
+ // 遍历所有未使用的物品,查找包含该tag的物品
+ var availableItems = infos.Where(info =>
+ !usedItems.Contains(info) &&
+ info.tags.Contains(tag))
+ .ToList();
+
+ // 按照类型优先级排序,确保每个类型都有机会被选中
+ availableItems = availableItems.OrderBy(item =>
+ {
+ var typeCount = result.Count(i => i.itemType == item.itemType);
+ var minForType = minCounts[item.itemType];
+ return typeCount >= minForType ? 1 : 0; // 优先选择未达到最小数量的类型
+ }).ThenBy(item => item.itemType)
+ .ToList();
+
+ // 选取所需数量的物品
+ for (int i = 0; i < Mathf.Min(availableItems.Count, requiredCount); i++)
+ {
+ var item = availableItems[i];
+ result.Add(item);
+ usedItems.Add(item);
+ foundCount++;
+ }
+
+ // 如果没有找到足够的物品,尝试从已满足其他tag的物品中寻找
+ if (foundCount < requiredCount)
+ {
+ var additionalItems = result.Where(item =>
+ item.tags.Contains(tag) &&
+ result.Count(i => i == item) == 1) // 确保不重复计数
+ .ToList();
+
+ // 如果一个物品有多个需要的tag,它可以被计数多次
+ // 但在这个实现中,我们保持简单,每个物品只计算一次
+ }
+ }
+
+ // 6. 确保每个类型达到最小数量
+ foreach (var typeGroup in result.GroupBy(item => item.itemType))
+ {
+ var type = typeGroup.Key;
+ var currentCount = typeGroup.Count();
+ var minRequired = minCounts[type];
+
+ if (currentCount < minRequired)
+ {
+ // 从该类型的未使用物品中补充
+ var typeItems = groupedByType.ContainsKey(type) ?
+ groupedByType[type] : new List<TaggedItemInfo>();
+
+ var unusedItemsOfType = typeItems
+ .Where(item => !usedItems.Contains(item))
+ .Take(minRequired - currentCount)
+ .ToList();
+
+ foreach (var item in unusedItemsOfType)
+ {
+ result.Add(item);
+ usedItems.Add(item);
+ }
+ }
+ }
+
+ // 7. 处理NoNeed:移除含有NoNeed标签的物品
+ if (question.NoNeed != null && question.NoNeed.Any())
+ {
+ result = result.Where(item =>
+ !item.tags.Any(tag => question.NoNeed.Contains(tag)))
+ .ToList();
+ }
+
+ // 8. 如果某个类型的最小数量仍然不满足,尝试用其他物品替换
+ foreach (var type in Enum.GetValues(typeof(ItemType)).Cast<ItemType>())
+ {
+ var currentCount = result.Count(item => item.itemType == type);
+ var minRequired = minCounts[type];
+
+ if (currentCount < minRequired)
+ {
+ // 尝试从该类型的未使用物品中获取更多
+ var typeItems = groupedByType.ContainsKey(type) ?
+ groupedByType[type] : new List<TaggedItemInfo>();
+
+ var unusedItemsOfType = typeItems
+ .Where(item => !usedItems.Contains(item))
+ .Take(minRequired - currentCount)
+ .ToList();
+
+ foreach (var item in unusedItemsOfType)
+ {
+ result.Add(item);
+ usedItems.Add(item);
+ }
+ }
+ }
+
+ return result;
+ }
}
-}
+} \ No newline at end of file