# ETHLatticePoE Cost/Reward Simulation
# Author: Your Name
# Date: 2025-09-30

import numpy as np
import matplotlib.pyplot as plt

# -------------------------------
# Simulation Parameters
# -------------------------------
num_blocks = 100              # Number of blocks to simulate
pow_hash_power = 1_000_000    # POW hashes per block
eth_reward_per_block = 2      # ETH reward per block for miners (simplified)
node_efficiency = 50_000      # Segments a single node can fill per block
premium_fraction = 0.1        # Fraction allocated to premium
eth_cost_per_segment = 0.00001  # ETH cost per off-chain segment (computation cost)
num_nodes_list = [1, 5, 10, 20, 50]  # Node scenarios to test

# -------------------------------
# Simulation Function
# -------------------------------
def simulate_lattice_vs_pow(num_nodes):
    freeCounter = 0
    premiumCounter = 0
    total_segments_filled = 0
    cumulative_eth_cost = 0
    cumulative_eth_reward = 0

    history_total_segments = []
    history_free_segments = []
    history_premium_segments = []
    history_pow_progress = []
    history_eth_cost = []
    history_eth_reward = []

    free_tick_segments = 100

    for block in range(num_blocks):
        # ETH deterministic freeTick
        free_segments = free_tick_segments
        freeCounter += free_segments

        # Off-chain nodes contribution
        node_total_segments = num_nodes * node_efficiency
        premium_segments = int(node_total_segments * premium_fraction)
        free_segments_from_nodes = node_total_segments - premium_segments

        premiumCounter += premium_segments

        # Cost in ETH for node computation
        eth_cost = node_total_segments * eth_cost_per_segment
        cumulative_eth_cost += eth_cost

        # ETH reward if lattice beats POW per block
        pow_progress = pow_hash_power * (block + 1)
        total_segments = free_segments + free_segments_from_nodes + premium_segments
        total_segments_filled += total_segments

        eth_reward = eth_reward_per_block if total_segments_filled > pow_progress else 0
        cumulative_eth_reward += eth_reward

        # Record history
        history_total_segments.append(total_segments_filled)
        history_free_segments.append(freeCounter + free_segments_from_nodes)
        history_premium_segments.append(premiumCounter)
        history_pow_progress.append(pow_progress)
        history_eth_cost.append(cumulative_eth_cost)
        history_eth_reward.append(cumulative_eth_reward)

    return {
        "total_segments": history_total_segments,
        "free_segments": history_free_segments,
        "premium_segments": history_premium_segments,
        "pow_progress": history_pow_progress,
        "eth_cost": history_eth_cost,
        "eth_reward": history_eth_reward,
        "final_eth_net": cumulative_eth_reward - cumulative_eth_cost
    }

# -------------------------------
# Run Scenarios
# -------------------------------
results = {}
for n in num_nodes_list:
    results[n] = simulate_lattice_vs_pow(n)

# -------------------------------
# Plot Lattice vs POW
# -------------------------------
plt.figure(figsize=(14,6))
for n in num_nodes_list:
    plt.plot(results[n]["total_segments"], label=f"Lattice Total ({n} nodes)")
plt.plot(results[1]["pow_progress"], 'k--', label="POW Progress")
plt.xlabel("Block")
plt.ylabel("Segments / Hash Units")
plt.title("Lattice Progression vs POW")
plt.legend()
plt.grid(True)
plt.show()

# -------------------------------
# Plot ETH Net Gain
# -------------------------------
plt.figure(figsize=(14,6))
for n in num_nodes_list:
    plt.plot(results[n]["eth_reward"], label=f"ETH Reward ({n} nodes)")
    plt.plot(results[n]["eth_cost"], '--', label=f"ETH Cost ({n} nodes)")
plt.xlabel("Block")
plt.ylabel("ETH")
plt.title("ETH Cost vs Reward per Node Scenario")
plt.legend()
plt.grid(True)
plt.show()

# -------------------------------
# Break-even Analysis
# -------------------------------
print("Break-even Analysis (ETH net gain = reward - cost):")
for n in num_nodes_list:
    net = results[n]["final_eth_net"]
    print(f"{n} nodes: Net ETH = {net:.4f} ({'Profit' if net>0 else 'Loss'})")
