import gradio as gr import numpy as np import matplotlib.pyplot as plt import math from typing import Tuple, Optional import requests import json class BulletDistanceCalculator: """A comprehensive bullet distance calculator with physics modeling.""" def __init__(self): self.gravity = 9.81 # m/s² self.air_density = 1.225 # kg/m³ at sea level def calculate_trajectory(self, initial_velocity: float, angle: float, bullet_mass: float = 0.01, drag_coefficient: float = 0.3, bullet_diameter: float = 0.007) -> Tuple[np.ndarray, np.ndarray, dict]: """ Calculate bullet trajectory with air resistance. Args: initial_velocity: Initial velocity in m/s angle: Launch angle in degrees bullet_mass: Mass of bullet in kg drag_coefficient: Drag coefficient bullet_diameter: Bullet diameter in meters Returns: Tuple of (x_coords, y_coords, results_dict) """ angle_rad = math.radians(angle) vx = initial_velocity * math.cos(angle_rad) vy = initial_velocity * math.sin(angle_rad) # Calculate cross-sectional area area = math.pi * (bullet_diameter / 2) ** 2 # Time step for numerical integration dt = 0.01 max_time = 20 # seconds x_coords = [0] y_coords = [0] t = 0 while t < max_time and y_coords[-1] >= 0: # Calculate drag force velocity = math.sqrt(vx**2 + vy**2) if velocity > 0: drag_force = 0.5 * self.air_density * velocity**2 * drag_coefficient * area drag_x = -drag_force * (vx / velocity) drag_y = -drag_force * (vy / velocity) else: drag_x = drag_y = 0 # Update velocities vx += (drag_x / bullet_mass) * dt vy += ((drag_y / bullet_mass) - self.gravity) * dt # Update positions x = x_coords[-1] + vx * dt y = y_coords[-1] + vy * dt if y < 0: # Ground impact # Linear interpolation to find exact impact point y_prev = y_coords[-1] x_prev = x_coords[-1] t_impact = t - dt + dt * (-y_prev) / (y - y_prev) x_impact = x_prev + vx * (t_impact - t + dt) x_coords.append(x_impact) y_coords.append(0) break x_coords.append(x) y_coords.append(y) t += dt # Calculate results max_height = max(y_coords) range_distance = x_coords[-1] flight_time = t results = { 'range': range_distance, 'max_height': max_height, 'flight_time': flight_time, 'final_velocity': math.sqrt(vx**2 + vy**2), 'impact_angle': math.degrees(math.atan2(vy, vx)) } return np.array(x_coords), np.array(y_coords), results def create_trajectory_plot(x_coords: np.ndarray, y_coords: np.ndarray, results: dict) -> str: """Create a matplotlib plot of the trajectory.""" plt.figure(figsize=(10, 6)) plt.plot(x_coords, y_coords, 'b-', linewidth=2, label='Trajectory') plt.scatter([0], [0], color='green', s=100, label='Launch Point', zorder=5) plt.scatter([x_coords[-1]], [y_coords[-1]], color='red', s=100, label='Impact Point', zorder=5) plt.xlabel('Distance (m)') plt.ylabel('Height (m)') plt.title(f'Bullet Trajectory\nRange: {results["range"]:.1f}m, Max Height: {results["max_height"]:.1f}m') plt.grid(True, alpha=0.3) plt.legend() plt.axis('equal') # Save plot plot_path = "trajectory_plot.png" plt.savefig(plot_path, dpi=150, bbox_inches='tight') plt.close() return plot_path def calculate_bullet_distance(velocity: float, angle: float, mass: float, drag_coeff: float, diameter: float) -> Tuple[str, str, str]: """ Main function for Gradio interface. Returns: Tuple of (results_text, plot_path, detailed_info) """ try: calculator = BulletDistanceCalculator() x_coords, y_coords, results = calculator.calculate_trajectory( velocity, angle, mass, drag_coeff, diameter ) # Create plot plot_path = create_trajectory_plot(x_coords, y_coords, results) # Format results results_text = f""" 🎯 **Bullet Distance Calculation Results** 📏 **Range**: {results['range']:.2f} meters 📈 **Maximum Height**: {results['max_height']:.2f} meters ⏱️ **Flight Time**: {results['flight_time']:.2f} seconds 🚀 **Final Velocity**: {results['final_velocity']:.2f} m/s 📐 **Impact Angle**: {results['impact_angle']:.1f}° """ detailed_info = f""" **Physics Parameters:** - Initial Velocity: {velocity} m/s - Launch Angle: {angle}° - Bullet Mass: {mass} kg - Drag Coefficient: {drag_coeff} - Bullet Diameter: {diameter} m **Environmental Conditions:** - Gravity: {calculator.gravity} m/s² - Air Density: {calculator.air_density} kg/m³ """ return results_text, plot_path, detailed_info except Exception as e: error_msg = f"❌ Error in calculation: {str(e)}" return error_msg, None, error_msg def get_huggingface_model_info(model_name: str) -> str: """Get information about a Hugging Face model.""" try: api_url = f"https://huggingface.co/api/models/{model_name}" response = requests.get(api_url, timeout=10) if response.status_code == 200: model_data = response.json() info = f""" 🤗 **Hugging Face Model Information** **Model**: {model_data.get('modelId', 'Unknown')} **Downloads**: {model_data.get('downloads', 0):,} **Tags**: {', '.join(model_data.get('tags', []))} **Pipeline Tag**: {model_data.get('pipeline_tag', 'N/A')} **Library**: {model_data.get('library_name', 'N/A')} **Last Modified**: {model_data.get('lastModified', 'N/A')} """ return info else: return f"❌ Error fetching model info: HTTP {response.status_code}" except Exception as e: return f"❌ Error connecting to Hugging Face: {str(e)}" # Create Gradio interface with gr.Blocks(title="Bullet Distance Calculator", theme=gr.themes.Soft()) as demo: gr.Markdown(""" # 🎯 Bullet Distance Calculator Calculate bullet trajectory with realistic physics including air resistance, drag, and gravity. This app interfaces with Hugging Face and provides comprehensive ballistics calculations. """) with gr.Tabs(): with gr.TabItem("🎯 Ballistics Calculator"): with gr.Row(): with gr.Column(scale=1): gr.Markdown("### Input Parameters") velocity = gr.Slider( minimum=100, maximum=1000, value=300, step=10, label="Initial Velocity (m/s)", info="Typical rifle: 300-800 m/s" ) angle = gr.Slider( minimum=0, maximum=90, value=30, step=1, label="Launch Angle (degrees)", info="0° = horizontal, 90° = vertical" ) mass = gr.Slider( minimum=0.001, maximum=0.1, value=0.01, step=0.001, label="Bullet Mass (kg)", info="Typical: 0.005-0.02 kg" ) drag_coeff = gr.Slider( minimum=0.1, maximum=1.0, value=0.3, step=0.01, label="Drag Coefficient", info="Typical: 0.2-0.5" ) diameter = gr.Slider( minimum=0.005, maximum=0.02, value=0.007, step=0.001, label="Bullet Diameter (m)", info="Typical: 0.005-0.01 m" ) calculate_btn = gr.Button("🚀 Calculate Trajectory", variant="primary") with gr.Column(scale=2): gr.Markdown("### Results") results_output = gr.Markdown() gr.Markdown("### Trajectory Plot") plot_output = gr.Image(label="Trajectory Visualization") gr.Markdown("### Detailed Information") detailed_output = gr.Markdown() with gr.TabItem("🤗 Hugging Face Integration"): gr.Markdown("### Hugging Face Model Information") with gr.Row(): model_input = gr.Textbox( label="Model Name", placeholder="e.g., microsoft/DialoGPT-medium", value="microsoft/DialoGPT-medium" ) fetch_btn = gr.Button("🔍 Get Model Info", variant="secondary") hf_output = gr.Markdown() with gr.TabItem("📚 About"): gr.Markdown(""" ## About This App This Bullet Distance Calculator provides: - **Realistic Physics**: Includes air resistance, drag, and gravity - **Interactive Visualization**: Real-time trajectory plotting - **Hugging Face Integration**: Access to model information - **Comprehensive Results**: Range, height, flight time, and more ### Physics Model The calculator uses numerical integration to solve the equations of motion: - Accounts for air resistance using drag coefficient - Considers bullet mass and cross-sectional area - Models realistic environmental conditions ### Hugging Face Features - Fetch model information and statistics - Access model metadata and tags - Real-time API integration Built with Gradio and designed for Hugging Face Spaces deployment. """) # Event handlers calculate_btn.click( fn=calculate_bullet_distance, inputs=[velocity, angle, mass, drag_coeff, diameter], outputs=[results_output, plot_output, detailed_output] ) fetch_btn.click( fn=get_huggingface_model_info, inputs=[model_input], outputs=[hf_output] ) if __name__ == "__main__": demo.launch(share=True,mcp_server=True)