lockdrop-simulation/lockdrop/display.py
zramsay 75c7c08496 99/1 for the Star/Galaxy allocation (#12)
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Reviewed-on: #12
Co-authored-by: zramsay <zramsay@noreply.git.vdb.to>
Co-committed-by: zramsay <zramsay@noreply.git.vdb.to>
2025-10-30 13:43:31 +00:00

266 lines
14 KiB
Python

"""
Display and table formatting functions for lockdrop analysis.
This module contains functions for displaying analysis results in formatted tables
and organizing the presentation of calculation results.
"""
import pandas as pd
from decimal import Decimal
from tabulate import tabulate
from .constants import (
PENALTY_RATES, LOCKDROP_ALLOCATION, STAR_ALLOCATION_PERCENT,
GALAXY_ALLOCATION_PERCENT, LOCKDROP_DURATION_BLOCKS, TOTAL_SUPPLY,
NUM_STARS, NUM_GALAXIES, NUM_PLANETS, LOCKDROP_ALLOCATION_PERCENT
)
def print_table_with_borders(df, title=""):
"""Print DataFrame with borders using tabulate."""
if title:
print(f"\n{title}")
print(tabulate(df, headers='keys', tablefmt='grid', showindex=False))
def print_constants_summary():
"""Display core constants as formatted tables."""
print("=" * 80)
print("📊 $Z LOCKDROP DISTRIBUTION - CORE CONSTANTS")
print("=" * 80)
# Lockdrop Allocation Table
lockdrop_df = pd.DataFrame({
'Parameter': ['Total Supply (1 $Z per Urbit ID)', 'Lockdrop Allocation %', 'Lockdrop Allocation ($Z)'],
'Value': [f"{TOTAL_SUPPLY:,}", f"{LOCKDROP_ALLOCATION_PERCENT:.2%}", f"{LOCKDROP_ALLOCATION:,.1f}"]
})
print_table_with_borders(lockdrop_df, "🔒 LOCKDROP ALLOCATION")
# Points Distribution Table
points_df = pd.DataFrame({
'Point Type': ['Galaxies', 'Stars', 'Planets (excl.)'],
'Count': [f"{NUM_GALAXIES:,}", f"{NUM_STARS:,}", f"{NUM_PLANETS:,}"],
'Allocation %': [f"{GALAXY_ALLOCATION_PERCENT:.3%}", f"{STAR_ALLOCATION_PERCENT:.3%}", "0%"]
})
print_table_with_borders(points_df, "🌟 URBIT POINT DISTRIBUTION")
# Penalty Schedule Table
penalty_df = pd.DataFrame({
'Lock Period': ['5 Years', '4 Years', '3 Years', '2 Years', '1 Year'],
'Penalty Rate': [f"{PENALTY_RATES[year]:.2%}" for year in [5, 4, 3, 2, 1]],
'Token % of Max': ['100%', '80%', '60%', '40%', '20%']
})
print_table_with_borders(penalty_df, "⚖️ PENALTY SCHEDULE")
print("\n" + "="*80)
def print_allocation_calculations(allocation_data):
"""Print basic allocation calculation tables."""
lockdrop_allocation_stars = LOCKDROP_ALLOCATION * STAR_ALLOCATION_PERCENT
lockdrop_allocation_galaxies = LOCKDROP_ALLOCATION * GALAXY_ALLOCATION_PERCENT
total_stars_locked = allocation_data['total_stars_locked']
total_galaxies_locked = allocation_data['total_galaxies_locked']
rounding_error_per_star = allocation_data['rounding_error_per_star']
rounding_error_per_galaxy = allocation_data['rounding_error_per_galaxy']
adjusted_max_allocation_per_star = allocation_data['adjusted_max_allocation_per_star']
adjusted_max_allocation_per_galaxy = allocation_data['adjusted_max_allocation_per_galaxy']
adjusted_z_per_star_per_block = allocation_data['adjusted_z_per_star_per_block']
adjusted_z_per_galaxy_per_block = allocation_data['adjusted_z_per_galaxy_per_block']
total_rounding_error_stars = allocation_data['total_rounding_error_stars']
total_rounding_error_galaxies = allocation_data['total_rounding_error_galaxies']
print("=" * 80)
print("🔢 ALLOCATION CALCULATIONS")
print("=" * 80)
# Raw Allocations Table
raw_allocation_per_star = lockdrop_allocation_stars / total_stars_locked if total_stars_locked > 0 else Decimal('0')
raw_allocation_per_galaxy = lockdrop_allocation_galaxies / total_galaxies_locked if total_galaxies_locked > 0 else Decimal('0')
raw_allocations_df = pd.DataFrame({
'Point Type': ['Stars', 'Galaxies'],
'Total Allocation ($Z)': [f"{lockdrop_allocation_stars:,.1f}", f"{lockdrop_allocation_galaxies:,.1f}"],
'Max Per Point ($Z)': [f"{raw_allocation_per_star:,.6f}", f"{raw_allocation_per_galaxy:,.6f}"]
})
print_table_with_borders(raw_allocations_df, "💰 RAW PARTICIPANT ALLOCATIONS")
# Quanta Calculations Table
raw_z_per_star_per_block = raw_allocation_per_star / LOCKDROP_DURATION_BLOCKS if total_stars_locked > 0 else Decimal('0')
raw_z_per_galaxy_per_block = raw_allocation_per_galaxy / LOCKDROP_DURATION_BLOCKS if total_galaxies_locked > 0 else Decimal('0')
quanta_df = pd.DataFrame({
'Point Type': ['Stars', 'Galaxies'],
'Raw Z per Block': [f"{raw_z_per_star_per_block:.15f}", f"{raw_z_per_galaxy_per_block:.15f}"],
'Adjusted Z per Block (q)': [f"{adjusted_z_per_star_per_block:.6f}", f"{adjusted_z_per_galaxy_per_block:.6f}"]
})
print_table_with_borders(quanta_df, "⚙️ QUANTA CALCULATION")
# Adjusted Allocations Table (after quanta calculation)
percentage_rounding_error_stars = total_rounding_error_stars / TOTAL_SUPPLY * 100 if total_stars_locked > 0 else Decimal('0')
percentage_rounding_error_galaxies = total_rounding_error_galaxies / TOTAL_SUPPLY * 100 if total_galaxies_locked > 0 else Decimal('0')
# Separate tables for better readability
star_adjusted_df = pd.DataFrame({
'Metric': ['Adjusted Max per Star', 'Rounding Error per Star', 'Total Rounding Error', 'Rounding Error %'],
'Value': [f"{adjusted_max_allocation_per_star:,.6f} $Z", f"{rounding_error_per_star:.9f} $Z",
f"{total_rounding_error_stars:,.6f} $Z", f"{percentage_rounding_error_stars:.8f}%"],
'Note': ['Before bonus', 'Per star loss', 'Goes to bonus pool', 'Of total supply']
})
galaxy_adjusted_df = pd.DataFrame({
'Metric': ['Adjusted Max per Galaxy', 'Rounding Error per Galaxy', 'Total Rounding Error', 'Rounding Error %'],
'Value': [f"{adjusted_max_allocation_per_galaxy:,.6f} $Z", f"{rounding_error_per_galaxy:.9f} $Z",
f"{total_rounding_error_galaxies:,.6f} $Z", f"{percentage_rounding_error_galaxies:.8f}%"],
'Note': ['Before bonus', 'Per galaxy loss', 'Goes to bonus pool', 'Of total supply']
})
print("\n🎯 QUANTA ADJUSTED PARTICIPANT ALLOCATIONS")
print_table_with_borders(star_adjusted_df, "⭐ Star Adjustments")
print_table_with_borders(galaxy_adjusted_df, "🌌 Galaxy Adjustments")
print("\n" + "="*80)
def print_penalty_analysis(allocation_data):
"""Print penalty system analysis using values before bonus calculations."""
print("=" * 80)
print("⚖️ PENALTY SYSTEM ANALYSIS")
print("=" * 80)
# Use adjusted allocations (after penalties, before bonus distribution)
adjusted_max_allocation_per_star = allocation_data['adjusted_max_allocation_per_star']
adjusted_max_allocation_per_galaxy = allocation_data['adjusted_max_allocation_per_galaxy']
penalty_analysis_df = pd.DataFrame({
'Lock Period': ['5 Years', '4 Years', '3 Years', '2 Years', '1 Year'],
'Penalty Rate': [f"{PENALTY_RATES[year]:.2%}" for year in [5, 4, 3, 2, 1]],
'Star Allocation ($Z)': [f"{adjusted_max_allocation_per_star * (1 - PENALTY_RATES[year]):,.6f}" for year in [5, 4, 3, 2, 1]],
'Galaxy Allocation ($Z)': [f"{adjusted_max_allocation_per_galaxy * (1 - PENALTY_RATES[year]):,.6f}" for year in [5, 4, 3, 2, 1]],
'vs Max Allocation': ['100%', '80%', '60%', '40%', '20%']
})
print_table_with_borders(penalty_analysis_df, "📊 PENALTY ADJUSTED ALLOCATIONS (Before Bonus Distribution)")
print("\n" + "="*80)
def print_participation_summary(allocation_data):
"""Print participation distribution summary."""
stars_counts = allocation_data['stars_counts']
galaxies_counts = allocation_data['galaxies_counts']
total_stars_locked = allocation_data['total_stars_locked']
total_galaxies_locked = allocation_data['total_galaxies_locked']
# Consolidated participation and lock period distribution
participation_df = pd.DataFrame({
'Lock Period': ['1 Year', '2 Years', '3 Years', '4 Years', '5 Years', 'Total'],
'Stars': [f"{stars_counts[year]:,}" for year in [1, 2, 3, 4, 5]] + [f"{total_stars_locked:,}"],
'% of Total Stars': [f"{stars_counts[year]/NUM_STARS:.2%}" for year in [1, 2, 3, 4, 5]] + [f"{total_stars_locked/NUM_STARS:.2%}"],
'Galaxies': [f"{galaxies_counts[year]:,}" for year in [1, 2, 3, 4, 5]] + [f"{total_galaxies_locked:,}"],
'% of Total Galaxies': [f"{galaxies_counts[year]/NUM_GALAXIES:.2%}" for year in [1, 2, 3, 4, 5]] + [f"{total_galaxies_locked/NUM_GALAXIES:.2%}"],
'Total': [f"{stars_counts[year] + galaxies_counts[year]:,}" for year in [1, 2, 3, 4, 5]] + [f"{total_stars_locked + total_galaxies_locked:,}"],
})
print("=" * 80)
print_table_with_borders(participation_df, "🎯 PARTICIPANTS LOCK PERIOD DISTRIBUTION")
print("\n" + "="*80)
def print_bonus_pool_calculations(allocation_data, bonus_data):
"""Print detailed bonus pool calculations."""
stars_counts = allocation_data['stars_counts']
galaxies_counts = allocation_data['galaxies_counts']
adjusted_max_allocation_per_star = allocation_data['adjusted_max_allocation_per_star']
adjusted_max_allocation_per_galaxy = allocation_data['adjusted_max_allocation_per_galaxy']
total_rounding_error_stars = allocation_data['total_rounding_error_stars']
total_rounding_error_galaxies = allocation_data['total_rounding_error_galaxies']
print("=" * 80)
print("🎁 BONUS POOL CALCULATIONS")
print("=" * 80)
# Star Bonus Pool Analysis
star_bonus_df = pd.DataFrame({
'Component': ['Penalty Pool', 'Rounding Error Bonus', 'Total Star Bonus Pool',
'Recipients (5Y Stars)', 'Bonus per 5Y Star', 'Final 5Y Star Allocation'],
'Value': [f"{bonus_data['star_penalty_pool']:,.6f} $Z", f"{total_rounding_error_stars:,.6f} $Z",
f"{bonus_data['star_bonus_pool_total']:,.6f} $Z", f"{stars_counts[5]:,}",
f"{bonus_data['bonus_per_star_5_years']:,.6f} $Z", f"{adjusted_max_allocation_per_star + bonus_data['bonus_per_star_5_years']:,.6f} $Z"]
})
print_table_with_borders(star_bonus_df, "⭐ STAR BONUS POOL ANALYSIS")
# Galaxy Bonus Pool Analysis
galaxy_bonus_df = pd.DataFrame({
'Component': ['Penalty Pool', 'Rounding Error Bonus', 'Total Galaxy Bonus Pool',
'Recipients (5Y Galaxies)', 'Bonus per 5Y Galaxy', 'Final 5Y Galaxy Allocation'],
'Value': [f"{bonus_data['galaxy_penalty_pool']:,.6f} $Z", f"{total_rounding_error_galaxies:,.6f} $Z",
f"{bonus_data['galaxy_bonus_pool_total']:,.6f} $Z", f"{galaxies_counts[5]:,}",
f"{bonus_data['bonus_per_galaxy_5_years']:,.6f} $Z", f"{adjusted_max_allocation_per_galaxy + bonus_data['bonus_per_galaxy_5_years']:,.6f} $Z"]
})
print_table_with_borders(galaxy_bonus_df, "🌌 GALAXY BONUS POOL ANALYSIS")
print("\n" + "="*80)
def print_final_allocations_and_verification(allocation_data, final_data):
"""Print final allocations and verification tables."""
stars_counts = allocation_data['stars_counts']
galaxies_counts = allocation_data['galaxies_counts']
final_star_allocations = final_data['final_star_allocations']
final_galaxy_allocations = final_data['final_galaxy_allocations']
star_z_per_block = final_data['star_z_per_block']
galaxy_z_per_block = final_data['galaxy_z_per_block']
total_stars_allocation = final_data['total_stars_allocation']
total_galaxies_allocation = final_data['total_galaxies_allocation']
print("=" * 80)
print("✅ FINAL ALLOCATIONS & VERIFICATION")
print("=" * 80)
# Star Final Allocations Table
star_final_df = pd.DataFrame({
'Lock Period': ['5 Years', '4 Years', '3 Years', '2 Years', '1 Year'],
'Penalty': [f"{PENALTY_RATES[year]:.2%}" for year in [5, 4, 3, 2, 1]],
'Final Allocation (per star) ($Z)': [f"{final_star_allocations[year]:,.8f}" for year in [5, 4, 3, 2, 1]],
'Z per Block': [f"{star_z_per_block[year]:,.8f}" for year in [5, 4, 3, 2, 1]],
'Participants': [f"{stars_counts[year]:,}" for year in [5, 4, 3, 2, 1]]
})
print_table_with_borders(star_final_df, "⭐ FINAL STAR ALLOCATIONS")
# Galaxy Final Allocations Table
galaxy_final_df = pd.DataFrame({
'Lock Period': ['5 Years', '4 Years', '3 Years', '2 Years', '1 Year'],
'Penalty': [f"{PENALTY_RATES[year]:.2%}" for year in [5, 4, 3, 2, 1]],
'Final Allocation (per galaxy) ($Z)': [f"{final_galaxy_allocations[year]:,.8f}" for year in [5, 4, 3, 2, 1]],
'Z per Block': [f"{galaxy_z_per_block[year]:,.8f}" for year in [5, 4, 3, 2, 1]],
'Participants': [f"{galaxies_counts[year]:,}" for year in [5, 4, 3, 2, 1]]
})
print_table_with_borders(galaxy_final_df, "🌌 FINAL GALAXY ALLOCATIONS")
# Verification and Rounding Error Analysis
lockdrop_allocation_stars = LOCKDROP_ALLOCATION * STAR_ALLOCATION_PERCENT
lockdrop_allocation_galaxies = LOCKDROP_ALLOCATION * GALAXY_ALLOCATION_PERCENT
final_rounding_error_stars = lockdrop_allocation_stars - total_stars_allocation
final_rounding_error_galaxies = lockdrop_allocation_galaxies - total_galaxies_allocation
final_rounding_error = final_rounding_error_stars + final_rounding_error_galaxies
verification_df = pd.DataFrame({
'Category': ['Star Allocations', 'Galaxy Allocations', 'Combined'],
'Calculated Total': [f"{total_stars_allocation:.8f} $Z", f"{total_galaxies_allocation:.8f} $Z",
f"{total_stars_allocation + total_galaxies_allocation:.8f} $Z"],
'Expected Total': [f"{lockdrop_allocation_stars:.8f} $Z", f"{lockdrop_allocation_galaxies:.8f} $Z",
f"{LOCKDROP_ALLOCATION:.8f} $Z"],
'Rounding Error': [f"{final_rounding_error_stars:.8f} $Z", f"{final_rounding_error_galaxies:.8f} $Z",
f"{final_rounding_error:.8f} $Z"]
})
print_table_with_borders(verification_df, "🔍 ALLOCATION VERIFICATION")
print("\n📝 NOTE: Final rounding errors go to Zenith Foundation")
print("\n" + "="*80)
def print_analysis_tables(allocation_data, bonus_data, final_data):
"""Print comprehensive analysis tables - calls all the detailed sections."""
print_participation_summary(allocation_data)
print_allocation_calculations(allocation_data)
print_penalty_analysis(allocation_data)
print_bonus_pool_calculations(allocation_data, bonus_data)
print_final_allocations_and_verification(allocation_data, final_data)