- Refactor lockdrop calculations and other helper code from the simulation notebook to a python module - Add a notebook for experimenting with lockdrop calculations - Add widget buttons to run calculations and export results - Add a script a to setup and run the notebook Reviewed-on: #2 Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com> Co-committed-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
266 lines
14 KiB
Python
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:.1%}", 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]:.1%}" 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]:.1%}" 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:.1%}"],
|
|
'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:.1%}"],
|
|
'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]:.1%}" for year in [5, 4, 3, 2, 1]],
|
|
'Final Allocation ($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]:.1%}" for year in [5, 4, 3, 2, 1]],
|
|
'Final Allocation ($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)
|