Aimbot-ParallelEnv/Assets/TargetLevelProbabilityPanel.cs

177 lines
7.4 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
public class TargetLevelProbabilityPanel : MonoBehaviour
{
public GameObject singleLevelProbabilityPanel;
public GameObject targetTitleText;
private GameObject titleText;
private List<GameObject> singleLevelPanelsObjs = new List<GameObject>();
private List<SingleLevelProbabilityPanel> singleLevelPanels = new List<SingleLevelProbabilityPanel>();
private int panelNum = 0;
public void IntializePanels(int levelNum, string titleName)
{
// initialize target level probability panel size
float defaultWidth = singleLevelProbabilityPanel.GetComponent<RectTransform>().sizeDelta.x;
float defaultLevelHeight = singleLevelProbabilityPanel.GetComponent<RectTransform>().sizeDelta.y;
float titleHeight = targetTitleText.GetComponent<RectTransform>().sizeDelta.y;
float averageProbability = 1f / levelNum;
float lastLevelProbability = 1f - averageProbability * (levelNum - 1);
Debug.Log("averageProbability: " + averageProbability);
transform.GetComponent<RectTransform>().sizeDelta = new Vector2(defaultWidth, (defaultLevelHeight * levelNum) + titleHeight);
// create title text
titleText = Instantiate(targetTitleText, transform);
titleText.GetComponent<TextMeshProUGUI>().text = titleName;
// create and initialize single level probability panels
for (int i = 0; i < levelNum; i++)
{
int tempIndex = i;
singleLevelPanelsObjs.Add(Instantiate(singleLevelProbabilityPanel, transform));
singleLevelPanels.Add(singleLevelPanelsObjs[i].GetComponent<SingleLevelProbabilityPanel>());
singleLevelPanels[i].InitializeLevelProbabilityPanel(i, i == levelNum - 1 ? lastLevelProbability : averageProbability);
//add onValueChanged event to slider and input field
singleLevelPanels[i].probabilitySlider.onValueChanged.AddListener((value) => OnSliderValueChange(value, tempIndex));
}
panelNum = levelNum;
}
/// <summary>
/// Adds an event trigger entry to an event trigger.
/// </summary>
/// <param name="trigger">The event trigger object.</param>
/// <param name="type">The event trigger type.</param>
/// <param name="action">The event handler method to execute.</param>
private void AddEventTrigger(GameObject gameObject, EventTriggerType triggerType, System.Action<BaseEventData> action)
{
EventTrigger eventTrigger = gameObject.GetComponent<EventTrigger>();
if (eventTrigger == null)
{
eventTrigger = gameObject.AddComponent<EventTrigger>();
}
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = triggerType;
entry.callback.AddListener(new UnityEngine.Events.UnityAction<BaseEventData>(action));
eventTrigger.triggers.Add(entry);
}
private void OnSliderValueChange(float value, int exceptedIndex)
{
float newTotalValue = 0;
float averageCorrectionValue = 0;
int unlockedPanelNum = 0;
int remainCorrectionNum = panelNum;
float extraValue = 0;
float[] correctionValues = new float[panelNum];
// calculate total probability value
for (int i = 0; i < panelNum; i++)
{
// disable slider listener
singleLevelPanels[i].probabilitySlider.onValueChanged.RemoveAllListeners();
newTotalValue += (i == exceptedIndex ? value : singleLevelPanels[i].ProbabilityValue);
if (singleLevelPanels[i].UnLocked)
{
unlockedPanelNum++;
}
}
// only have one panel
if (panelNum == 1)
{
singleLevelPanels[exceptedIndex].SetProbability(1);
enableSliderListener();
return;
}
//only one panel is unlocked
if (unlockedPanelNum == 1)
{
// limit this panel value under 1 - (newTotalValue - value)
singleLevelPanels[exceptedIndex].SetProbability(newTotalValue - 1 > 0 ? 1 - newTotalValue + value : value);
enableSliderListener();
return;
}
// Calculate the average correction value
extraValue = newTotalValue - 1;
averageCorrectionValue = extraValue / (unlockedPanelNum - 1);
// initialize correction value to each panel
correctionValues = Enumerable.Repeat(averageCorrectionValue, panelNum).ToArray();
// make sure all probability value is not less than 0 and equal to 1
int iterationCount = 0;
while (remainCorrectionNum > 0)
{
iterationCount++;
Debug.Log(remainCorrectionNum);
remainCorrectionNum = 0;
List<int> reCorrectionIndex = new List<int>();
int lastReCorrectionIndex = 0;
float underZeroExtraValueAfterCorrected = 0;
for (int i = 0; i < panelNum; ++i)
{
// if the panel is the changed one
if (i == exceptedIndex)
{
correctionValues[i] = 0;
continue;
}
// if the panel is locked or the probability value is 0 or the probability value is equal to the correction value
if (singleLevelPanels[i].IsLocked || singleLevelPanels[i].ProbabilityValue <= 0)
{
correctionValues[i] = 0;
}
else if (singleLevelPanels[i].ProbabilityValue == correctionValues[i])
{
underZeroExtraValueAfterCorrected += correctionValues[i];
}
else if (singleLevelPanels[i].ProbabilityValue - correctionValues[i] < 0)
{
underZeroExtraValueAfterCorrected += correctionValues[i];
correctionValues[i] = singleLevelPanels[i].ProbabilityValue;
remainCorrectionNum++;
}
else
{
lastReCorrectionIndex = i;
reCorrectionIndex.Add(i);
}
}
foreach (int index in reCorrectionIndex)
{
float newAverageCorrectionValue = (extraValue - underZeroExtraValueAfterCorrected) / reCorrectionIndex.Count;
//
if (index == lastReCorrectionIndex)
{
correctionValues[index] = extraValue - (newAverageCorrectionValue * (reCorrectionIndex.Count - 1));
}
else
{
correctionValues[index] = newAverageCorrectionValue;
}
}
if (iterationCount >= 100)
{
break;
}
}
// applicate the value to all unlocked panels excepted the changed one
for (int i = 0; i < panelNum; i++)
{
singleLevelPanels[i].SetProbability(i == exceptedIndex ? value : singleLevelPanels[i].ProbabilityValue - correctionValues[i]);
}
enableSliderListener();
}
private void enableSliderListener()
{
for (int i = 0; i < panelNum; i++)
{
int tempIndex = i;
singleLevelPanels[i].probabilitySlider.onValueChanged.AddListener((value) => OnSliderValueChange(value, tempIndex));
}
}
}