From b8680f8c07ac4a070eae611e81ccb103201b9a30 Mon Sep 17 00:00:00 2001 From: Prathamesh Musale Date: Tue, 12 Aug 2025 16:34:50 +0530 Subject: [PATCH] Add borders to output tables --- lockdrop_calculations.py | 257 +++++++++++++++++++++++++++++++++------ 1 file changed, 222 insertions(+), 35 deletions(-) diff --git a/lockdrop_calculations.py b/lockdrop_calculations.py index e1b6021..59bb69b 100644 --- a/lockdrop_calculations.py +++ b/lockdrop_calculations.py @@ -13,6 +13,7 @@ import seaborn as sns import json import os from collections import defaultdict +from tabulate import tabulate # Configure decimal precision getcontext().prec = 28 @@ -48,6 +49,13 @@ PENALTY_RATES = { } +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 configure_matplotlib(): """Configure matplotlib settings for consistent plots.""" plt.style.use('seaborn-v0_8') @@ -80,8 +88,7 @@ def print_constants_summary(): '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("\nšŸ”’ LOCKDROP ALLOCATION") - print(lockdrop_df.to_string(index=False)) + print_table_with_borders(lockdrop_df, "šŸ”’ LOCKDROP ALLOCATION") # Points Distribution Table points_df = pd.DataFrame({ @@ -89,17 +96,15 @@ def print_constants_summary(): 'Count': [f"{NUM_GALAXIES:,}", f"{NUM_STARS:,}", f"{NUM_PLANETS:,}"], 'Allocation %': ['0.39%', '99.61%', '0%'] }) - print("\n⭐ URBIT POINTS DISTRIBUTION") - print(points_df.to_string(index=False)) + print_table_with_borders(points_df, "⭐ URBIT POINTS DISTRIBUTION") # Lockdrop Parameters Table params_df = pd.DataFrame({ 'Parameter': ['Block Duration', 'Max Point Lock Duration (5 yrs)', 'Total Blocks', 'Star Allocation %', 'Galaxy Allocation %'], 'Value': [f"{BLOCK_DURATION_SECONDS} seconds", f"{LOCKDROP_DURATION_SECONDS:,.0f} seconds", - f"{LOCKDROP_DURATION_BLOCKS:,}", f"{STAR_ALLOCATION_PERCENT:.6f}", f"{GALAXY_ALLOCATION_PERCENT:.6f}"] + f"{LOCKDROP_DURATION_BLOCKS:,}", f"{STAR_ALLOCATION_PERCENT:.6%}", f"{GALAXY_ALLOCATION_PERCENT:.6%}"] }) - print("\nā±ļø LOCKDROP PARAMETERS") - print(params_df.to_string(index=False)) + print_table_with_borders(params_df, "ā±ļø LOCKDROP PARAMETERS") print("\n" + "="*80) @@ -308,31 +313,199 @@ def generate_test_output(final_data): return output -def print_analysis_tables(allocation_data, bonus_data, final_data): - """Print comprehensive analysis tables.""" +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'] + 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) + rounding_error_per_star = raw_allocation_per_star - adjusted_max_allocation_per_star + rounding_error_per_galaxy = raw_allocation_per_galaxy - adjusted_max_allocation_per_galaxy + 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': ['Final allocation', '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': ['Final allocation', 'Per galaxy loss', 'Goes to bonus pool', 'Of total supply'] + }) + + print("\nšŸŽÆ 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(): + """Print penalty system analysis.""" + print("=" * 80) + print("āš–ļø PENALTY SYSTEM ANALYSIS") + print("=" * 80) + + # Theoretical penalty analysis (before bonus distribution) + base_allocations = calculate_base_allocations() + adjusted_max_allocation_per_star = base_allocations['adjusted_max_allocation_per_star'] + adjusted_max_allocation_per_galaxy = base_allocations['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'] - 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'] print("=" * 80) print("šŸ“ˆ DYNAMIC LOCKDROP ANALYSIS") print("=" * 80) - # Participation rates - star_participation_rate = total_stars_locked / NUM_STARS - galaxy_participation_rate = total_galaxies_locked / NUM_GALAXIES + # 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_table_with_borders(participation_df, "šŸŽÆ PARTICIPANTS LOCK PERIOD DISTRIBUTION") + print("\n" + "="*80) - print(f"\nšŸ“Š PARTICIPATION RATES") - print(f" Stars: {star_participation_rate:.1%} ({total_stars_locked:,}/{NUM_STARS:,})") - print(f" Galaxies: {galaxy_participation_rate:.1%} ({total_galaxies_locked:,}/{NUM_GALAXIES:,})") - # Final allocations table - print("\n⭐ FINAL STAR ALLOCATIONS") +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_components = [] + for years in [1, 2, 3, 4]: + star_count = stars_counts[years] + penalty = PENALTY_RATES[years] + if star_count > 0: + component_amount = adjusted_max_allocation_per_star * star_count * penalty + star_bonus_components.append(f"{years}Y Stars: {component_amount:,.2f} $Z") + + 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_components = [] + for years in [1, 2, 3, 4]: + galaxy_count = galaxies_counts[years] + penalty = PENALTY_RATES[years] + if galaxy_count > 0: + component_amount = adjusted_max_allocation_per_galaxy * galaxy_count * penalty + galaxy_bonus_components.append(f"{years}Y Galaxies: {component_amount:,.2f} $Z") + + 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") + + # Show bonus pool sources if there are penalties + if star_bonus_components: + print(f"\nšŸ’” Star Bonus Pool Sources:") + for component in star_bonus_components: + print(f" • {component}") + + if galaxy_bonus_components: + print(f"\nšŸ’” Galaxy Bonus Pool Sources:") + for component in galaxy_bonus_components: + print(f" • {component}") + + 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]], @@ -340,9 +513,9 @@ def print_analysis_tables(allocation_data, bonus_data, final_data): 'Z per Block': [f"{star_z_per_block[year]:.12f}" for year in [5, 4, 3, 2, 1]], 'Participants': [f"{stars_counts[year]:,}" for year in [5, 4, 3, 2, 1]] }) - print(star_final_df.to_string(index=False)) + print_table_with_borders(star_final_df, "⭐ FINAL STAR ALLOCATIONS") - print("\n🌌 FINAL GALAXY 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]], @@ -350,23 +523,37 @@ def print_analysis_tables(allocation_data, bonus_data, final_data): 'Z per Block': [f"{galaxy_z_per_block[year]:.12f}" for year in [5, 4, 3, 2, 1]], 'Participants': [f"{galaxies_counts[year]:,}" for year in [5, 4, 3, 2, 1]] }) - print(galaxy_final_df.to_string(index=False)) + print_table_with_borders(galaxy_final_df, "🌌 FINAL GALAXY ALLOCATIONS") - # Bonus pool summary - print("\nšŸŽ BONUS POOL SUMMARY") - bonus_summary_df = pd.DataFrame({ - 'Component': ['Star Bonus Pool', 'Galaxy Bonus Pool', 'Total Bonus Distributed'], - 'Value': [ - f"{bonus_data['star_bonus_pool_total']:,.6f} $Z", - f"{bonus_data['galaxy_bonus_pool_total']:,.6f} $Z", - f"{bonus_data['star_bonus_pool_total'] + bonus_data['galaxy_bonus_pool_total']:,.6f} $Z" - ] + # 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:.12f} $Z", f"{total_galaxies_allocation:.12f} $Z", + f"{total_stars_allocation + total_galaxies_allocation:.12f} $Z"], + 'Expected Total': [f"{lockdrop_allocation_stars:.12f} $Z", f"{lockdrop_allocation_galaxies:.12f} $Z", + f"{LOCKDROP_ALLOCATION:.12f} $Z"], + 'Rounding Error': [f"{final_rounding_error_stars:.12f} $Z", f"{final_rounding_error_galaxies:.12f} $Z", + f"{final_rounding_error:.12f} $Z"] }) - print(bonus_summary_df.to_string(index=False)) - + print_table_with_borders(verification_df, "šŸ” ALLOCATION VERIFICATION") print("\n" + "="*80) +def print_analysis_tables(allocation_data, bonus_data, final_data): + """Print comprehensive analysis tables - calls all the detailed sections.""" + print_allocation_calculations(allocation_data) + print_penalty_analysis() + print_participation_summary(allocation_data) + print_bonus_pool_calculations(allocation_data, bonus_data) + print_final_allocations_and_verification(allocation_data, final_data) + + def create_visualization(allocation_data, final_data): """Create comprehensive visualization plots.""" stars_counts = allocation_data['stars_counts']