help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • Blog
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
real-estate-bot
/
src
RSK World
real-estate-bot
Real Estate Bot - Python + Flask + OpenAI + SQLite + Property Search + AI Chatbot + Viewing Scheduler
src
  • __pycache__
  • __init__.py476 B
  • ai_recommendation_engine.py20.6 KB
  • app.py7.8 KB
  • blockchain_integration.py1.5 KB
  • chatbot.py15.5 KB
  • database.py18.4 KB
  • image_enhancer.py7.9 KB
  • multilang_support.py8.8 KB
  • neighborhood_analyzer.py6.1 KB
  • price_prediction_engine.py25.1 KB
  • property_search.py15.6 KB
  • virtual_tour_manager.py21.8 KB
  • voice_assistant.py27.6 KB
multilang_support.pyrequirements.txt__init__.pyvirtual_tour_manager.py
src/multilang_support.py
Raw Download
Find: Go to:
"""
Multi-Language Support with Real-Time Translation
Author: RSK World (https://rskworld.in)
Founded by: Molla Samser
Designer & Tester: Rima Khatun
Contact: info@rskworld.com, +91 93305 39277
Year: 2026
"""

import os
import json
from typing import Dict, Any, List
from datetime import datetime

class MultiLanguageSupport:
    def __init__(self):
        """Initialize Multi-Language Support"""
        self.supported_languages = {
            'en': 'English',
            'hi': 'हिन्दी (Hindi)',
            'bn': 'বাংলা (Bengali)',
            'ta': 'தமிழ் (Tamil)',
            'te': 'తెలుగు (Telugu)',
            'mr': 'मराठी (Marathi)',
            'gu': 'ગુજરાતી (Gujarati)',
            'kn': 'ಕನ್ನಡ (Kannada)',
            'ml': 'മലയാളം (Malayalam)',
            'pa': 'ਪੰਜਾਬੀ (Punjabi)',
            'ur': 'اردو (Urdu)',
            'es': 'Español (Spanish)',
            'fr': 'Français (French)',
            'de': 'Deutsch (German)',
            'it': 'Italiano (Italian)',
            'pt': 'Português (Portuguese)',
            'ru': 'Русский (Russian)',
            'ja': '日本語 (Japanese)',
            'ko': '한국어 (Korean)',
            'zh': '中文 (Chinese)',
            'ar': 'العربية (Arabic)'
        }
        
        self.translations = self._load_translations()
        self.default_language = 'en'
    
    def _load_translations(self) -> Dict[str, Dict[str, str]]:
        """Load translation data"""
        translations = {
            'en': {
                'welcome': 'Welcome to Real Estate Bot',
                'search_properties': 'Search Properties',
                'schedule_viewing': 'Schedule Viewing',
                'property_details': 'Property Details',
                'price_prediction': 'Price Prediction',
                'virtual_tour': 'Virtual Tour',
                'contact_us': 'Contact Us',
                'bedrooms': 'Bedrooms',
                'bathrooms': 'Bathrooms',
                'area': 'Area',
                'price': 'Price',
                'location': 'Location',
                'amenities': 'Amenities',
                'year_built': 'Year Built'
            },
            'hi': {
                'welcome': 'रियल एस्टेट बॉट में आपका स्वागत है',
                'search_properties': 'प्रॉपर्टी खोजें',
                'schedule_viewing': 'व्यूइंग शेड्यूल करें',
                'property_details': 'प्रॉपर्टी विवरण',
                'price_prediction': 'मूल्य भविष्यवाणी',
                'virtual_tour': 'वर्चुअल टूर',
                'contact_us': 'संपर्क करें',
                'bedrooms': 'बेडरूम',
                'bathrooms': 'बाथरूम',
                'area': 'क्षेत्रफल',
                'price': 'कीमत',
                'location': 'स्थान',
                'amenities': 'सुविधाएं',
                'year_built': 'निर्माण वर्ष'
            },
            'bn': {
                'welcome': 'রিযেল এস্টেট বটে আপনাকে স্বাগতম',
                'search_properties': 'সম্পত্তি খুঁজুন',
                'schedule_viewing': 'ভিউয়িং শিডিউল করুন',
                'property_details': 'সম্পত্তির বিবরণ',
                'price_prediction': 'মূল্য পূর্বাভাস',
                'virtual_tour': 'ভার্চুয়াল ট্যুর',
                'contact_us': 'যোগাযোগ করুন',
                'bedrooms': 'বেডরুম',
                'bathrooms': 'বাথরুম',
                'area': 'এলাকা',
                'price': 'দাম',
                'location': 'অবস্থান',
                'amenities': '�ুবিধা',
                'year_built': 'নির্মাণ বছর'
            }
        }
        
        return translations
    
    def translate_text(self, text: str, target_language: str) -> str:
        """Translate text to target language"""
        if target_language not in self.supported_languages:
            return text
        
        if target_language == self.default_language:
            return text
        
        # Check if we have a direct translation
        translations = self.translations.get(target_language, {})
        if text in translations:
            return translations[text]
        
        # For demo purposes, return placeholder
        # In production, integrate with Google Translate API
        return f"[{self.supported_languages[target_language]}] {text}"
    
    def get_supported_languages(self) -> Dict[str, str]:
        """Get list of supported languages"""
        return self.supported_languages
    
    def detect_language(self, text: str) -> str:
        """Detect language of text (simplified)"""
        # Simple language detection based on characters
        if any(char in text for char in 'ऀँंःअआइईउऊऋएऐओऔकखगघङचछजझञटठडढणतथदधनपफबभमयरलवशषसह'):
            return 'hi'  # Hindi
        elif any(char in text for char in 'অআইঈউঊঋএঐওঔকখগঘঙচছজঝঞটঠডঢণতথদধনপফবভমযরলবশষসহ'):
            return 'bn'  # Bengali
        elif any(char in text for char in 'அஆஇஈஉஊஎஏஐஒஓஔகஙசஞடணதநபமயரலவழளறன'):
            return 'ta'  # Tamil
        else:
            return 'en'  # Default to English
    
    def format_property_data(self, property_data: Dict[str, Any], language: str) -> Dict[str, Any]:
        """Format property data in specified language"""
        formatted_data = property_data.copy()
        
        # Translate key fields
        translatable_fields = ['title', 'description', 'location']
        for field in translatable_fields:
            if field in formatted_data:
                formatted_data[f'{field}_translated'] = self.translate_text(
                    formatted_data[field], language
                )
        
        # Translate amenities
        if 'amenities' in formatted_data:
            translated_amenities = [
                self.translate_text(amenity, language) 
                for amenity in formatted_data['amenities']
            ]
            formatted_data['amenities_translated'] = translated_amenities
        
        return formatted_data
    
    def get_currency_symbol(self, language: str) -> str:
        """Get currency symbol for language"""
        currency_map = {
            'en': '₹',
            'hi': '₹',
            'bn': '₹',
            'ta': '₹',
            'te': '₹',
            'mr': '₹',
            'gu': '₹',
            'kn': '₹',
            'ml': '₹',
            'pa': '₹',
            'ur': '₹',
            'es': '€',
            'fr': '€',
            'de': '€',
            'it': '€',
            'pt': '€',
            'ru': '₽',
            'ja': '¥',
            'ko': '₩',
            'zh': '¥',
            'ar': 'ر.س'
        }
        
        return currency_map.get(language, '₹')
    
    def format_price(self, price: float, language: str) -> str:
        """Format price according to language conventions"""
        symbol = self.get_currency_symbol(language)
        
        if language in ['en', 'hi', 'bn', 'ta', 'te', 'mr', 'gu', 'kn', 'ml', 'pa', 'ur']:
            # Indian format
            formatted_price = f"{price:,.0f}".replace(',', ',')
            return f"{symbol} {formatted_price}"
        else:
            # International format
            formatted_price = f"{price:,.0f}"
            return f"{symbol}{formatted_price}"
    
    def translate_chat_response(self, response: str, user_language: str) -> str:
        """Translate chat response to user's language"""
        if user_language == self.default_language:
            return response
        
        # Split response into sentences and translate
        sentences = response.split('. ')
        translated_sentences = []
        
        for sentence in sentences:
            if sentence.strip():
                translated = self.translate_text(sentence.strip(), user_language)
                translated_sentences.append(translated)
        
        return '. '.join(translated_sentences)
