_xiaofang/xiaofang/Assets/Script/UI/PanelUI/EvacuationPanel.cs

475 lines
17 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 UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.Networking.Types;
using UnityEngine.UI;
using static System.Collections.Specialized.BitVector32;
using static UnityEditor.Progress;
public class EvacuationPanel : MonoBehaviour
{
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 Sprite[] showImage;
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;
public int isHere;
[Header("可分配列表")]
List<int> nonZeroAreas = new List<int>();
public SelectScenePanel selectScene;
[Header("被清除的区域")] public List<int> clearRegion=new List<int>();
[Header("被重新分配的区域")] private HashSet<int> excludedAreas = new HashSet<int>();
// Start is called before the first frame update
void Start()
{
redistributeBtn.interactable = false;
ChangeImage(redistributeBtn.interactable);
jc = JuesechoicePop.GetComponent<JueseChoicePop>();
CountsubmitBtn.onClick.AddListener(Submit);
submitBtn.onClick.AddListener(totalSubmit);
StuCountInputField.onEndEdit.AddListener(CheckInput);
SetScene();
SetClass();
}
void Update()
{
CheckInput(StuCountInputField.text);
//IsRedistribution();
IsOpen(selectScene.difficultyId);
}
//上传数据
public void totalSubmit()
{
createTemplateInfo.Instance.auth_CreateTemplate.npcList = new List<NpcList>();
foreach(var npcInfo in personnelItems)
{
NpcList nPC = new NpcList();
nPC.npcId = npcInfo.npcId.ToString();
nPC.areaId = npcInfo.sceneId.ToString();
nPC.isHere=npcInfo.isHere;
nPC.npcNum = npcInfo.NpcNum;
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;
if (!int.TryParse(StuCountInputField.text, out count) || count <= 0)
{
Debug.LogError("请输入有效的总人数!");
return;
}
//StuCountInputField.text = "";
// 调用分配方法
var result = DistributeNpcByRatio(personnelItems, count);
// 更新 UI 和数据
foreach (var kvp in result)
{
PersonnelItem item = personnelItems.Find(p => p.sceneId == kvp.Key);
if (item != null)
{
item.SetInfo(kvp.Value.ToString()); // 更新UI显示
item.NpcNum = kvp.Value; // 更新Npc数量
item.personnelImage.gameObject.SetActive(true); // 显示图标
Debug.Log($"Scene ID: {kvp.Key}, Assigned NPC Count: {kvp.Value}");
}
}
}
//Npc分配
public Dictionary<int, int> DistributeNpcByRatio(List<PersonnelItem> personnelItems, int totalNpcCount)
{
Dictionary<int, float> sceneRatios = new Dictionary<int, float>(); // 存储场景ID和比例
float totalRatio = 0; // 所有场景的比例之和
// 遍历所有可以分配的区域解析NpcRatio提取分配比例
foreach (var item in personnelItems)
{
LocationData locationData = js.GetAreaDateById(item.sceneId);
string[] allLimits = locationData.NpcRatio.Split('|'); // 多个比例段
foreach (string limit in allLimits)
{
string[] parts = limit.Split(',');
if (parts.Length >= 5) // 确保数据有效
{
int sceneId = item.sceneId; // 使用 PersonnelItem 的 sceneId
float ratio = float.Parse(parts[4]); // 第五项是分配比例
item.npcId = int.Parse(parts[2]);
item .isHere=int.Parse(parts[3]);
if (!sceneRatios.ContainsKey(sceneId))
{
sceneRatios.Add(sceneId, ratio);
totalRatio += ratio; // 累加所有场景的比例
}
}
}
}
// 如果没有有效的分配比例,直接返回空结果
if (sceneRatios.Count == 0 || totalRatio == 0)
{
Debug.LogError("没有找到有效的分配比例!");
return new Dictionary<int, int>();
}
// 根据比例分配人数
Dictionary<int, int> finalDistribution = new Dictionary<int, int>();
int remainingNpc = totalNpcCount;
foreach (var entry in sceneRatios)
{
int allocatedNpc = Mathf.FloorToInt(totalNpcCount * (entry.Value / totalRatio)); // 按比例分配
finalDistribution[entry.Key] = allocatedNpc; // 添加到分配结果
remainingNpc -= allocatedNpc; // 更新剩余NPC数量
}
// 将剩余人数分配给当前人数最少的场景
while (remainingNpc > 0)
{
int minScene = finalDistribution.OrderBy(kvp => kvp.Value).First().Key; // 找到当前人数最少的场景
finalDistribution[minScene]++;
remainingNpc--;
}
return finalDistribution;
}
//设置左侧场景显示2.0
public void SetScene()
{
foreach (var item in js.locationDictionary)
{
if(item.Value.NpcRatio=="-1")
{
continue;
}
else
{
string[] npcratio = item.Value.NpcRatio.Split('|');
foreach(var npcLimit in npcratio)
{
string[] limit = npcLimit.Split(',');
if (limit[0] == selectScene.idcidentId.ToString()&& limit[1] == selectScene.difficultyId.ToString())
{
GameObject sceneitem = GameObject.Instantiate(personnelPrefabs, personnelContent);
PersonnelItem personnelItem = sceneitem.GetComponent<PersonnelItem>();
Button button = personnelItem.transform.Find("sceneText").GetComponent<Button>();
personnelItem.sceneText.text = js.SetUIText(item.Value.Name);
personnelItem.sceneId = item.Key;
personnelItem.Num = 1; // 设置初始值为 1
// 点击事件监听
button.onClick.AddListener(() =>
{
// 标记当前选择的区域
OnSceneItemClicked(sceneitem, Color.yellow, selectedScene);
// 如果被点击的区域已经有人员
if (personnelItem.NpcNum > 0)
{
redistributeBtn.interactable = true;
ChangeImage(redistributeBtn.interactable);
redistributeBtn.transform.GetComponent<Image>().sprite = showImage[1];
// 清除所有之前的监听器,确保只有最新的事件被执行
redistributeBtn.onClick.RemoveAllListeners();
// 添加最新的监听器
redistributeBtn.onClick.AddListener(() =>
{
// 清除选定区域的人员数据
RedistributeLogic(personnelItem.sceneId, personnelItem.NpcNum);
redistributeBtn.interactable = false;
ChangeImage(redistributeBtn.interactable);
});
}
// 清空现有场景下的所有人员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);
}
}
}
}
}
// 判断重新分配按钮是否可以点击
public void IsRedistribution()
{
// 遍历 personnelItems检查是否有任何 PersonnelItem 的 gameObject 处于激活状态
bool canRedistribute = personnelItems.Any(item =>
item.personnelImage != null && item.personnelImage.gameObject.activeSelf);
// 设置重新分配按钮的交互状态
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)
{
// 1. 计算需要重新分配的 NPC 总数
int totalRedistributePeople = excludedNum;
// 2. 标记当前重新分配的区域
if (!excludedAreas.Contains(excludedSceneId))
{
excludedAreas.Add(excludedSceneId); // 将被重新分配的区域加入到排除列表中
Debug.Log($"Scene ID {excludedSceneId} added to excluded areas.");
}
// 修改被重新分配区域的数据
PersonnelItem excludedItem = personnelItems.FirstOrDefault(item => item.sceneId == excludedSceneId);
if (excludedItem != null)
{
excludedItem.NpcNum = 0; // 清空 NPC 数量
excludedItem.SetInfo(""); // 更新 UI 显示为空
excludedItem.personnelImage.gameObject.SetActive(false); // 隐藏图标
Debug.Log($"Cleared NPCs from Scene ID: {excludedSceneId}");
}
else
{
Debug.LogWarning($"Scene ID {excludedSceneId} not found in personnelItems.");
return;
}
// 3. 筛选有效的分配区域(跳过已排除的区域)
List<PersonnelItem> validAreas = personnelItems.Where(item => !excludedAreas.Contains(item.sceneId)).ToList();
if (validAreas.Count == 0)
{
Debug.LogWarning("No valid areas available for redistribution.");
return;
}
// 4. 随机分配人数到有效区域
System.Random random = new System.Random(); // 随机数生成器
Dictionary<int, int> redistributionResult = new Dictionary<int, int>();
// 初始化分配结果
foreach (var item in validAreas)
{
redistributionResult[item.sceneId] = 0;
}
// 随机分配 NPC
int remainingNpc = totalRedistributePeople;
while (remainingNpc > 0)
{
// 随机选择一个区域
int randomIndex = random.Next(0, validAreas.Count);
PersonnelItem targetItem = validAreas[randomIndex];
// 更新分配结果
redistributionResult[targetItem.sceneId]++;
remainingNpc--;
}
// 5. 更新有效区域的 UI 显示和数据
foreach (var kvp in redistributionResult)
{
PersonnelItem targetItem = validAreas.FirstOrDefault(item => item.sceneId == kvp.Key);
if (targetItem != null)
{
targetItem.NpcNum += kvp.Value; // 更新 NPC 数量
targetItem.SetInfo(targetItem.NpcNum.ToString()); // 更新 UI 显示
targetItem.personnelImage.gameObject.SetActive(true); // 确保图标可见
Debug.Log($"Redistributed {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);
}
}
//重新分配的按钮图片修改
public void ChangeImage(bool isSure)
{
if (isSure)
{
redistributeBtn.transform.GetComponent<Image>().sprite = showImage[1];
}
else
{
redistributeBtn.transform.GetComponent<Image>().sprite = showImage[0];
}
}
}