CoolFace
Apppublic

shantanu9/rewards_system

sourceHugging Facemitupdated 1y agoView on Hugging Face
0likes
app.py367 linesDownload Raw Back to root
1import gradio as gr2import pandas as pd3import locale4import numpy as np5 6USD_INR_RATE = 85  # 1 USD = 85 INR7 8def format_indian_number(num):9    """Format number in Indian number system (e.g., 1,23,456)"""10    s = str(int(num)) # Convert to integer and then string11    r = ''12    for i, c in enumerate(reversed(s)):13        if i == 3 or (i > 3 and (i - 1) % 2 == 0):14            r = ',' + r15        r = c + r16    return r17 18def format_us_number(num):19    """Format number in US number system (e.g., 1,000)"""20    return f"{int(num):,}" # Convert to integer and format with commas21 22def calculate_bonus_points(referrals: int) -> int:23    """24    Return the non-cumulative bonus points for the given number of referrals,25    using milestones at 5, 10, 15, 20, 25, 30, 35, 40, 45, 50. 26    Above 50, the user gets a gift hamper (no extra points).27    """28    # Define bonus tiers as a list of (threshold, points) tuples29    bonus_tiers = [30        (50, 9800),31        (40, 9800),32        (35, 8100),33        (30, 8100),34        (25, 6250),35        (20, 4550),36        (15, 4550),37        (10, 2700),38        (5, 100),39        (0, 0)40    ]41    42    # Find the first tier where referrals >= threshold43    for threshold, points in bonus_tiers:44        if referrals >= threshold:45            return points46    47    return 0  # Default case, should never reach here48 49def percent_to_decimal(val):50    return float(val) / 100.051 52def validate_percentage(val: float, name: str) -> float:53    """Validate that a value is a valid percentage between 0 and 100."""54    if not isinstance(val, (int, float)):55        raise ValueError(f"{name} must be a number")56    if val < 0 or val > 100:57        raise ValueError(f"{name} must be between 0 and 100")58    return float(val)59 60def validate_positive_number(val: float, name: str) -> float:61    """Validate that a value is a positive number."""62    if not isinstance(val, (int, float)):63        raise ValueError(f"{name} must be a number")64    if val < 0:65        raise ValueError(f"{name} must be positive")66    return float(val)67 68def simulate_referral(69    installs_millions,70    mau_percent,71    baseline_referees_percent,72    referrer_reward_points,73    referee_reward_points,74    point_to_rupee,75    average_referrals,76):77    """78    Calculate referral campaign metrics based on user inputs.79    """80    try:81        # Validate inputs82        installs_millions = validate_positive_number(installs_millions, "Lifetime installs")83        mau_percent = validate_percentage(mau_percent, "MAU percentage")84        baseline_referees_percent = validate_percentage(baseline_referees_percent, "Referrers percentage")85        referrer_reward_points = validate_positive_number(referrer_reward_points, "Referrer reward points")86        referee_reward_points = validate_positive_number(referee_reward_points, "Referee reward points")87        point_to_rupee = validate_positive_number(point_to_rupee, "Points to rupee conversion")88        average_referrals = validate_positive_number(average_referrals, "Average referrals")89 90        installs = installs_millions * 1_000_00091        mau = installs * percent_to_decimal(mau_percent)92        number_of_referees = mau * percent_to_decimal(baseline_referees_percent)93        total_users_referred = number_of_referees * average_referrals94        95        if total_users_referred == 0:96            return ("0", "0", "0", "0", "₹ 0.00", "US$ 0.00", "₹ 0.00", "US$ 0.00")  # Return zeros as formatted strings if no referrals97            98        total_base_points_referrers = number_of_referees * average_referrals * referrer_reward_points99        total_base_points_referred = number_of_referees * average_referrals * referee_reward_points100        bonus_points_per_referrer = calculate_bonus_points(average_referrals)101        total_bonus_points_referrers = int(number_of_referees * bonus_points_per_referrer)102        total_points_awarded = (103            total_base_points_referrers104            + total_base_points_referred105            + total_bonus_points_referrers106        )107        total_rupee_cost = total_points_awarded * point_to_rupee108        total_usd_cost = round(total_rupee_cost / USD_INR_RATE, 2)109        cpi_referral = total_rupee_cost / total_users_referred if total_users_referred > 0 else 0110        cpi_usd = round(cpi_referral / USD_INR_RATE, 2) if total_users_referred > 0 else 0111        112        return (113            format_indian_number(total_users_referred),114            format_indian_number(total_base_points_referrers),115            format_indian_number(total_base_points_referred),116            format_indian_number(total_bonus_points_referrers),117            f"₹ {format_indian_number(total_rupee_cost)}",118            f"US$ {total_usd_cost:.2f}",119            f"₹ {format_indian_number(cpi_referral)}",120            f"US$ {cpi_usd:.2f}"121        )122    except Exception as e:123        # Log the error and return zeros as formatted strings124        print(f"Error in simulation: {str(e)}")125        return ("0", "0", "0", "0", "₹ 0.00", "US$ 0.00", "₹ 0.00", "US$ 0.00")126 127def calculate_individual_rewards(128    num_referrals,129    referrer_reward_points,130    point_to_rupee131):132    """133    Calculate rewards for an individual referrer based on number of referrals.134    """135    base_points = num_referrals * referrer_reward_points136    bonus_points = calculate_bonus_points(num_referrals)137    total_points = base_points + bonus_points138    total_rupee_value = total_points * point_to_rupee139    return {140        "Number of Referrals": num_referrals,141        "Base Points": base_points,142        "Bonus Points": bonus_points,143        "Total Points": total_points,144        "Total Rupee Value (₹)": total_rupee_value145    }146 147def update_individual_rewards(num_refs, referrer_reward_points, referee_reward_points, point_to_rupee):148    rewards_data = []149    for i in range(1, int(num_refs) + 1):150        rewards_data.append(calculate_individual_rewards(151            i, referrer_reward_points, point_to_rupee152        ))153    # Eligible rupee value for the entered number of referrals154    eligible = float(rewards_data[-1]["Total Rupee Value (₹)"]) if rewards_data else 0.0155    return pd.DataFrame(rewards_data), eligible156 157individual_rewards_table = gr.Dataframe(158    headers=["Number of Referrals", "Base Points", "Bonus Points", "Total Points", "Total Rupee Value (₹)"],159    label="Rewards for Different Referral Counts",160    interactive=False,161    elem_id="output-grey-table"162)163 164# New: Table for Tab 1 showing the new tier structure165def get_tier_table(point_to_rupee=0.1, referrer_reward_points=30):166    # Define the rows as per your table167    rows = [168        ("1 – 4", 1, 4),169        ("5", 5, 5),170        ("6 – 9", 6, 9),171        ("10", 10, 10),172        ("11 – 14", 11, 14),173        ("15", 15, 15),174        ("16 – 19", 16, 19),175        ("20", 20, 20),176        ("21 – 24", 21, 24),177        ("25", 25, 25),178        ("26 – 29", 26, 29),179        ("30", 30, 30),180        ("31 – 34", 31, 34),181        ("35", 35, 35),182        ("36 – 39", 36, 39),183        ("40", 40, 40),184        ("41 – 44", 41, 44),185        ("45", 45, 45),186        ("46 – 50", 46, 50),187        ("51 +", 51, 100),188    ]189    data = []190    for label, start, end in rows:191        if label == "51 +":192            data.append([label, "–", "Gift hamper (no extra points)", "–", "–"])193            continue194        base_min = referrer_reward_points * start195        base_max = referrer_reward_points * end196        if start == end:197            base_points = f"{int(base_min)}"198        else:199            base_points = f"{int(base_min)} – {int(base_max)}"200        # Bonus201        bonus = calculate_bonus_points(start)202        if start == end and bonus > 0:203            bonus_str = f"+{int(bonus)}"204        elif bonus > 0:205            bonus_str = f"+{int(bonus)}"206        else:207            bonus_str = "–"208        # Total points209        total_min = base_min + bonus210        total_max = base_max + bonus211        if start == end:212            total_points = f"{int(total_min)}"213        else:214            total_points = f"{int(total_min)} – {int(total_max)}"215        # Rupee value (integer, no decimals, no commas)216        rupee_min = int(total_min * point_to_rupee)217        rupee_max = int(total_max * point_to_rupee)218        if start == end:219            rupee_val = f"₹ {rupee_min}"220        else:221            rupee_val = f"₹ {rupee_min} – ₹ {rupee_max}"222        data.append([label, base_points, bonus_str, total_points, rupee_val])223    df = pd.DataFrame(data, columns=["Referrals Made", "Base Points (30 pts × referrals)", "Tier Bonus (one-time, not cumulative)", "Total Points", "Rupee Value (₹0.10 / pt)"])224    return df225 226# Create Gradio interface227with gr.Blocks() as demo:228    gr.Markdown("## Referral Rewards Simulator")229    gr.Markdown("Adjust the inputs to simulate the cost and effectiveness of referral rewards.")230 231    with gr.Tabs():232        with gr.TabItem("Campaign Overview"):233            with gr.Row():234                with gr.Column():235                    installs_millions = gr.Number(value=1.7, label="Lifetime installs (in millions)")236                    mau_percent = gr.Number(value=10, label="MAU as % of installs", precision=2, elem_id="mau-percent")237                    baseline_referees_percent = gr.Number(value=10, label="Referrers as % of MAU", precision=2, elem_id="ref-percent")238                    average_referrals = gr.Number(value=5, label="Average # of referrals per referee")239                    referrer_reward_points = gr.Number(value=30, label="Referrer reward per referral (points)")240                    referee_reward_points = gr.Number(value=30, label="Referee reward per referral (points)")241                    point_to_rupee = gr.Number(value=0.1, label="Points-to-rupee conversion (e.g., 0.1 for ₹0.10)")242 243                with gr.Column():244                    total_users_referred_out = gr.Textbox(label="Total users referred", interactive=False, elem_id="output-grey")245                    total_base_points_referrers_out = gr.Textbox(label="Total base points to referrers (A)", interactive=False, elem_id="output-grey")246                    total_base_points_referred_out = gr.Textbox(label="Total base points to referees (B)", interactive=False, elem_id="output-grey")247                    total_bonus_points_referrers_out = gr.Textbox(label="Total bonus points to referrers (C)", interactive=False, elem_id="output-grey")248                    with gr.Row():249                        total_rupee_cost_out = gr.Textbox(label="Total rupee cost of rewards (₹)", interactive=False, elem_id="output-grey")250                        total_usd_cost_out = gr.Textbox(label="Total cost (US$)", interactive=False, elem_id="output-grey")251                    with gr.Row():252                        cpi_referral_out = gr.Textbox(label="CPI (₹ per referred user)", interactive=False, elem_id="output-grey")253                        cpi_usd_out = gr.Textbox(label="CPI (US$ per referred user)", interactive=False, elem_id="output-grey")254                    gr.Markdown(f"**Conversion rate used:** 1 USD = {USD_INR_RATE} INR")255 256            gr.Markdown("### Bonus Tier Logic")257            tier_table = gr.Dataframe(258                value=get_tier_table(),259                headers=["Referrals Made", "Base Points (30 pts × referrals)", "Tier Bonus (one-time, not cumulative)", "Total Points", "Rupee Value (₹0.10 / pt)"],260                label="Bonus Tier Table",261                interactive=False,262                elem_id="output-grey-table"263            )264 265        with gr.TabItem("Individual User Perspective"):266            with gr.Row():267                with gr.Column():268                    num_referrals = gr.Number(value=3, label="Number of Referrals")269                    eligible_rupee_value = gr.Number(label="Eligible Rupee Value (₹)", interactive=False, elem_id="output-grey")270                    # Horizontal summary table for selected referral counts271                    horizontal_ref_counts = [5, 10, 15, 20, 25, 30, 35, 40, 50]272                    def horizontal_eligible_table(referrer_reward_points, referee_reward_points, point_to_rupee):273                        data = {"Number of Referrals": horizontal_ref_counts}274                        data["Eligible Rupee Value (₹)"] = [275                            f"₹{format_indian_number(calculate_individual_rewards(n, referrer_reward_points, point_to_rupee)['Total Rupee Value (₹)'])}"276                            for n in horizontal_ref_counts277                        ]278                        return pd.DataFrame(data).T279                    horizontal_table = gr.Dataframe(280                        value=None,281                        headers=[str(n) for n in horizontal_ref_counts],282                        label="Quick View: Eligible Rupee Value for Key Referral Counts",283                        interactive=False,284                        elem_id="output-grey-table"285                    )286                    # Update horizontal table on load and on input change287                    def update_horizontal_table(referrer_reward_points, referee_reward_points, point_to_rupee):288                        data = {str(n): f"₹{int(calculate_individual_rewards(n, referrer_reward_points, point_to_rupee)['Total Rupee Value (₹)'])}" for n in horizontal_ref_counts}289                        df = pd.DataFrame([data], index=["Eligible Rupee Value (₹)"])290                        return df291                    demo.load(292                        fn=update_horizontal_table,293                        inputs=[referrer_reward_points, referee_reward_points, point_to_rupee],294                        outputs=[horizontal_table]295                    )296                    referrer_reward_points.change(update_horizontal_table, [referrer_reward_points, referee_reward_points, point_to_rupee], [horizontal_table])297                    referee_reward_points.change(update_horizontal_table, [referrer_reward_points, referee_reward_points, point_to_rupee], [horizontal_table])298                    point_to_rupee.change(update_horizontal_table, [referrer_reward_points, referee_reward_points, point_to_rupee], [horizontal_table])299                    num_referrals.change(300                        fn=update_individual_rewards,301                        inputs=[num_referrals, referrer_reward_points, referee_reward_points, point_to_rupee],302                        outputs=[individual_rewards_table, eligible_rupee_value]303                    )304                    # Populate table and eligible value on load305                    demo.load(306                        fn=update_individual_rewards,307                        inputs=[num_referrals, referrer_reward_points, referee_reward_points, point_to_rupee],308                        outputs=[individual_rewards_table, eligible_rupee_value]309                    )310 311    # Define how inputs are passed to the simulation function312    demo.load(313        fn=simulate_referral,314        inputs=[315            installs_millions,316            mau_percent,317            baseline_referees_percent,318            referrer_reward_points,319            referee_reward_points,320            point_to_rupee,321            average_referrals322        ],323        outputs=[324            total_users_referred_out,325            total_base_points_referrers_out,326            total_base_points_referred_out,327            total_bonus_points_referrers_out,328            total_rupee_cost_out,329            total_usd_cost_out,330            cpi_referral_out,331            cpi_usd_out332        ]333    )334    # Also update on any input change335    for inp in [installs_millions, mau_percent, baseline_referees_percent, referrer_reward_points, referee_reward_points, point_to_rupee, average_referrals]:336        inp.change(337            fn=simulate_referral,338            inputs=[339                installs_millions,340                mau_percent,341                baseline_referees_percent,342                referrer_reward_points,343                referee_reward_points,344                point_to_rupee,345                average_referrals346            ],347            outputs=[348                total_users_referred_out,349                total_base_points_referrers_out,350                total_base_points_referred_out,351                total_bonus_points_referrers_out,352                total_rupee_cost_out,353                total_usd_cost_out,354                cpi_referral_out,355                cpi_usd_out356            ]357        )358 359# Add custom CSS for grey background on output fields360demo.css = """361#output-grey > div, #output-grey-table .dataframe { background-color: #f0f0f0 !important; }362#output-grey-table .dataframe td { background-color: #f0f0f0 !important; }363"""364 365# Launch the Gradio app366if __name__ == "__main__":367    demo.launch()