diff --git a/Armstrong.py b/Armstrong.py index cf8c603..eb71836 100644 --- a/Armstrong.py +++ b/Armstrong.py @@ -1,12 +1,52 @@ -import math -a=int(input("Enter a number to check : ")) -temp=a -ans=0 -while a!=0: - res = a % 10 - ans += math.pow(res,3) - a //=10 -if(temp==ans): - print("This number is armmstrong") -else: - print("This is not armstrong") \ No newline at end of file +def is_armstrong_number(num): + """ + Check if a number is an Armstrong number. + An Armstrong number is a number that is equal to the sum of its own digits + each raised to the power of the number of digits. + + Args: + num (int): The number to check + + Returns: + bool: True if the number is an Armstrong number, False otherwise + """ + if not isinstance(num, int) or num < 0: + return False + + # Convert to string to easily get number of digits + num_str = str(num) + num_digits = len(num_str) + + # Calculate sum of each digit raised to the power of num_digits + total = sum(int(digit) ** num_digits for digit in num_str) + + return total == num + + +def main(): + """Main function to run the Armstrong number checker.""" + try: + # Get input from user with validation + user_input = input("Enter a number to check: ").strip() + + # Validate input is a non-negative integer + if not user_input.isdigit(): + print("Error: Please enter a valid non-negative integer.") + return + + number = int(user_input) + + # Check if it's an Armstrong number + if is_armstrong_number(number): + print(f"{number} is an Armstrong number!") + else: + print(f"{number} is not an Armstrong number.") + + except KeyboardInterrupt: + print("\nOperation cancelled by user.") + except Exception as e: + print(f"An unexpected error occurred: {e}") + + +if __name__ == "__main__": + main() diff --git a/Bubble-Game/index.html b/Bubble-Game/index.html new file mode 100644 index 0000000..d31e6d0 --- /dev/null +++ b/Bubble-Game/index.html @@ -0,0 +1,28 @@ + + + + + + Bubble Number Game + + + +
+

Bubble Number Game

