import gradio as gr from PIL import Image import os from dotenv import load_dotenv from simple_salesforce import Salesforce from datetime import datetime import shutil import base64 import pytz import hashlib import statistics # Load environment variables load_dotenv() SF_USERNAME = os.getenv("SF_USERNAME") SF_PASSWORD = os.getenv("SF_PASSWORD") SF_SECURITY_TOKEN = os.getenv("SF_SECURITY_TOKEN") # Validate Salesforce credentials if not all([SF_USERNAME, SF_PASSWORD, SF_SECURITY_TOKEN]): raise ValueError("Missing Salesforce credentials. Set SF_USERNAME, SF_PASSWORD, and SF_SECURITY_TOKEN in environment variables.") # Initialize Salesforce connection try: sf = Salesforce( username=SF_USERNAME, password=SF_PASSWORD, security_token=SF_SECURITY_TOKEN, domain='login' ) except Exception as e: print(f"Salesforce connection failed: {str(e)}") raise # Valid milestones VALID_MILESTONES = ["Planning", "Foundation", "Walls Erected", "Interior Furnishing", "Completed"] # Adjust the timezone to IST local_timezone = pytz.timezone("Asia/Kolkata") # Mock Hugging Face image analysis (replace with real model integration) def analyze_image_with_hf(image_path): img = Image.open(image_path) detected_elements = [] width, height = img.size total_pixels = width * height img_data = list(img.convert('RGB').getdata()) gray_pixels = sum(1 for pixel in img_data if sum(pixel[:3]) / 3 < 128) / len(img_data) color_variance = statistics.variance([sum(pixel[:3]) / 3 for pixel in img_data]) if len(img_data) > 1 else 0 # Adjusted logic to detect completed construction, overriding small size if (color_variance > 2000 and gray_pixels < 0.4 and any(keyword in os.path.basename(image_path).lower() for keyword in ["window", "door", "roof"])) or \ (total_pixels > 800000 and gray_pixels < 0.4 and color_variance > 2000): detected_elements.extend(["roof", "windows", "doors", "cladding", "finished"]) elif total_pixels < 200000 and color_variance < 800: detected_elements.append("planning") elif gray_pixels > 0.6 and total_pixels > 400000: detected_elements.append("foundation") elif gray_pixels > 0.35 and total_pixels > 800000 and color_variance > 1500: detected_elements.append("walls") elif gray_pixels < 0.25 or any(keyword in os.path.basename(image_path).lower() for keyword in ["interior", "plumbing", "electrical", "ceiling"]): detected_elements.extend(["interior", "electrical_wiring", "plumbing_pipes"]) else: detected_elements.append("walls") return detected_elements # Image processing and Salesforce upload with live preview def process_image(images, project_name): try: if not images or len(images) == 0: return "Error: Please upload at least one image to proceed.", None, "Pending", "", "", 0 results_html = [] upload_statuses = [] milestones = [] progresses = [] for image in images: img = None try: img = Image.open(image) except Exception as e: if "cannot identify image file" in str(e): return f"Error: Unsupported image format '{os.path.basename(image)}'. Please use JPG, JPEG, PNG, or convert to a supported format.", None, "Failure", "", "", 0 return f"Error: Failed to open image '{os.path.basename(image)}' - {str(e)}", None, "Failure", "", "", 0 image_size_mb = os.path.getsize(image) / (1024 * 1024) if image_size_mb > 20: return "Error: One or more images exceed 20MB.", None, "Failure", "", "", 0 if not str(image).lower().endswith(('.jpg', '.jpeg', '.png', '.avif')): return "Error: Only JPG, JPEG, PNG, or AVIF images are supported.", None, "Failure", "", "", 0 upload_dir = "public_uploads" os.makedirs(upload_dir, exist_ok=True) unique_id = datetime.now().strftime("%Y%m%d%H%M%S") image_filename = f"{unique_id}_{os.path.basename(image)}" saved_image_path = os.path.join(upload_dir, image_filename) shutil.copy(image, saved_image_path) with open(saved_image_path, 'rb') as image_file: image_data = base64.b64encode(image_file.read()).decode('utf-8') file_url = "" try: content_version = { 'Title': image_filename, 'PathOnClient': saved_image_path, 'VersionData': image_data } content_version_result = sf.ContentVersion.create(content_version) content_version_id = content_version_result['id'] file_url = f"https://sathkruthatechsolutionspri8-dev-ed.develop.lightning.force.com/{content_version_id}" except Exception as e: if "STORAGE_LIMIT_EXCEEDED" in str(e): file_url = "Upload skipped due to storage limit" else: return f"Error: Failed to upload image to Salesforce - {str(e)}", None, "Failure", "", "", 0 detected_elements = analyze_image_with_hf(image) completed_tasks = [] not_completed_tasks = [] all_tasks = { "Planning": [ "Initial project outline and objectives have been established.", "Preliminary designs and architectural plans are drafted.", "Stakeholder meetings and initial approvals are completed." ], "Foundation": [ "Site preparation, including clearing and leveling, is finished.", "Excavation for the foundation has been completed.", "Concrete pouring for the foundation, including footings and slabs, is done.", "Initial structural inspections for the foundation have been passed." ], "Walls Erected": [ "The concrete framework, including columns and beams, is in place.", "All structural walls have been erected and stabilized.", "Temporary scaffolding and safety measures are installed for ongoing work.", "Initial inspections for structural integrity have been completed." ], "Interior Furnishing": [ "Plumbing and electrical groundwork installations are completed.", "Interior walls are fully implemented.", "Flooring installation is completed.", "Painting and fixtures are installed." ], "Completed": [ "Roofing installation and weatherproofing are completed.", "Windows, doors, and exterior cladding are installed.", "Interior work, including electrical, plumbing, and HVAC systems, is fully implemented.", "Finishing touches, such as flooring, painting, and fixtures, are completed.", "All phases of the project are finished, including final inspections and approvals." ] } if any(elem == "planning" for elem in detected_elements): completed_tasks.extend(all_tasks["Planning"]) final_milestone = "Planning" percent_complete = 10 elif any(elem == "foundation" for elem in detected_elements): completed_tasks.extend(all_tasks["Foundation"]) final_milestone = "Foundation" percent_complete = 30 elif any(elem == "walls" for elem in detected_elements): completed_tasks.extend(all_tasks["Walls Erected"]) final_milestone = "Walls Erected" percent_complete = 50 elif any(elem in ["interior", "electrical_wiring", "plumbing_pipes"] for elem in detected_elements): completed_tasks.extend(all_tasks["Interior Furnishing"]) final_milestone = "Interior Furnishing" percent_complete = 80 elif all(elem in ["roof", "windows", "doors", "cladding", "finished"] for elem in detected_elements if elem in ["roof", "windows", "doors", "cladding", "finished"]): completed_tasks.extend(all_tasks["Completed"]) final_milestone = "Completed" percent_complete = 100 else: completed_tasks.extend(all_tasks["Walls Erected"]) final_milestone = "Walls Erected" percent_complete = 50 all_possible_tasks = [task for sublist in all_tasks.values() for task in sublist] not_completed_tasks = [task for task in all_possible_tasks if task not in completed_tasks] completed_html = "".join([f'
{final_milestone}
{percent_complete}%
Project is fully completed as of 02:35 PM IST, June 20, 2025.
{final_milestone}
{percent_complete}%
Construction is in progress at {final_milestone} stage as of 02:35 PM IST, June 20, 2025.