# modules/fact_game.py """Enhanced Fact Game Module""" import random from typing import Dict, List, Optional from modules.api_utils import ( fetch_wikipedia_summary, search_wikipedia, fetch_wikidata_entity, fetch_related_topics, ) # Curated list of interesting topics for facts FACT_CATEGORIES = { "Science": [ "Quantum Entanglement", "Black Hole", "DNA", "Photosynthesis", "Theory of Relativity", "Higgs Boson", "Dark Matter", "CRISPR", "Stem Cell", "Nanotechnology", "Artificial Neural Network", ], "History": [ "Ancient Egypt", "Roman Empire", "Renaissance", "Industrial Revolution", "World War II", "Cold War", "French Revolution", "Ming Dynasty", "Viking Age", "Byzantine Empire", "Aztec Empire", ], "Nature": [ "Amazon Rainforest", "Great Barrier Reef", "Mount Everest", "Grand Canyon", "Antarctica", "Sahara Desert", "Northern Lights", "Yellowstone", "Galapagos Islands", "Mariana Trench", ], "Technology": [ "Internet", "Blockchain", "Quantum Computing", "5G Technology", "Virtual Reality", "3D Printing", "Robotics", "Solar Power", "Electric Vehicle", "Space Exploration", "Biotechnology", ], "Culture": [ "Olympics", "UNESCO", "Nobel Prize", "Louvre Museum", "Great Wall of China", "Machu Picchu", "Taj Mahal", "Easter Island", "Stonehenge", "Angkor Wat", ], } def extract_interesting_fact(text: str) -> str: """Extract the most interesting sentence from text""" sentences = text.split(".") # Keywords that often indicate interesting facts interesting_keywords = [ "first", "largest", "smallest", "discovered", "invented", "record", "unique", "only", "famous", "remarkable", "surprising", "estimated", "approximately", "billion", "million", "ancient", "modern", "revolutionary", ] # Score sentences based on interesting keywords scored_sentences = [] for sentence in sentences: if len(sentence.strip()) > 20: # Minimum length score = sum( 1 for keyword in interesting_keywords if keyword.lower() in sentence.lower() ) scored_sentences.append((sentence.strip(), score)) # Sort by score and return the most interesting if scored_sentences: scored_sentences.sort(key=lambda x: x[1], reverse=True) return scored_sentences[0][0] + "." # Fallback to first substantial sentence for sentence in sentences: if len(sentence.strip()) > 50: return sentence.strip() + "." return text[:200] + "..." def generate_random_fact() -> Dict: """Generate a random fact from curated topics""" # Select random category and topic category = random.choice(list(FACT_CATEGORIES.keys())) topic = random.choice(FACT_CATEGORIES[category]) # Fetch summary summary_data = fetch_wikipedia_summary(topic) if not summary_data: return {"error": "Could not fetch fact", "status": False} extract = summary_data.get("extract", "") # Extract interesting fact fact = extract_interesting_fact(extract) return { "fact": fact, "topic": summary_data.get("title", topic), "category": category, "status": True, } def generate_fact_quiz(num_facts: int = 5) -> List[Dict]: """Generate multiple facts for a timed game""" facts = [] used_topics = set() attempts = 0 max_attempts = num_facts * 3 while len(facts) < num_facts and attempts < max_attempts: fact = generate_random_fact() attempts += 1 if fact.get("status") and fact.get("topic") not in used_topics: facts.append(fact) used_topics.add(fact.get("topic")) return facts def generate_themed_facts(theme: str, num_facts: int = 5) -> List[Dict]: """Generate facts based on a specific theme""" facts = [] # Find the category that best matches the theme matching_category = None for category, topics in FACT_CATEGORIES.items(): if theme.lower() in category.lower(): matching_category = category break if not matching_category: # Search for theme in all topics for category, topics in FACT_CATEGORIES.items(): for topic in topics: if theme.lower() in topic.lower(): matching_category = category break if matching_category: break if matching_category: topics = FACT_CATEGORIES[matching_category] random.shuffle(topics) for topic in topics[:num_facts]: summary_data = fetch_wikipedia_summary(topic) if summary_data: extract = summary_data.get("extract", "") fact = extract_interesting_fact(extract) facts.append( { "fact": fact, "topic": summary_data.get("title", topic), "category": matching_category, "status": True, } ) return facts def generate_daily_fact() -> Dict: """Generate a special 'fact of the day'""" # Use current date as seed for consistency from datetime import datetime today = datetime.now().strftime("%Y-%m-%d") random.seed(today) fact = generate_random_fact() fact["is_daily"] = True # Reset random seed random.seed() return fact def generate_fact_challenge(difficulty: str = "Medium") -> Dict: """Generate a fact challenge with true/false question""" fact_data = generate_random_fact() if not fact_data.get("status"): return fact_data # Create a true/false challenge if difficulty == "Easy": # Simple true fact challenge = { "fact": fact_data["fact"], "topic": fact_data["topic"], "is_true": True, "question": "Is this fact true?", "status": True, } elif difficulty == "Medium": # 50/50 chance of modified fact if random.random() > 0.5: # True fact challenge = { "fact": fact_data["fact"], "topic": fact_data["topic"], "is_true": True, "question": "Is this fact true?", "status": True, } else: # Modified fact (make it false) modified_fact = fact_data["fact"] # Simple modifications to make it false replacements = [ ("largest", "smallest"), ("first", "last"), ("most", "least"), ("highest", "lowest"), ("discovered", "invented"), ("ancient", "modern"), ] for old, new in replacements: if old in modified_fact.lower(): modified_fact = modified_fact.replace(old, new) break challenge = { "fact": modified_fact, "topic": fact_data["topic"], "is_true": False, "question": "Is this fact true?", "original_fact": fact_data["fact"], "status": True, } else: # Hard # More complex modifications or completely different topic if random.random() > 0.3: # True fact but more complex challenge = { "fact": fact_data["fact"], "topic": fact_data["topic"], "is_true": True, "question": "Is this fact accurate?", "status": True, } else: # Mix facts from different topics other_fact = generate_random_fact() if other_fact.get("status"): # Combine elements from two different facts mixed_fact = ( fact_data["fact"].split(".")[0] + " and " + other_fact["fact"].split(".")[-1] ) challenge = { "fact": mixed_fact, "topic": fact_data["topic"], "is_true": False, "question": "Is this statement factually correct?", "original_fact": fact_data["fact"], "status": True, } else: # Fallback to medium difficulty return generate_fact_challenge("Medium") return challenge