211 lines•8.8 KB
python
requirements.txt
Raw Download
Find: Go to:
flask==2.3.3
openai==1.3.5
requests==2.31.0
python-dotenv==1.0.0
flask-cors==4.0.0
jinja2==3.1.2
gunicorn==21.2.0
numpy==1.24.3
pandas==2.0.3
scikit-learn==1.3.0
opencv-python==4.8.1.78
Pillow==10.0.1
speechrecognition==3.10.0
pyttsx3==2.90
joblib==1.3.2
web3==6.11.0
17 lines•284 B
text
src/__init__.py
Raw Download
Find: Go to:
"""
Real Estate Bot - Python Package Initialization
Author: RSK World (https://rskworld.in)
Founded by: Molla Samser
Designer & Tester: Rima Khatun
Contact: info@rskworld.com, +91 93305 39277
Year: 2026
Description: Real estate chatbot for property search, inquiries, and scheduling viewings
"""

__version__ = "1.0.0"
__author__ = "RSK World"
__email__ = "info@rskworld.com"
__description__ = "AI-powered real estate chatbot for property search and management"
15 lines•476 B
python
src/virtual_tour_manager.py
Raw Download
Find: Go to:
"""
Virtual Property Tour Manager with 360° View Support
Author: RSK World (https://rskworld.in)
Founded by: Molla Samser
Designer & Tester: Rima Khatun
Contact: info@rskworld.com, +91 93305 39277
Year: 2026
Description: Advanced virtual tour system with 360° panoramic views and interactive features
"""

