_xiaofang/xiaofang/Assets/Script/UI/PanelUI/EvacuationPanel.cs
2024-12-16 15:57:15 +08:00

514 lines
19 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<string, int> distributePeople = new Dictionary<string, int>();// 分配给各个场景的人数
public List<PersonnelItem> 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<ClassItem> classItemList = new List<ClassItem>();
public List<ClassMate> classMateList = new List<ClassMate>();
[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<int> nonZeroAreas = new List<int>();
Dictionary<int, PersonnelItem> personnelItemsDict = new Dictionary<int, PersonnelItem>();//储存分配结果
//private HashSet<int> excludedAreas = new HashSet<int>(); // 被清空的区域 ID
public SelectScenePanel selectScene;
private HashSet<int> clearedAreas = new HashSet<int>();
// 保存分配结果的字典
public Dictionary<int, int> allocatedPeople = new Dictionary<int, int>();
public List<int> clearRegion=new List<int>();//被清除的区域
// Start is called before the first frame update
void Start()
{
SetNpcType();
nonZeroAreas= GetNonZeroNpcRatioAreas();
jc = JuesechoicePop.GetComponent<JueseChoicePop>();
//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<NpcList>();
createTemplateInfo.Instance.auth_CreateTemplate.npcList.Add(nPC);
panel.panelToggle[3].interactable = true; // 启用第二个Toggle
panel.panelToggle[3].gameObject.transform.GetComponent<Image>().sprite = panel.toggleImage[1];
panel.panelToggle[4].interactable = true; // 启用第三个Toggle
panel.panelToggle[4].gameObject.transform.GetComponent<Image>().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<int, int> DistributePeopleWithBalance(int[] scenes, Dictionary<int, PersonnelItem> personnelItemsDict, int totalPeople)
{
// 1. 计算当前每个区域的总人数(初始人数 + 已分配人数)
Dictionary<int, int> totalPeoplePerScene = new Dictionary<int, int>();
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<int, int> initialPeoplePerScene = new Dictionary<int, int>(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<int, int> allocatedPeople = new Dictionary<int, int>();
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<int> GetNonZeroNpcRatioAreas()
{
List<int> nonZeroAreas = new List<int>();
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;
}
//设置左侧场景显示
public void SetPersonnel()
{
// 清空现有的UI项
foreach (Transform child in personnelContent)
{
Destroy(child.gameObject);
}
// 清空人员列表
personnelItems.Clear();
foreach (var sceneEntry in panel.sceneDataDictionary)
{
foreach (var sceneInfo in sceneEntry.Value)
{
LocationData area = js.GetAreaDateById(int.Parse(sceneInfo.sceneId));
// 如果NpcRatio不为"-1"表示该场景有效
if (area.NpcRatio != "-1")
{
// 检查 personnelItems 是否已经包含该 sceneText.text
var existingItem = personnelItems.Find(item => item.sceneText.text == sceneEntry.Key);
if (existingItem != null)
{
// 如果已经存在,增加 Num
existingItem.Num++;
}
else
{
// 如果没有重复的 personnelItem创建并添加
GameObject item = GameObject.Instantiate(personnelPrefabs, personnelContent);
PersonnelItem personnelItem = item.GetComponent<PersonnelItem>();
Button button = personnelItem.transform.Find("sceneText").GetComponent<Button>();
personnelItem.sceneText.text = sceneEntry.Key;
personnelItem.sceneId = area.ID;
personnelItem.Num = 1; // 设置初始值为 1
// 点击事件监听
button.onClick.AddListener(() =>
{
// 标记当前选择的区域
OnSceneItemClicked(item, Color.yellow, selectedScene);
// 如果被点击的区域已经有人员
if (personnelItem.NpcNum > 0)
{
redistributeBtn.onClick.AddListener(() => {
// 清除选定区域的人员数据
RedistributeLogic(personnelItem.sceneId, personnelItem.NpcNum);
});
}
// 清空现有场景下的所有人员UI
foreach (Transform child in sceneCount)
{
Destroy(child.gameObject);
}
// 执行后续的场景级别配置
LocationData locationData = js.GetAreaDateById(personnelItem.sceneId);
if (locationData.Level.ToString() != "0")
{
GameObject levelItem = GameObject.Instantiate(scenePrefab, sceneCount);
Button levelBtn = levelItem.transform.Find("chooseBtn2").GetComponent<Button>();
levelBtn.onClick.AddListener(() =>
{
JueseChoicePop jueseChoicePop = jueseChoicePanel.GetComponent<JueseChoicePop>();
jueseChoicePop.SetClass(personnelItem.sceneId);
jueseChoicePanel.gameObject.SetActive(true);
});
ClassItem classItem = levelItem.GetComponent<ClassItem>();
classItem.classname.text = locationData.Level.ToString();
}
});
personnelItems.Add(personnelItem);
}
}
else
{
break; // 如果遇到无效场景NpcRatio为-1跳出当前循环
}
}
}
}
// 判断重新分配按钮是否可以点击
public void IsRedistribution()
{
// 遍历 personnelItemsDict检查是否有任何 PersonnelItem 的 gameObject 处于激活状态
bool canRedistribute = false;
foreach (var kvp in personnelItemsDict)
{
if (kvp.Value.personnelImage!=null&&kvp.Value.personnelImage.gameObject.activeSelf) // 检查 gameObject 是否显示
{
canRedistribute = true;
break;
}
else
{
canRedistribute = false;
break;
}
}
// 设置重新分配按钮的交互状态
redistributeBtn.interactable = canRedistribute;
}
//判断输入框的数字是否大于1
void CheckInput(string input)
{
// 尝试将输入转换为数字
if (float.TryParse(input, out float result))
{
// 判断数字是否大于1
if (result > 1)
{
CountsubmitBtn.GetComponent<Image>().sprite = rsprite;
CountsubmitBtn.onClick.AddListener(Countsubmit);
}
}
}
//Npc数量设置按钮置灰设置
public void Countsubmit()
{
//按钮置灰
CountsubmitBtn.GetComponent<Image>().sprite = fsprite;
StuCountInputField.text = string.Empty;
//按配置对输入的Npc数量进行 分配
//取消监听
CountsubmitBtn.onClick.RemoveAllListeners();
}
//场景ID进行配置
public void SettopText()
{
topText.text = "以下班级需要设定班主任老师:";
topText.text = "以下楼层需要设定搜救老师:";
}
//实例化ClassItem
public void SetClass()
{
for (int i = 0; i < 10; i++)
{
GameObject item = GameObject.Instantiate<GameObject>(classPrefab, content);
ClassItem classItem = item.GetComponent<ClassItem>();
classItem.JuesechoicePop = JuesechoicePop;
classItemList.Add(classItem);
}
}
//重新分配
public void RedistributeLogic(int excludedSceneId, int excludedNum)
{
// 计算需要重新分配的 NPC 总数
int totalRedistributePeople = excludedNum;
// 清除当前选中区域的人员数据
PersonnelItem excludedItem = personnelItemsDict[excludedSceneId];
excludedItem.NpcNum = 0;
excludedItem.SetInfo(""); // 更新 UI 显示
excludedItem.personnelImage.gameObject.SetActive(false); // 隐藏图标
clearRegion.Add(excludedSceneId); // 记录清空的区域 ID
Debug.Log($"Cleared NPCs from Scene ID: {excludedSceneId}");
// 准备有效分配区域列表(排除被清空的区域)
List<int> validAreas = new List<int>();
foreach (var kvp in personnelItemsDict)
{
if (!clearRegion.Contains(kvp.Key)) // 排除清空的区域
{
validAreas.Add(kvp.Key);
}
}
// 如果没有有效区域,则提示
if (validAreas.Count == 0)
{
Debug.LogWarning("No valid areas available for redistribution.");
return;
}
// 将有效区域转换为数组
int[] validSceneIds = validAreas.ToArray();
foreach (int sceneId in validSceneIds)
{
Debug.Log("Valid Scene ID: " + sceneId);
}
var redistributionResult = DistributePeopleWithBalance(validSceneIds, personnelItemsDict, totalRedistributePeople);
// 更新分配结果到 UI
foreach (var kvp in redistributionResult)
{
if (personnelItemsDict.ContainsKey(kvp.Key))
{
PersonnelItem redistributedItem = personnelItemsDict[kvp.Key];
redistributedItem.NpcNum += kvp.Value; // 更新人数
redistributedItem.SetInfo(redistributedItem.NpcNum.ToString()); // 更新 UI 显示
redistributedItem.personnelImage.gameObject.SetActive(true); // 确保图标显示
redistributedItem.personnelNum.gameObject.SetActive(true); // 确保图标显示
Debug.Log($"Assigned {kvp.Value} NPCs to Scene ID: {kvp.Key}");
}
}
}
//设置文字颜色
public void OnSceneItemClicked(GameObject clickedItem, Color color, GameObject select)
{
// 如果有之前选中的角色,重置其视觉效果
if (selectedScene != null && select != clickedItem)
{
Text prevText = selectedScene.GetComponentInChildren<Text>();
if (prevText != null)
{
prevText.fontSize = 32; // 恢复原始字号
prevText.color = Color.white; // 恢复原始颜色
}
}
// 设置当前选中的角色为选中状态
selectedScene = clickedItem; // 更新选中人物
Text personText = clickedItem.GetComponentInChildren<Text>();
if (personText != null)
{
// 字号变大和颜色变更(选中状态)
personText.fontSize = 36;
personText.color = color; // 选中颜色
}
}
//判断分管区域是否打开
public void IsOpen(int id)
{
if (selectScene.difficultyId > 3)
{
classCount.gameObject.SetActive(true);
}
else
{
classCount.gameObject.SetActive(false);
}
}
}