520 lines
17 KiB
C#
520 lines
17 KiB
C#
using Newtonsoft.Json.Linq;
|
||
using UnityEngine;
|
||
using System;
|
||
using System.Collections.Concurrent;
|
||
using System.Collections.Generic;
|
||
using UnityEngine.Events;
|
||
using Octopus.Simulator.Networks;
|
||
using Newtonsoft.Json;
|
||
using Cysharp.Threading.Tasks;
|
||
using Octopus.Simulator;
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_start
|
||
{
|
||
public string processor_id;
|
||
public string processor_label;
|
||
public int processing_time;
|
||
public List<ProcessInputQueue> input_queues;
|
||
public List<ProcessInputStore> input_stores;
|
||
public string output_queue;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessInputQueue
|
||
{
|
||
public string queue_name;
|
||
public int required_items;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessInputStore
|
||
{
|
||
public string store_name;
|
||
public int required_items;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_using_queue
|
||
{
|
||
public string processor_id;
|
||
public string processor_label;
|
||
public string queue_name;
|
||
public int queue_length;
|
||
public int required_items;
|
||
public int priority_order;
|
||
public string queue_type;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_using_store
|
||
{
|
||
public string processor_id;
|
||
public string processor_label;
|
||
public string store_name;
|
||
public int store_length;
|
||
public int required_items;
|
||
public int priority_order;
|
||
public string queue_type;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_checking_inputs
|
||
{
|
||
public string processor_id;
|
||
public List<ProcessInputQueue> queues;
|
||
public List<ProcessInputStore> stores;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_defects_detected
|
||
{
|
||
public string processor_id;
|
||
public int defect_count;
|
||
public string queue_name;
|
||
public int queue_length;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_requesting_resource
|
||
{
|
||
public string processor_id;
|
||
public string resource_name;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_resource_acquired
|
||
{
|
||
public string processor_id;
|
||
public string resource_name;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_speed_factor_applied
|
||
{
|
||
public string processor_id;
|
||
public string resource_name;
|
||
public float original_time;
|
||
public float adjusted_time;
|
||
public float speed_factor;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_batch_started
|
||
{
|
||
public string processor_id;
|
||
public int product_count;
|
||
public int processing_time;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_batch_completed
|
||
{
|
||
public string processor_id;
|
||
public int product_count;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_output_queue
|
||
{
|
||
public string processor_id;
|
||
public string queue_name;
|
||
public int queue_length_before;
|
||
public int products_to_add;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_output_store
|
||
{
|
||
public string processor_id;
|
||
public string store_name;
|
||
public int store_length;
|
||
public int products_added;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_waiting
|
||
{
|
||
public string processor_id;
|
||
public int missing;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_ResourceAcquired
|
||
{
|
||
public string processor_id;
|
||
public string resource_name;
|
||
}
|
||
|
||
[Serializable]
|
||
public class ProcessDataClass_statistics
|
||
{
|
||
public StatisticsProcess statistics;
|
||
}
|
||
|
||
[Serializable]
|
||
public class StatisticsProcess
|
||
{
|
||
public int total_input;
|
||
public int total_processed;
|
||
}
|
||
|
||
public class SimulationModelProcess : SimulationModel
|
||
{
|
||
public string eventUsingQueue = "processor_using_queue";
|
||
public string eventUsingStore = "processor_using_store";
|
||
public string eventStartBatch = "processor_batch_started";
|
||
public string eventOutputQueue = "processor_output_queue";
|
||
public List<GameObject> listProducts = new List<GameObject>();
|
||
public Transform productPos;
|
||
public UnityEvent onProcessStart;
|
||
public UnityEvent onProcessEnd;
|
||
public SimulationModelResource resource;
|
||
int productCount = 0;
|
||
float processTime = 0;
|
||
float elapsedTime = 0;
|
||
ConcurrentQueue<JObject> dataQueue;
|
||
bool startBatch = false;
|
||
|
||
Action AnimationAction_Start;
|
||
Action AnimationAction_End;
|
||
|
||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||
void Start()
|
||
{
|
||
var animator = GetComponentInChildren<ActionAnimator>();
|
||
|
||
if ( animator != null)
|
||
{
|
||
AnimationAction_Start += animator.AnimationStart;
|
||
AnimationAction_End += animator.AnimationEnd;
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
protected override IEnumerator RunSimulationCoroutine()
|
||
{
|
||
yield return new WaitUntil(() => !string.IsNullOrEmpty(nodeID));
|
||
while (dataQueue == null)
|
||
{
|
||
dataQueue = MQTTDataBase.Instance.GetDataQueue(nodeID);
|
||
if (dataQueue == null)
|
||
yield return null;
|
||
else
|
||
break;
|
||
}
|
||
while (true)
|
||
{
|
||
if (dataQueue.IsEmpty)
|
||
{
|
||
yield return null;
|
||
continue;
|
||
}
|
||
if (dataQueue.TryDequeue(out JObject currentData))
|
||
{
|
||
string eventKey = "_event";
|
||
if (currentData.ContainsKey(eventKey))
|
||
{
|
||
string value = currentData[eventKey].ToString();
|
||
if (value.Contains(eventUsingQueue))
|
||
{
|
||
string[] queueIDKey = { "data", "queue_name" };
|
||
string[] loadCountKey = { "data", "required_items" };
|
||
string queueID = GetJsonValue(currentData, queueIDKey)?.ToString();
|
||
int loadCount = GetJsonIntValue(currentData, loadCountKey);
|
||
SimulationModel model = DataManager.I.GetModel(queueID);
|
||
SimulationModelStore storeModel = (SimulationModelStore)model;
|
||
for (int i = 0; i < loadCount; i++)
|
||
{
|
||
GameObject product = null;
|
||
yield return new WaitUntil(() => {
|
||
product = storeModel.GetProduct();
|
||
return product != null;
|
||
});
|
||
product.transform.parent = productPos;
|
||
product.transform.localPosition = Vector3.zero;
|
||
product.transform.localRotation = Quaternion.identity;
|
||
listProducts.Add(product);
|
||
}
|
||
}
|
||
else if (value.Contains(eventUsingStore))
|
||
{
|
||
string[] queueIDKey = { "data", "store_name" };
|
||
string[] loadCountKey = { "data", "required_items" };
|
||
string queueID = GetJsonValue(currentData, queueIDKey)?.ToString();
|
||
int loadCount = GetJsonIntValue(currentData, loadCountKey);
|
||
SimulationModel model = DataManager.I.GetModel(queueID);
|
||
SimulationModelStore storeModel = (SimulationModelStore)model;
|
||
for (int i = 0; i < loadCount; i++)
|
||
{
|
||
GameObject product = null;
|
||
yield return new WaitUntil(() => {
|
||
product = storeModel.GetProduct();
|
||
return product != null;
|
||
});
|
||
product.transform.parent = productPos;
|
||
product.transform.localPosition = Vector3.zero;
|
||
product.transform.localRotation = Quaternion.identity;
|
||
listProducts.Add(product);
|
||
}
|
||
}
|
||
else if (value.Contains(eventStartBatch))
|
||
{
|
||
string[] productCountKey = { "data", "product_count" };
|
||
string[] processTimeKey = { "data", "processing_time" };
|
||
int productCount = GetJsonIntValue(currentData, productCountKey);
|
||
processTime = GetJsonFloatValue(currentData, processTimeKey);
|
||
elapsedTime = 0;
|
||
startBatch = true;
|
||
onProcessStart?.Invoke();
|
||
}
|
||
else if (value.Contains(eventOutputQueue))
|
||
{
|
||
string[] outputQueueKey = { "data", "queue_name" };
|
||
string[] productCountKey = { "data", "products_to_add" };
|
||
string queueID = GetJsonValue(currentData, outputQueueKey)?.ToString();
|
||
int productCount = GetJsonIntValue(currentData, productCountKey);
|
||
SimulationModel model = DataManager.I.GetModel(queueID);
|
||
SimulationModelStore storeModel = (SimulationModelStore)model;
|
||
for (int i = 0; i < productCount; i++)
|
||
{
|
||
if (listProducts.Count > 0)
|
||
{
|
||
GameObject product = listProducts[0];
|
||
storeModel.StoreProduct(product);
|
||
listProducts.Remove(product);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("Trying to unload from empty transporter : " + nodeID);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
yield return null;
|
||
}
|
||
yield return null;
|
||
}
|
||
*/
|
||
|
||
private void SetUsingQueue(ProcessDataClass_using_queue data)
|
||
{
|
||
string queueID = data.queue_name;
|
||
int loadCount = data.required_items;
|
||
SimulationModel model = DataManager.I.GetModel(queueID);
|
||
SimulationModelStore storeModel = model.GetComponent<SimulationModelStore>();
|
||
for (int i = 0; i < loadCount; i++)
|
||
{
|
||
GameObject product = null;
|
||
product = ProductManager.Instance.SpawnProduct();
|
||
|
||
product.transform.parent = productPos;
|
||
product.transform.localPosition = Vector3.zero;
|
||
product.transform.localRotation = Quaternion.identity;
|
||
listProducts.Add(product);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
private void SetUsingStore(ProcessDataClass_using_store data)
|
||
{
|
||
string queueID = data.store_name;
|
||
int loadCount = data.required_items;
|
||
SimulationModel model = DataManager.I.GetModel(queueID);
|
||
SimulationModelStore storeModel = model.GetComponent<SimulationModelStore>();
|
||
for (int i = 0; i < loadCount; i++)
|
||
{
|
||
GameObject product = null;
|
||
product = ProductManager.Instance.SpawnProduct();
|
||
|
||
product.transform.parent = productPos;
|
||
product.transform.localPosition = Vector3.zero;
|
||
product.transform.localRotation = Quaternion.identity;
|
||
listProducts.Add(product);
|
||
}
|
||
}
|
||
|
||
private void BatchStarted(ProcessDataClass_batch_started data)
|
||
{
|
||
int productCount = data.product_count;
|
||
processTime = data.processing_time;
|
||
elapsedTime = 0;
|
||
startBatch = true;
|
||
onProcessStart?.Invoke();
|
||
AnimationAction_Start?.Invoke();
|
||
}
|
||
|
||
private void OutputToQueue(ProcessDataClass_output_queue data)
|
||
{
|
||
string queueID = data.queue_name;
|
||
int productCount = data.products_to_add;
|
||
SimulationModel model = DataManager.I.GetModel(queueID);
|
||
SimulationModelStore storeModel = model.GetComponent<SimulationModelStore>();
|
||
for (int i = 0; i < productCount; i++)
|
||
{
|
||
if (listProducts.Count > 0)
|
||
{
|
||
GameObject product = listProducts[0];
|
||
//storeModel.StoreProduct(product);
|
||
listProducts.Remove(product);
|
||
Destroy(product);
|
||
}
|
||
else
|
||
{
|
||
//Debug.LogWarning("Trying to unload from empty transporter : " + nodeID);
|
||
}
|
||
}
|
||
|
||
AnimationAction_End?.Invoke();
|
||
}
|
||
|
||
private void DefectToQueue(ProcessDataClass_defects_detected data)
|
||
{
|
||
string queueID = data.queue_name;
|
||
int productCount = data.defect_count;
|
||
SimulationModel model = DataManager.I.GetModel(queueID);
|
||
SimulationModelStore storeModel = model.GetComponent<SimulationModelStore>();
|
||
for (int i = 0; i < productCount; i++)
|
||
{
|
||
if (listProducts.Count > 0)
|
||
{
|
||
GameObject product = listProducts[0];
|
||
//storeModel.StoreProduct(product);
|
||
listProducts.Remove(product);
|
||
Destroy(product);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("Trying to unload from empty transporter : " + nodeID);
|
||
}
|
||
}
|
||
|
||
|
||
AnimationAction_End?.Invoke();
|
||
}
|
||
|
||
private void OutputToStore(ProcessDataClass_output_store data)
|
||
{
|
||
string queueID = data.store_name;
|
||
int productCount = data.products_added;
|
||
SimulationModel model = DataManager.I.GetModel(queueID);
|
||
SimulationModelStore storeModel = model.GetComponent<SimulationModelStore>();
|
||
for (int i = 0; i < productCount; i++)
|
||
{
|
||
if (listProducts.Count > 0)
|
||
{
|
||
GameObject product = listProducts[0];
|
||
//storeModel.StoreProduct(product);
|
||
listProducts.Remove(product);
|
||
Destroy(product);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("Trying to unload from empty transporter : " + nodeID);
|
||
}
|
||
}
|
||
|
||
|
||
AnimationAction_End?.Invoke();
|
||
}
|
||
|
||
private void ResourceAcquired(ProcessDataClass_ResourceAcquired data)
|
||
{
|
||
resource = DataManager.I.GetModel(data.resource_name) as SimulationModelResource;
|
||
//resource.gameObject.SetActive(true);
|
||
|
||
AnimationAction_Start?.Invoke();
|
||
}
|
||
|
||
private void ResourceReleased()
|
||
{
|
||
if (resource)
|
||
{
|
||
//resource.gameObject.SetActive(false);
|
||
resource = null;
|
||
}
|
||
|
||
AnimationAction_End?.Invoke();
|
||
}
|
||
|
||
public override void GetData(string data)
|
||
{
|
||
var message = JsonConvert.DeserializeObject<BaseJson>(data);
|
||
|
||
switch (message._event)
|
||
{
|
||
case "processor_using_queue":
|
||
SetUsingQueue(message.data.ToObject<ProcessDataClass_using_queue>());
|
||
//Debug.Log($"{this.nodeID}");
|
||
return;
|
||
|
||
case "processor_using_store":
|
||
SetUsingStore(message.data.ToObject<ProcessDataClass_using_store>());
|
||
return;
|
||
|
||
case "processor_batch_started":
|
||
BatchStarted(message.data.ToObject<ProcessDataClass_batch_started>());
|
||
//Debug.Log($"{this.nodeID} started batch");
|
||
return;
|
||
|
||
case "processor_output_queue":
|
||
OutputToQueue(message.data.ToObject<ProcessDataClass_output_queue>());
|
||
return;
|
||
|
||
case "processor_output_store":
|
||
OutputToStore(message.data.ToObject<ProcessDataClass_output_store>());
|
||
return;
|
||
|
||
case "processor_defects_detected":
|
||
DefectToQueue(message.data.ToObject<ProcessDataClass_defects_detected>());
|
||
return;
|
||
|
||
case "processor_output_defect_store":
|
||
OutputToStore(message.data.ToObject<ProcessDataClass_output_store>());
|
||
return;
|
||
|
||
case "processor_resource_acquired":
|
||
ResourceAcquired(message.data.ToObject<ProcessDataClass_ResourceAcquired>());
|
||
//Debug.Log($"{this.nodeID} acquired {message.data.ToObject<ProcessDataClass_ResourceAcquired>().resource_name}");
|
||
return;
|
||
|
||
case "processor_resource_released":
|
||
//Debug.Log($"{this.nodeID} release event");
|
||
//Debug.Log($"{this.nodeID} release {this.resource.nodeID} ");
|
||
ResourceReleased();
|
||
return;
|
||
case "processor_statistics_update":
|
||
SetBubble(message.data.ToObject<ProcessDataClass_statistics>().statistics);
|
||
break;
|
||
|
||
default:
|
||
|
||
//Debug.Log($"{message._event} does not match any case!!!");
|
||
return;
|
||
|
||
}
|
||
}
|
||
|
||
public override void SetBubble(object data)
|
||
{
|
||
var processStatistics = data as StatisticsProcess;
|
||
|
||
string msg = $"{processStatistics.total_input}/{processStatistics.total_processed}";
|
||
|
||
if (currentBubble == null)
|
||
{
|
||
// <20><><EFBFBD><EFBFBD>
|
||
currentBubble = Instantiate(bubbleUIPrefab, FindAnyObjectByType<Canvas_Bubble>().transform);
|
||
currentBubble.target = DataBubbleSocket;
|
||
currentBubble.worldOffset = new Vector3(0, 0, 0); // <20>ʿ信 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
currentBubble.GetComponent<RectTransform>().SetAsFirstSibling();
|
||
}
|
||
// <20>ؽ<EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>
|
||
currentBubble.SetMessage(msg);
|
||
currentBubble.SetDetail(processStatistics,logicType.processor, LogicUIManager.instance.GetItemLabelByID(nodeID));
|
||
}
|
||
}
|