Borealis-Legacy/Nodes/Flyff/flyff_leveling_predictor_node.py
2025-02-16 22:50:39 -07:00

142 lines
5.1 KiB
Python

#!/usr/bin/env python3
"""
Flyff - Leveling Predictor Node:
- Tracks the last N changes in EXP values.
- Calculates the average change rate and time intervals.
- Predicts the estimated time to reach level 100.
"""
import time
import numpy as np
from OdenGraphQt import BaseNode
from PyQt5.QtCore import QTimer
from Modules import data_manager
class FlyffLevelingPredictorNode(BaseNode):
__identifier__ = "bunny-lab.io.flyff_leveling_predictor_node"
NODE_NAME = "Flyff - Leveling Predictor"
def __init__(self):
super(FlyffLevelingPredictorNode, self).__init__()
# Input port for EXP values
self.add_input("exp", "EXP")
# User-defined number of changes to track
self.add_text_input("exp_track_count", "# of EXP Changes to Track", text="7")
# Output widgets
self.add_text_input("time_to_level", "Time to Level", text="Calculating...")
self.add_text_input("time_between_kills", "Time Between Kills", text="N/A")
self.add_text_input("exp_per_kill", "EXP Per Kill", text="N/A")
# Internal tracking lists
self.exp_history = []
self.time_intervals = []
self.last_exp_value = None
self.last_update_time = None
# Timer to periodically process EXP changes
self.timer = QTimer()
self.timer.timeout.connect(self.process_exp_change)
self.timer.start(1000) # Check for updates every second
def reset_tracking_arrays(self):
"""
Resets the EXP history and time interval arrays when a level-up is detected.
"""
self.exp_history.clear()
self.time_intervals.clear()
self.last_exp_value = None
self.last_update_time = None
def process_exp_change(self):
"""
Monitors changes in EXP values and calculates various statistics.
"""
exp_value = data_manager.get_data().get("exp", None)
if exp_value is None:
return
exp_track_count = self.get_property("exp_track_count")
try:
exp_track_count = int(exp_track_count)
except ValueError:
exp_track_count = 7 # Default to 7 if invalid input
# Reset if EXP value decreases (indicating a level-up)
if self.last_exp_value is not None and exp_value < self.last_exp_value:
self.reset_tracking_arrays()
if self.last_exp_value is not None and exp_value != self.last_exp_value:
current_time = time.time()
# Store EXP change history
self.exp_history.append(exp_value)
if len(self.exp_history) > exp_track_count:
self.exp_history.pop(0)
# Store time intervals
if self.last_update_time is not None:
interval = current_time - self.last_update_time
self.time_intervals.append(interval)
if len(self.time_intervals) > exp_track_count:
self.time_intervals.pop(0)
# Perform calculations
self.calculate_time_to_level()
self.calculate_additional_metrics()
# Update last tracking values
self.last_update_time = current_time
self.last_exp_value = exp_value
def calculate_time_to_level(self):
"""
Calculates the estimated time to reach level 100 based on EXP change history.
"""
if len(self.exp_history) < 2 or len(self.time_intervals) < 1:
self.set_property("time_to_level", "Insufficient data")
return
exp_deltas = np.diff(self.exp_history) # Compute EXP change per interval
avg_exp_change = np.mean(exp_deltas) if len(exp_deltas) > 0 else 0
avg_time_change = np.mean(self.time_intervals)
if avg_exp_change <= 0:
self.set_property("time_to_level", "Not gaining EXP")
return
current_exp = self.exp_history[-1]
remaining_exp = 100.0 - current_exp # Distance to level 100
estimated_time = (remaining_exp / avg_exp_change) * avg_time_change
# Convert estimated time into hours, minutes, and seconds
hours = int(estimated_time // 3600)
minutes = int((estimated_time % 3600) // 60)
seconds = int(estimated_time % 60)
time_str = f"{hours}h {minutes}m {seconds}s"
self.set_property("time_to_level", time_str)
def calculate_additional_metrics(self):
"""
Calculates and updates the "Time Between Kills" and "EXP Per Kill".
"""
if len(self.time_intervals) > 0:
avg_time_between_kills = np.mean(self.time_intervals)
minutes = int(avg_time_between_kills // 60)
seconds = int(avg_time_between_kills % 60)
self.set_property("time_between_kills", f"{minutes}m {seconds}s")
else:
self.set_property("time_between_kills", "N/A")
if len(self.exp_history) > 1:
exp_deltas = np.diff(self.exp_history)
avg_exp_per_kill = np.mean(exp_deltas) if len(exp_deltas) > 0 else 0
self.set_property("exp_per_kill", f"{avg_exp_per_kill:.2f}%")
else:
self.set_property("exp_per_kill", "N/A")