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()