using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Xml.Serialization; using Unity.VisualScripting; using UnityEngine; using UnityEngine.Networking.Types; using UnityEngine.UI; using static System.Collections.Specialized.BitVector32; using static UnityEditor.Progress; public class EvacuationPanel : MonoBehaviour { public Dictionary distributePeople = new Dictionary();// 分配给各个场景的人数 public List personnelItems;//左侧区域 public Transform personnelContent; public Panel panel; public GameObject personnelPrefabs; public GameObject classPrefab; public GameObject classCount;// public GameObject scenePrefab;//区域预制体 public Transform sceneCount;//区域预制体的容器 public GameObject jueseChoicePanel; public Transform content; public Text topText; private GameObject selectedScene = null;//当前选中场景 public List classItemList = new List(); public List classMateList = new List(); [Header("学生数量")] public InputField StuCountInputField; public Button CountsubmitBtn; public Sprite rsprite; public Sprite fsprite; public GameObject JuesechoicePop; public JueseChoicePop jc = new JueseChoicePop(); public JSONReader js; [Header("总按钮")] public Button redistributeBtn; public Button submitBtn; [Header("Npc数量")] public int npcNum; [Header("Npc类型")] public string npcType; public string roleid; [Header("可分配列表")] List nonZeroAreas = new List(); Dictionary personnelItemsDict = new Dictionary();//储存分配结果 //private HashSet excludedAreas = new HashSet(); // 被清空的区域 ID public SelectScenePanel selectScene; private HashSet clearedAreas = new HashSet(); // 保存分配结果的字典 public Dictionary allocatedPeople = new Dictionary(); public List clearRegion=new List();//被清除的区域 // Start is called before the first frame update void Start() { SetNpcType(); nonZeroAreas= GetNonZeroNpcRatioAreas(); jc = JuesechoicePop.GetComponent(); //redistributeBtn.onClick.AddListener(ClearData); //redistributeBtn.onClick.AddListener(() => //{ // if (redistributeBtn.interactable) // { // Debug.Log("Redistribute button clicked!"); // RedistributeLogic(); // } //}); CountsubmitBtn.onClick.AddListener(Submit); submitBtn.onClick.AddListener(totalSubmit); StuCountInputField.onEndEdit.AddListener(CheckInput); SetClass(); } void Update() { CheckInput(StuCountInputField.text); IsRedistribution(); IsOpen(selectScene.difficultyId); } //上传数据 public void totalSubmit() { NpcList nPC = new NpcList(); nPC.npcId = npcType; nPC.areaId = roleid; createTemplateInfo.Instance.auth_CreateTemplate.npcList = new List(); createTemplateInfo.Instance.auth_CreateTemplate.npcList.Add(nPC); panel.panelToggle[3].interactable = true; // 启用第二个Toggle panel.panelToggle[3].gameObject.transform.GetComponent().sprite = panel.toggleImage[1]; panel.panelToggle[4].interactable = true; // 启用第三个Toggle panel.panelToggle[4].gameObject.transform.GetComponent().sprite = panel.toggleImage[1]; } //设置Npc类型 public void SetNpcType() { foreach (var scene in panel.sceneDataDictionary) { foreach (var npcData in js.locationDictionary) { // 解析角色限制字段 string roleLimit = npcData.Value.NpcRatio; if(npcData.Value.NpcRatio=="-1") { continue; } else { // 先按“,”分隔 string[] roleLimitSections = roleLimit.Split(','); if (scene.Key == npcData.Value.Note) { // 只有当 scene.Key 和 npcData.Value.Note 匹配时才执行 this.npcType = roleLimitSections[1]; roleid = roleLimitSections[0]; } } } } } //文字框提交按钮 public void Submit() { // 获取输入的总人数 int count = int.Parse(StuCountInputField.text); // 总人数 StuCountInputField.text = ""; // 使用分配方法 foreach (var item in personnelItems) { personnelItemsDict[item.sceneId] = item; // 使用 sceneId 作为键 } // 将 nonZeroAreas 转换为场景 ID 数组 int[] sceneIds = nonZeroAreas.ToArray(); // 调用分配方法 var result = DistributePeopleWithBalance(sceneIds, personnelItemsDict, count); // 保存并使用分配结果 allocatedPeople = result; // 更新 UI 显示 foreach (var kvp in result) { if (personnelItemsDict.ContainsKey(kvp.Key)) { personnelItemsDict[kvp.Key].SetInfo(kvp.Value.ToString()); // 更新UI personnelItemsDict[kvp.Key].NpcNum=kvp.Value; personnelItemsDict[kvp.Key].personnelImage.gameObject.SetActive(true); Debug.LogError(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+++++++++++++++++++Key" + kvp.Key); Debug.LogError(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+++++++++++++++++++Num" + kvp.Value); } } } //分配Npc public Dictionary DistributePeopleWithBalance(int[] scenes, Dictionary personnelItemsDict, int totalPeople) { // 1. 计算当前每个区域的总人数(初始人数 + 已分配人数) Dictionary totalPeoplePerScene = new Dictionary(); foreach (var scene in scenes) { // 如果 personnelItemsDict 中包含该场景,取其初始人数;否则设为 0 if (personnelItemsDict.ContainsKey(scene)) { totalPeoplePerScene[scene] = personnelItemsDict[scene].Num+personnelItemsDict[scene].NpcNum; // 初始人数 } else { totalPeoplePerScene[scene] = 0; } Debug.Log($"Scene {scene}: Initial People = {totalPeoplePerScene[scene]}"); } // 保存初始人数以便后续计算 Dictionary initialPeoplePerScene = new Dictionary(totalPeoplePerScene); // 2. 分配剩余人数 int remainingPeople = totalPeople; while (remainingPeople > 0) { // 找出当前人数最少的区域 int minScene = -1; // 用于记录人数最少的场景 ID int minPeople = int.MaxValue; foreach (var scene in totalPeoplePerScene) { if (scene.Value < minPeople) { minPeople = scene.Value; minScene = scene.Key; } } // 分配一个 NPC 到人数最少的区域 if (minScene != -1) // 确保找到有效的场景 { totalPeoplePerScene[minScene]++; remainingPeople--; } else { break; // 如果没有找到有效的场景,终止分配 } } // 3. 计算分配结果,减去初始人数 Dictionary allocatedPeople = new Dictionary(); foreach (var scene in totalPeoplePerScene) { int initialPeople = initialPeoplePerScene.GetValueOrDefault(scene.Key, 0); allocatedPeople[scene.Key] = scene.Value - initialPeople; // 分配人数 = 总人数 - 初始人数 } // 保存分配结果 this.allocatedPeople = allocatedPeople; return allocatedPeople; } //判断NPC的比例字段,列出分配比例不为0的所有区域名称。 public List GetNonZeroNpcRatioAreas() { List nonZeroAreas = new List(); foreach (var sceneEntry in panel.sceneDataDictionary) { foreach (var sceneInfo in sceneEntry.Value) { foreach (var npcData in js.locationDictionary) { LocationData locationData = npcData.Value; // 如果场景的 ID 匹配当前 NPC 的 ID if (locationData.ID == int.Parse(sceneInfo.sceneId)) { // 获取每个区域的 NpcRatio 字段 string npcRatio = locationData.NpcRatio; // 将 NpcRatio 字符串按 '|' 分割,获取每一项 string[] npcRatioEntries = npcRatio.Split('|'); // 遍历每一项 foreach (var entry in npcRatioEntries) { // 将每一项按 ',' 分割,获取事故位置、NPCID、归属和分配比例 string[] entryData = entry.Split(','); if (entryData.Length == 4) { string allocationRatio = entryData[3]; // 获取分配比例 // 检查分配比例是否不为 "0" 和 "-1" if (allocationRatio != "0" && allocationRatio != "-1") { // 如果比例不为0,将该区域 ID 添加到列表 nonZeroAreas.Add(locationData.ID); Debug.Log("locationData.ID"+ locationData.ID); break; // 一旦找到有效的分配比例,就不再检查当前区域的其他项 } } } } } } } // 输出所有分配比例不为0的区域 ID foreach (var area in nonZeroAreas) { Debug.Log("区域 ID:" + area); } // 返回符合条件的区域 ID 列表 return nonZeroAreas; } //设置左侧场景显示2.0 public void SetScene() { // 清空现有的UI项 foreach (Transform child in personnelContent) { Destroy(child.gameObject); } // 清空人员列表 personnelItems.Clear(); foreach (var item in js.locationDictionary) { if(item.Value.NpcRatio=="-1") { break; } else { string[] npcratio = item.Value.NpcRatio.Split('|'); foreach(var npcLimit in npcratio) { string[] limit = npcLimit.Split(','); if (limit[0] == selectScene.scnenId.ToString()&& limit[1] == selectScene.difficultyId.ToString()) { //GameObject sceneitem = GameObject.Instantiate(personnelPrefabs, personnelContent); //PersonnelItem personnelItem = sceneitem.GetComponent(); //Button button = personnelItem.transform.Find("sceneText").GetComponent