2024-09-11 23:22:18 +09:00

78 lines
2.6 KiB
Python

from datetime import datetime
from enum import Enum
import matplotlib.pyplot as plt
import pandas
class NodeState(Enum):
"""
A state of node at a certain time.
For now, we assume that the node cannot send and receive messages at the same time for simplicity.
"""
SENDING = -1
IDLE = 0
RECEIVING = 1
class NodeStateTable:
def __init__(self, num_nodes: int, duration_sec: int):
# Create a table to store the state of each node at each millisecond
self.__table = [
[NodeState.IDLE] * (duration_sec * 1000) for _ in range(num_nodes)
]
def __getitem__(self, idx: int) -> list[NodeState]:
return self.__table[idx]
def analyze(self):
df = pandas.DataFrame(self.__table).transpose()
df.columns = [f"Node-{i}" for i in range(len(self.__table))]
# Convert NodeState enum to their integer values
df = df.map(lambda state: state.value)
print("==========================================")
print("Node States of All Nodes over Time")
print(", ".join(f"{state.name}:{state.value}" for state in NodeState))
print("==========================================")
print(f"{df}\n")
csv_path = f"all_node_states_{datetime.now().isoformat(timespec="seconds")}.csv"
df.to_csv(csv_path)
print(f"Saved DataFrame to {csv_path}\n")
# Count/print the number of each state for each node
# because the df is usually too big to print
state_counts = df.apply(pandas.Series.value_counts).fillna(0)
print("State Counts per Node:")
print(f"{state_counts}\n")
# Draw a dot plot
plt.figure(figsize=(15, 8))
for node in df.columns:
times = df.index
states = df[node]
sending_times = times[states == NodeState.SENDING.value]
receiving_times = times[states == NodeState.RECEIVING.value]
plt.scatter(
sending_times,
[node] * len(sending_times),
color="red",
marker="o",
s=10,
label="SENDING" if node == df.columns[0] else "",
)
plt.scatter(
receiving_times,
[node] * len(receiving_times),
color="blue",
marker="x",
s=10,
label="RECEIVING" if node == df.columns[0] else "",
)
plt.xlabel("Time")
plt.ylabel("Node")
plt.title("Node States Over Time")
plt.legend(loc="upper right")
plt.draw()