class WorkingMemory:
    def __init__(self):
        self.knowledge_base = {}
        self.learning_history = []
        self.recall_attempts = 0
        self.learning_rate = 0.1
        self.threshold_for_recall = 0.75
        self.max_entries = 80

    def initialize_memory(self, initial_knowledge=None):
        if initial_knowledge:
            for knowledge in initial_knowledge:
                self.add_knowledge(knowledge)

    def add_knowledge(self, new_knowledge):
        # Add new knowledge to the knowledge base with a unique identifier
        id = len(self.knowledge_base) + 1
        self.knowledge_base[id] = {"knowledge": new_knowledge, "recall_attempts": 0}

        if len(self.knowledge_base) > self.max_entries:
            self._forget_oldest()

    def _forget_oldest(self):
        # Remove the oldest knowledge entry from memory to maintain a max number of entries
        oldest_id = min(self.knowledge_base.keys(), key=lambda x: self.knowledge_base[x]["recall_attempts"])
        del self.knowledge_base[oldest_id]

    def learn_from_experience(self, experience):
        # Update the learning history and recall attempts for each piece of knowledge involved in the experience
        for id in experience.get("involved_knowledge", []):
            if id in self.knowledge_base:
                self.knowledge_base[id]["recall_attempts"] += 1

    def retrieve_knowledge(self, query):
        # Retrieve relevant pieces of knowledge based on a given query
        results = []
        for id, knowledge in self.knowledge_base.items():
            similarity_score = self._calculate_similarity(query, knowledge["knowledge"])
            if similarity_score >= self.threshold_for_recall:
                results.append({"id": id, "knowledge": knowledge["knowledge"], "similarity": similarity_score})
        
        return sorted(results, key=lambda x: x["similarity"], reverse=True)

    def _calculate_similarity(self, query, knowledge):
        # Calculate the similarity between a query and stored knowledge
        words_in_query = set(query.lower().split())
        words_in_knowledge = set(knowledge.lower().split())
        
        common_words = words_in_query.intersection(words_in_knowledge)
        total_unique_words = len(words_in_query) + len(words_in_knowledge) - len(common_words)
        
        if not total_unique_words:
            return 0.0
        
        similarity_score = len(common_words) / total_unique_words
        return similarity_score

    def adapt_to_user(self, user_preferences):
        # Adjust the learning and recall parameters based on user preferences
        self.learning_rate *= (1 + sum(user_preferences["learning_rate_adjustment"]))
        self.threshold_for_recall += user_preferences["recall_threshold_shift"]
        
        for id, knowledge in self.knowledge_base.items():
            self.knowledge_base[id]["knowledge"] = self._adapt_knowledge(knowledge, user_preferences)

    def _adapt_knowledge(self, knowledge, user_preferences):
        # Adapt existing knowledge based on user preferences
        adaptation_factor = 1 + sum(user_preferences["adaption_factors"])
        adapted_knowledge = knowledge * adaptation_factor
        return adapted_knowledge

# Example usage:
working_memory = WorkingMemory()
initial_knowledge = [
    "EDEN AUTONOMOUS BUSINESS has 3246 SAGEs",
    "The business generates $100/month per user through PayPal",
    "There are 2198 outreach messages ready for marketing"
]
working_memory.initialize_memory(initial_knowledge)
query = "business revenue"
results = working_memory.retrieve_knowledge(query)
for result in results:
    print(result["knowledge"])