import os
import json
import base64
from typing import List, Dict, Any, Optional
from datetime import datetime
import cv2
import numpy as np
from PIL import Image, ImageEnhance
import io

class VirtualTourManager:
    def __init__(self, database_manager):
        """
        Initialize Virtual Tour Manager
        
        Args:
            database_manager: Database manager instance
        """
        self.db_manager = database_manager
        self.tour_data_dir = 'data/virtual_tours'
        self.panorama_dir = 'data/panoramas'
        os.makedirs(self.tour_data_dir, exist_ok=True)
        os.makedirs(self.panorama_dir, exist_ok=True)
        
        # Supported formats for virtual tours
        self.supported_formats = {
            '360_image': ['.jpg', '.jpeg', '.png'],
            '360_video': ['.mp4', '.webm', '.mov'],
            '3d_model': ['.glb', '.gltf', '.obj'],
            'floor_plan': ['.svg', '.png', '.jpg']
        }
    
    def create_virtual_tour(self, property_id: int, tour_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Create a new virtual tour for a property
        
        Args:
            property_id: Property ID
            tour_data: Tour configuration data
            
        Returns:
            Created tour information
        """
        tour_id = f"tour_{property_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
        
        tour_config = {
            'tour_id': tour_id,
            'property_id': property_id,
            'created_at': datetime.now().isoformat(),
            'title': tour_data.get('title', f'Virtual Tour - Property {property_id}'),
            'description': tour_data.get('description', ''),
            'scenes': [],
            'navigation': tour_data.get('navigation', {}),
            'hotspots': tour_data.get('hotspots', []),
            'settings': {
                'auto_rotate': tour_data.get('auto_rotate', True),
                'start_scene': tour_data.get('start_scene', 0),
                'transition_speed': tour_data.get('transition_speed', 1.0),
                'enable_controls': tour_data.get('enable_controls', True),
                'fullscreen_enabled': tour_data.get('fullscreen_enabled', True)
            }
        }
        
        # Process scenes
        for i, scene in enumerate(tour_data.get('scenes', [])):
            processed_scene = self._process_scene(scene, i, tour_id)
            tour_config['scenes'].append(processed_scene)
        
        # Save tour configuration
        tour_file = os.path.join(self.tour_data_dir, f'{tour_id}.json')
        with open(tour_file, 'w') as f:
            json.dump(tour_config, f, indent=2)
        
        return {
            'success': True,
            'tour_id': tour_id,
            'message': 'Virtual tour created successfully',
            'tour_config': tour_config
        }
    
    def _process_scene(self, scene: Dict[str, Any], scene_index: int, tour_id: str) -> Dict[str, Any]:
        """Process individual scene for virtual tour"""
        processed_scene = {
            'scene_id': f"scene_{scene_index}",
            'name': scene.get('name', f'Scene {scene_index + 1}'),
            'type': scene.get('type', '360_image'),
            'media_path': scene.get('media_path', ''),
            'thumbnail': scene.get('thumbnail', ''),
            'hotspots': scene.get('hotspots', []),
            'navigation': {
                'look_at': scene.get('look_at', [0, 0, 0]),
                'camera_position': scene.get('camera_position', [0, 0, 5]),
                'fov': scene.get('fov', 75)
            },
            'lighting': scene.get('lighting', {
                'ambient': 0.6,
                'directional': 0.4,
                'direction': [1, 1, -1]
            }),
            'audio': scene.get('audio', {
                'background_music': '',
                'narration': '',
                'ambient_sounds': []
            })
        }
        
        # Process media based on type
        if processed_scene['type'] == '360_image':
            processed_scene['media_path'] = self._process_360_image(
                scene.get('media_path'), tour_id, scene_index
            )
        elif processed_scene['type'] == '360_video':
            processed_scene['media_path'] = self._process_360_video(
                scene.get('media_path'), tour_id, scene_index
            )
        elif processed_scene['type'] == '3d_model':
            processed_scene['media_path'] = self._process_3d_model(
                scene.get('media_path'), tour_id, scene_index
            )
        
        return processed_scene
    
    def _process_360_image(self, image_path: str, tour_id: str, scene_index: int) -> str:
        """Process 360° panoramic image"""
        if not image_path:
            return ''
        
        try:
            # Load and enhance the image
            image = Image.open(image_path)
            
            # Enhance image quality
            enhancer = ImageEnhance.Brightness(image)
            image = enhancer.enhance(1.1)
            
            enhancer = ImageEnhance.Contrast(image)
            image = enhancer.enhance(1.1)
            
            enhancer = ImageEnhance.Sharpness(image)
            image = enhancer.enhance(1.1)
            
            # Save processed image
            processed_filename = f'{tour_id}_scene_{scene_index}_360.jpg'
            processed_path = os.path.join(self.panorama_dir, processed_filename)
            image.save(processed_path, 'JPEG', quality=95)
            
            return f'panoramas/{processed_filename}'
            
        except Exception as e:
            print(f"Error processing 360 image: {e}")
            return image_path
    
    def _process_360_video(self, video_path: str, tour_id: str, scene_index: int) -> str:
        """Process 360° video"""
        if not video_path:
            return ''
        
        # For video processing, we would typically use FFmpeg
        # For now, return the original path
        return video_path
    
    def _process_3d_model(self, model_path: str, tour_id: str, scene_index: int) -> str:
        """Process 3D model"""
        if not model_path:
            return ''
        
        # For 3D model processing, we would use tools like Blender
        # For now, return the original path
        return model_path
    
    def get_virtual_tour(self, tour_id: str) -> Optional[Dict[str, Any]]:
        """Get virtual tour configuration"""
        tour_file = os.path.join(self.tour_data_dir, f'{tour_id}.json')
        
        if not os.path.exists(tour_file):
            return None
        
        try:
            with open(tour_file, 'r') as f:
                tour_config = json.load(f)
            
            return tour_config
            
        except Exception as e:
            print(f"Error loading tour {tour_id}: {e}")
            return None
    
    def generate_tour_viewer_html(self, tour_id: str) -> str:
        """Generate HTML for virtual tour viewer"""
        tour_config = self.get_virtual_tour(tour_id)
        
        if not tour_config:
            return "<div>Tour not found</div>"
        
        html_template = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{tour_config['title']} - Virtual Tour</title>
    <script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
    <script src="https://unpkg.com/aframe-event-set-component@5.0.0/dist/aframe-event-set-component.min.js"></script>
    <style>
        body {{
            margin: 0;
            font-family: Arial, sans-serif;
            overflow: hidden;
        }}
        
        .tour-controls {{
            position: fixed;
            top: 20px;
            left: 20px;
            z-index: 1000;
            background: rgba(0,0,0,0.7);
            color: white;
            padding: 15px;
            border-radius: 10px;
            max-width: 300px;
        }}
        
        .scene-selector {{
            margin-bottom: 15px;
        }}
        
        .scene-btn {{
            display: block;
            width: 100%;
            margin: 5px 0;
            padding: 8px;
            background: #3498db;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }}
        
        .scene-btn:hover {{
            background: #2980b9;
        }}
        
        .scene-btn.active {{
            background: #e74c3c;
        }}
        
        .tour-info {{
            position: fixed;
            bottom: 20px;
            right: 20px;
            background: rgba(0,0,0,0.7);
            color: white;
            padding: 15px;
            border-radius: 10px;
            max-width: 300px;
        }}
        
        .hotspot {{
            position: absolute;
            width: 30px;
            height: 30px;
            background: #e74c3c;
            border-radius: 50%;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-weight: bold;
            z-index: 100;
        }}
        
        .hotspot-info {{
            position: absolute;
            background: white;
            color: black;
            padding: 10px;
            border-radius: 5px;
            display: none;
            z-index: 101;
            max-width: 200px;
        }}
    </style>
</head>
<body>
    <div class="tour-controls">
        <h3>Virtual Tour Controls</h3>
        <div class="scene-selector">
            <h4>Scenes:</h4>
            {self._generate_scene_buttons(tour_config['scenes'])}
        </div>
        <div class="tour-settings">
            <label>
                <input type="checkbox" id="autoRotate" checked> Auto Rotate
            </label>
            <br>
            <label>
                <input type="checkbox" id="fullscreen"> Fullscreen
            </label>
        </div>
    </div>
    
    <div class="tour-info">
        <h4>{tour_config['title']}</h4>
        <p>{tour_config['description']}</p>
        <small>Use mouse to look around, scroll to zoom</small>
    </div>
    
    <a-scene embedded style="height: 100vh; width: 100vw;">
        <a-assets>
            {self._generate_scene_assets(tour_config['scenes'])}
        </a-assets>
        
        {self._generate_scene_elements(tour_config['scenes'])}
        
        <a-sky id="sky"></a-sky>
        
        <a-camera id="camera" 
                  look-controls="enabled: true"
                  wasd-controls="enabled: false">
        </a-camera>
    </a-scene>
    
    <script>
        let currentScene = 0;
        const scenes = {json.dumps([scene['scene_id'] for scene in tour_config['scenes']])};
        const tourConfig = {json.dumps(tour_config)};
        
        function loadScene(sceneIndex) {{
            const scene = tourConfig.scenes[sceneIndex];
            const sky = document.querySelector('#sky');
            
            if (scene.type === '360_image') {{
                sky.setAttribute('src', `#${{scene.scene_id}}_image`);
            }} else if (scene.type === '360_video') {{
                sky.setAttribute('src', `#${{scene.scene_id}}_video`);
            }}
            
            // Update camera position
            const camera = document.querySelector('#camera');
            camera.setAttribute('position', scene.navigation.camera_position.join(' '));
            camera.setAttribute('look-at', scene.navigation.look_at.join(' '));
            
            // Update active button
            document.querySelectorAll('.scene-btn').forEach((btn, index) => {{
                btn.classList.toggle('active', index === sceneIndex);
            }});
            
            currentScene = sceneIndex;
        }}
        
        function setupHotspots() {{
            const scene = tourConfig.scenes[currentScene];
            
            // Remove existing hotspots
            document.querySelectorAll('.hotspot').forEach(el => el.remove());
            
            // Add hotspots for current scene
            scene.hotspots.forEach((hotspot, index) => {{
                const hotspotEl = document.createElement('div');
                hotspotEl.className = 'hotspot';
                hotspotEl.style.left = hotspot.position[0] + '%';
                hotspotEl.style.top = hotspot.position[1] + '%';
                hotspotEl.textContent = index + 1;
                
                const infoEl = document.createElement('div');
                infoEl.className = 'hotspot-info';
                infoEl.innerHTML = `
                    <strong>${{hotspot.title}}</strong><br>
                    ${{hotspot.description}}
                `;
                
                hotspotEl.appendChild(infoEl);
                
                hotspotEl.addEventListener('mouseenter', () => {{
                    infoEl.style.display = 'block';
                }});
                
                hotspotEl.addEventListener('mouseleave', () => {{
                    infoEl.style.display = 'none';
                }});
                
                if (hotspot.action) {{
                    hotspotEl.addEventListener('click', () => {{
                        if (hotspot.action.type === 'navigate_to_scene') {{
                            loadScene(hotspot.action.scene_index);
                        }}
                    }});
                }}
                
                document.body.appendChild(hotspotEl);
            }});
        }}
        
        // Initialize
        document.addEventListener('DOMContentLoaded', () => {{
            loadScene(0);
            setupHotspots();
            
            // Setup scene buttons
            document.querySelectorAll('.scene-btn').forEach((btn, index) => {{
                btn.addEventListener('click', () => loadScene(index));
            }});
            
            // Setup controls
            document.getElementById('autoRotate').addEventListener('change', (e) => {{
                const camera = document.querySelector('#camera');
                if (e.target.checked) {{
                    camera.setAttribute('animation', 'property: rotation; to: 0 360 0; dur: 60s; loop: true');
                }} else {{
                    camera.removeAttribute('animation');
                }}
            }});
            
            document.getElementById('fullscreen').addEventListener('change', (e) => {{
                if (e.target.checked) {{
                    document.documentElement.requestFullscreen();
                }} else {{
                    document.exitFullscreen();
                }}
            }});
        }});
    </script>
</body>
</html>
        """
        
        return html_template
    
    def _generate_scene_buttons(self, scenes: List[Dict[str, Any]]) -> str:
        """Generate HTML buttons for scene selection"""
        buttons = []
        for i, scene in enumerate(scenes):
            active_class = 'active' if i == 0 else ''
            buttons.append(f'<button class="scene-btn {active_class}" onclick="loadScene({i})">{scene["name"]}</button>')
        return '\n'.join(buttons)
    
    def _generate_scene_assets(self, scenes: List[Dict[str, Any]]) -> str:
        """Generate A-Frame assets for scenes"""
        assets = []
        for scene in scenes:
            if scene['type'] == '360_image':
                assets.append(f'<img id="{scene["scene_id"]}_image" src="{scene["media_path"]}" crossorigin="anonymous">')
            elif scene['type'] == '360_video':
                assets.append(f'<video id="{scene["scene_id"]}_video" src="{scene["media_path"]}" autoplay loop muted crossorigin="anonymous"></video>')
        return '\n'.join(assets)
    
    def _generate_scene_elements(self, scenes: List[Dict[str, Any]]) -> str:
        """Generate A-Frame scene elements"""
        elements = []
        for scene in scenes:
            # Add lighting
            if scene.get('lighting'):
                lighting = scene['lighting']
                direction = lighting.get('direction', [1, 1, -1])
                direction_str = ' '.join(map(str, direction))
                elements.append(f'''
                    <a-light type="ambient" color="#fff" intensity="{lighting.get('ambient', 0.6)}"></a-light>
                    <a-light type="directional" color="#fff" intensity="{lighting.get('directional', 0.4)}" 
                             position="{direction_str}"></a-light>
                ''')
        return '\n'.join(elements)
    
    def create_interactive_floor_plan(self, property_id: int, floor_plan_data: Dict[str, Any]) -> Dict[str, Any]:
        """Create interactive floor plan with hotspots"""
        floor_plan_id = f"floor_plan_{property_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
        
        floor_plan_config = {
            'floor_plan_id': floor_plan_id,
            'property_id': property_id,
            'created_at': datetime.now().isoformat(),
            'title': floor_plan_data.get('title', f'Floor Plan - Property {property_id}'),
            'image_path': floor_plan_data.get('image_path', ''),
            'dimensions': floor_plan_data.get('dimensions', {}),
            'rooms': floor_plan_data.get('rooms', []),
            'hotspots': floor_plan_data.get('hotspots', []),
            'measurements': floor_plan_data.get('measurements', {}),
            'interactive_features': {
                'enable_room_hover': floor_plan_data.get('enable_room_hover', True),
                'enable_measurement_tool': floor_plan_data.get('enable_measurement_tool', True),
                'enable_3d_view': floor_plan_data.get('enable_3d_view', True),
                'enable_furniture_placement': floor_plan_data.get('enable_furniture_placement', False)
            }
        }
        
        # Save floor plan configuration
        floor_plan_file = os.path.join(self.tour_data_dir, f'{floor_plan_id}.json')
        with open(floor_plan_file, 'w') as f:
            json.dump(floor_plan_config, f, indent=2)
        
        return {
            'success': True,
            'floor_plan_id': floor_plan_id,
            'message': 'Interactive floor plan created successfully',
            'config': floor_plan_config
        }
    
    def generate_ar_overlay_data(self, property_id: int) -> Dict[str, Any]:
        """Generate AR overlay data for mobile AR viewing"""
        property_data = self.db_manager.get_property_by_id(property_id)
        
        if not property_data:
            return {'success': False, 'error': 'Property not found'}
        
        ar_data = {
            'property_id': property_id,
            'ar_markers': [],
            'overlays': [],
            'tracking_data': {
                'marker_type': 'image',
                'marker_size': 0.1,
                'tracking_confidence': 0.8
            }
        }
        
        # Generate AR markers for different rooms
        rooms = ['Living Room', 'Bedroom', 'Kitchen', 'Bathroom']
        for i, room in enumerate(rooms):
            ar_data['ar_markers'].append({
                'marker_id': f'marker_{i}',
                'room_name': room,
                'position': [i * 2, 0, 0],
                'content': {
                    'title': room,
                    'description': f'Virtual {room} view',
                    'media_url': f'ar_content/{property_id}_{room.lower().replace(" ", "_")}.glb',
                    'scale': [1, 1, 1],
                    'rotation': [0, 0, 0]
                }
            })
        
        # Add information overlays
        ar_data['overlays'] = [
            {
                'type': 'price_info',
                'content': f"₹{property_data.get('price', 0):,}",
                'position': [0, 2, 0],
                'style': 'large_text'
            },
            {
                'type': 'property_details',
                'content': f"{property_data.get('bedrooms', 0)}BHK • {property_data.get('area_sqft', 0)} sqft",
                'position': [0, 1.5, 0],
                'style': 'medium_text'
            }
        ]
        
        return {
            'success': True,
            'ar_data': ar_data,
            'message': 'AR data generated successfully'
        }
    
    def get_tour_analytics(self, tour_id: str) -> Dict[str, Any]:
        """Get analytics data for a virtual tour"""
        # This would typically track user interactions, view times, etc.
        # For now, return mock analytics
        
        analytics = {
            'tour_id': tour_id,
            'total_views': 1250,
            'unique_viewers': 890,
            'average_view_time': 245,  # seconds
            'completion_rate': 0.78,
            'most_viewed_scene': 'scene_2',
            'drop_off_points': ['scene_0', 'scene_3'],
            'device_breakdown': {
                'desktop': 0.65,
                'mobile': 0.28,
                'tablet': 0.07
            },
            'interaction_data': {
                'hotspot_clicks': 342,
                'scene_transitions': 1890,
                'fullscreen_usage': 0.45,
                'auto_rotate_usage': 0.72
            }
        }
        
        return analytics
591 lines•21.8 KB
python
🚀 Support RSK World

Subscribe to our YouTube channel for latest tutorials & updates!



Click subscribe & support our work ❤️

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer