# scheduler/optimizer.py def choose_best_node(nodes, action, intelligence=None): best_node = None best_score = -10**9 ranked = [] # ----------------------------- # SCORE EACH NODE # ----------------------------- for node in nodes: breakdown = { "cpu": 0, "thermal": 0, "policy": 0, "intelligence": 0, "final": 0 } # CPU availability cpu_score = (100 - node.get("cpu_load", 0)) breakdown["cpu"] = cpu_score # Thermal penalty thermal_penalty = node.get("temp", 0) breakdown["thermal"] = -thermal_penalty # Policy rules policy_score = 0 if node.get("policy") == "preferred": policy_score += 20 elif node.get("policy") == "avoid": policy_score -= 50 breakdown["policy"] = policy_score # Intelligence feedback intel_score = 0 if intelligence: stats = intelligence.profiles.get(action["target"]) if stats: latest = stats.finalize() intel_score -= latest["score"].get("thermal", 0) * 0.3 intel_score -= latest["score"].get("instability", 0) * 0.2 breakdown["intelligence"] = intel_score # Final score final = cpu_score + policy_score + intel_score + breakdown["thermal"] breakdown["final"] = final ranked.append({ "node": node, "score": breakdown }) if final > best_score: best_score = final best_node = node # ----------------------------- # SORT FOR EXPLANATION # ----------------------------- ranked_sorted = sorted( ranked, key=lambda x: x["score"]["final"], reverse=True ) # ----------------------------- # EXPLANATION OBJECT # ----------------------------- explanation = { "selected": best_node["name"] if best_node else None, "top_candidates": [ { "node": r["node"]["name"], "final_score": r["score"]["final"], "breakdown": r["score"] } for r in ranked_sorted[:5] ] } return { "best_node": best_node, "ranked": ranked, "explanation": explanation }