+
+
Target: 5
+
Score: 0
+
Time: 30s
+
+
+ +
+
+ + +
+
+
+ + + \ No newline at end of file diff --git a/Bubble-Game/script.js b/Bubble-Game/script.js new file mode 100644 index 0000000..39526e5 --- /dev/null +++ b/Bubble-Game/script.js @@ -0,0 +1,111 @@ +document.addEventListener('DOMContentLoaded', () => { + const startBtn = document.getElementById('start-btn'); + const resetBtn = document.getElementById('reset-btn'); + const gameArea = document.getElementById('game-area'); + const targetNumber = document.getElementById('target-number'); + const scoreElement = document.getElementById('score'); + const timeElement = document.getElementById('time'); + const messageElement = document.getElementById('message'); + + let score = 0; + let timeLeft = 30; + let gameInterval; + let currentTarget; + let gameActive = false; + + startBtn.addEventListener('click', startGame); + resetBtn.addEventListener('click', resetGame); + + function startGame() { + if (gameActive) return; + gameActive = true; + score = 0; + timeLeft = 30; + scoreElement.textContent = score; + timeElement.textContent = timeLeft; + messageElement.textContent = ''; + startBtn.disabled = true; + resetBtn.disabled = false; + generateNewRound(); + gameInterval = setInterval(updateTimer, 1000); + } + + function resetGame() { + gameActive = false; + clearInterval(gameInterval); + score = 0; + timeLeft = 30; + scoreElement.textContent = score; + timeElement.textContent = timeLeft; + targetNumber.textContent = '5'; + messageElement.textContent = ''; + startBtn.disabled = false; + resetBtn.disabled = true; + clearBubbles(); + } + + function updateTimer() { + timeLeft--; + timeElement.textContent = timeLeft; + if (timeLeft <= 0) { + endGame(); + } + } + + function endGame() { + gameActive = false; + clearInterval(gameInterval); + clearBubbles(); + messageElement.textContent = `Game Over! Final Score: ${score}`; + startBtn.disabled = false; + resetBtn.disabled = true; + } + + function generateNewRound() { + clearBubbles(); + currentTarget = Math.floor(Math.random() * 10) + 1; // 1-10 + targetNumber.textContent = currentTarget; + const bubbleCount = 6; + const numbers = [currentTarget]; + while (numbers.length < bubbleCount) { + const num = Math.floor(Math.random() * 10) + 1; + if (!numbers.includes(num)) { + numbers.push(num); + } + } + // Shuffle numbers + for (let i = numbers.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [numbers[i], numbers[j]] = [numbers[j], numbers[i]]; + } + // Create bubbles + numbers.forEach(num => { + const bubble = document.createElement('div'); + bubble.className = 'bubble'; + bubble.textContent = num; + bubble.style.left = Math.random() * (gameArea.clientWidth - 60) + 'px'; + bubble.style.top = Math.random() * (gameArea.clientHeight - 60) + 'px'; + bubble.addEventListener('click', () => handleBubbleClick(num)); + gameArea.appendChild(bubble); + }); + } + + function handleBubbleClick(num) { + if (!gameActive) return; + if (num === currentTarget) { + score++; + scoreElement.textContent = score; + generateNewRound(); + } else { + // Wrong bubble, maybe penalize or just continue + messageElement.textContent = 'Wrong! Try again.'; + setTimeout(() => messageElement.textContent = '', 1000); + } + } + + function clearBubbles() { + while (gameArea.firstChild) { + gameArea.removeChild(gameArea.firstChild); + } + } +}); \ No newline at end of file diff --git a/Bubble-Game/styles.css b/Bubble-Game/styles.css new file mode 100644 index 0000000..7547ebf --- /dev/null +++ b/Bubble-Game/styles.css @@ -0,0 +1,101 @@ +body { + font-family: Arial, sans-serif; + background-color: #f0f0f0; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + margin: 0; +} + +.game-container { + text-align: center; + background-color: white; + padding: 20px; + border-radius: 10px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + max-width: 600px; + width: 100%; +} + +h1 { + color: #333; + margin-bottom: 20px; +} + +.game-info { + display: flex; + justify-content: space-around; + margin-bottom: 20px; + font-size: 18px; + font-weight: bold; +} + +.game-area { + position: relative; + width: 100%; + height: 400px; + border: 2px solid #333; + border-radius: 10px; + margin-bottom: 20px; + overflow: hidden; + background-color: #e6f3ff; +} + +.bubble { + position: absolute; + width: 60px; + height: 60px; + border-radius: 50%; + background-color: #4CAF50; + color: white; + display: flex; + justify-content: center; + align-items: center; + font-size: 24px; + font-weight: bold; + cursor: pointer; + transition: transform 0.2s; + animation: float 3s ease-in-out infinite; +} + +.bubble:hover { + transform: scale(1.1); +} + +@keyframes float { + 0%, 100% { transform: translateY(0px); } + 50% { transform: translateY(-20px); } +} + +.controls { + margin-bottom: 20px; +} + +button { + padding: 10px 20px; + font-size: 16px; + margin: 0 10px; + cursor: pointer; + border: none; + border-radius: 5px; + background-color: #4CAF50; + color: white; + transition: background-color 0.3s; +} + +button:hover { + background-color: #45a049; +} + +button:disabled { + background-color: #cccccc; + cursor: not-allowed; +} + +.message { + font-size: 18px; + font-weight: bold; + color: #333; + min-height: 24px; +} \ No newline at end of file diff --git a/agent.py b/agent.py new file mode 100644 index 0000000..df60ced --- /dev/null +++ b/agent.py @@ -0,0 +1,264 @@ +import threading +import queue +import time +import random +import logging +from typing import Any, Dict, Optional +from abc import ABC, abstractmethod + +# Configure logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') +logger = logging.getLogger(__name__) + +class MessageBus: + """Thread-safe message bus for agent communication.""" + + def __init__(self): + self._queues: Dict[str, queue.Queue] = {} + self._lock = threading.RLock() + self._shutdown_event = threading.Event() + + def register_agent(self, agent_name: str) -> queue.Queue: + """Register an agent and return its message queue.""" + with self._lock: + if agent_name in self._queues: + raise ValueError(f"Agent '{agent_name}' is already registered") + self._queues[agent_name] = queue.Queue() + return self._queues[agent_name] + + def unregister_agent(self, agent_name: str): + """Unregister an agent.""" + with self._lock: + self._queues.pop(agent_name, None) + + def send_message(self, sender: str, recipient: str, content: Any, timeout: float = 1.0): + """Send a message from sender to recipient.""" + if self._shutdown_event.is_set(): + return + + with self._lock: + if recipient not in self._queues: + logger.warning(f"Message to unknown recipient '{recipient}' from '{sender}' ignored") + return + + message = { + "sender": sender, + "recipient": recipient, + "content": content, + "timestamp": time.time() + } + + try: + self._queues[recipient].put(message, timeout=timeout) + except queue.Full: + logger.error(f"Message queue for '{recipient}' is full, message dropped") + + def shutdown(self): + """Shutdown the message bus.""" + self._shutdown_event.set() + with self._lock: + for agent_queue in self._queues.values(): + # Clear any remaining messages + while not agent_queue.empty(): + try: + agent_queue.get_nowait() + except queue.Empty: + break + +# Global message bus instance +message_bus = MessageBus() + +class Agent(ABC, threading.Thread): + """Base class for all agents with improved error handling and lifecycle management.""" + + def __init__(self, name: str): + super().__init__(daemon=True, name=f"Agent-{name}") + self.name = name + self._running = threading.Event() + self._shutdown_event = threading.Event() + self._message_queue: Optional[queue.Queue] = None + self.logger = logging.getLogger(f"{__name__}.{name}") + + def start(self): + """Start the agent.""" + try: + self._message_queue = message_bus.register_agent(self.name) + self._running.set() + super().start() + self.logger.info(f"Agent '{self.name}' started") + except Exception as e: + self.logger.error(f"Failed to start agent '{self.name}': {e}") + raise + + def stop(self): + """Stop the agent gracefully.""" + self.logger.info(f"Stopping agent '{self.name}'") + self._shutdown_event.set() + self._running.clear() + + if self._message_queue: + # Clear any pending messages + while not self._message_queue.empty(): + try: + self._message_queue.get_nowait() + except queue.Empty: + break + + self.join(timeout=5.0) + if self.is_alive(): + self.logger.warning(f"Agent '{self.name}' did not stop gracefully") + + def send(self, recipient: str, content: Any): + """Send a message to another agent.""" + if not self._running.is_set(): + self.logger.warning(f"Agent '{self.name}' is not running, cannot send message") + return + message_bus.send_message(self.name, recipient, content) + + @abstractmethod + def receive(self, msg: Dict[str, Any]): + """Handle incoming message.""" + pass + + def run(self): + """Main agent loop with proper error handling.""" + self.logger.info(f"Agent '{self.name}' entering main loop") + + while self._running.is_set() and not self._shutdown_event.is_set(): + try: + # Wait for message with timeout to allow shutdown checks + msg = self._message_queue.get(timeout=0.1) + self.receive(msg) + self._message_queue.task_done() + + except queue.Empty: + continue # No message, continue loop + except Exception as e: + self.logger.error(f"Error processing message in agent '{self.name}': {e}") + # Continue processing other messages rather than crashing + + self.logger.info(f"Agent '{self.name}' exiting main loop") + +# Agent that generates random numbers +class NumberAgent(Agent): + def __init__(self, name: str, target: str): + super().__init__(name) + self.target = target + + def run(self): + """Generate random numbers and send them to target agent.""" + super().run() # Call parent run method for message processing + + # Additional behavior: generate numbers periodically + while self._running.is_set() and not self._shutdown_event.is_set(): + try: + num = random.randint(1, 10) + self.logger.info(f"Generated number: {num}") + print(f"🎲 {self.name} generated number: {num}") + self.send(self.target, num) + time.sleep(2) + except Exception as e: + self.logger.error(f"Error in NumberAgent {self.name}: {e}") + time.sleep(1) # Brief pause before retry + + def receive(self, msg: Dict[str, Any]): + """Handle incoming messages.""" + self.logger.debug(f"NumberAgent {self.name} received: {msg}") + +# Agent that adds received numbers +class SumAgent(Agent): + def __init__(self, name: str): + super().__init__(name) + self.total = 0 + self._lock = threading.Lock() + + def receive(self, msg: Dict[str, Any]): + """Handle incoming messages by adding numbers.""" + try: + value = msg["content"] + if not isinstance(value, (int, float)): + self.logger.warning(f"Received non-numeric value: {value}") + return + + with self._lock: + self.total += value + + self.logger.info(f"Added {value} from {msg['sender']}, current total = {self.total}") + print(f"➕ {self.name} received {value} from {msg['sender']}") + print(f" Current total = {self.total}") + + except KeyError: + self.logger.error(f"Message missing 'content' key: {msg}") + except Exception as e: + self.logger.error(f"Error processing message in SumAgent {self.name}: {e}") + +# Agent that monitors system status +class MonitorAgent(Agent): + def __init__(self, name: str): + super().__init__(name) + + def run(self): + """Monitor system status periodically.""" + super().run() # Call parent run method for message processing + + # Additional behavior: periodic status monitoring + while self._running.is_set() and not self._shutdown_event.is_set(): + try: + self.logger.info("System running smoothly...") + print("👁️ System running smoothly...") + time.sleep(5) + except Exception as e: + self.logger.error(f"Error in MonitorAgent {self.name}: {e}") + time.sleep(1) + + def receive(self, msg: Dict[str, Any]): + """Handle incoming messages.""" + self.logger.debug(f"MonitorAgent {self.name} received: {msg}") + +def main(): + """Main function to run the agent system.""" + agents = [] + + def cleanup_agents(): + """Clean up all agents on shutdown.""" + logger.info("Shutting down agents...") + for agent in agents: + try: + agent.stop() + except Exception as e: + logger.error(f"Error stopping agent {agent.name}: {e}") + + # Shutdown message bus + message_bus.shutdown() + logger.info("All agents stopped") + + try: + # Create agents + sum_agent = SumAgent("SumAgent") + num_agent1 = NumberAgent("NumberAgent1", "SumAgent") + num_agent2 = NumberAgent("NumberAgent2", "SumAgent") + monitor_agent = MonitorAgent("Monitor") + + agents = [sum_agent, num_agent1, num_agent2, monitor_agent] + + # Start all agents + logger.info("Starting agents...") + for agent in agents: + agent.start() + + logger.info("Agent system running. Press Ctrl+C to stop.") + + # Keep main thread alive + while True: + time.sleep(1) + + except KeyboardInterrupt: + logger.info("Received shutdown signal") + except Exception as e: + logger.error(f"Unexpected error in main: {e}") + finally: + cleanup_agents() + + +if __name__ == "__main__": + main()