El jueves, 9 de junio de 2016, 11:33:04 (UTC-3), Garret L escribió: > > Hi, I'm new to this forum, so this may have already been mentioned, but is > there a way to make multiple parts of a single card hidden using cloze > deletion? >
I feel you bro, I was actually looking for the same. I gave a glimpse at Peter's cloze.py code, and although it is not that hard to follow I could not set my mind to code a new card type class (Multi-cloze deletion class) that inherited from the cloze class. I have exams next week and I can't afford to spend time on this right now. I am sure that Peter would be able to perform with great ease some modifications to his own cloze.py code to fit your needs. There is a function in it that does "create sister cards"; maybe discarding it from the code is a first step approach. I will adjunt cloze.py code # # cloze.py <[email protected]> # import re from mnemosyne.libmnemosyne.translator import _ from mnemosyne.libmnemosyne.card import Card from mnemosyne.libmnemosyne.plugin import Plugin from mnemosyne.libmnemosyne.card_type import CardType from mnemosyne.libmnemosyne.fact_view import FactView cloze_re = re.compile(r"\[(.+?)\]", re.DOTALL) class Cloze(CardType): """CardType to do cloze deletion on a string, e.g. "The political parties in the US are the [democrats] and the [republicans]." would give the following cards: Q:The political parties in the US are the [...] and the republicans. A:democrats Q:The political parties in the US are the democrats and the [...]. A:republicans Illustration of a CardType which does not use the traditional FactView mechanism. This is implemented by creating cards which contain extra_data entries "cloze" and "index", containing e.g. "democrats" and 0. Storing both the cloze and its index allows us to have enough data to support all possible editing operations. """ id = "5" name = _("Cloze deletion") fact_keys_and_names = [("text", _("Text"))] unique_fact_keys = ["text"] required_fact_keys = ["text"] v = FactView(_("Cloze"), "5.1") v.q_fact_keys = ["f"] # Generated on the fly. v.a_fact_keys = ["b"] # Generated on the fly. fact_views = [v] def fact_key_format_proxies(self): return {"text": "text", "f": "text", "b": "text"} def is_fact_data_valid(self, fact_data): text = fact_data["text"] for f in self.component_manager.all("hook", "preprocess_cloze"): text = f.run(text) return bool(cloze_re.search(text)) def _q_a_from_cloze(self, text, index): """Auxiliary function used by other card types to return question and answer for the cloze with a given index in a text which can have the following form: La [casa:house] es [grande:big] Use 'index=-1' to get the cloze text without brackets and without hints. """ for f in self.component_manager.all("hook", "preprocess_cloze"): text = f.run(text) cursor = 0 current_index = 0 question = text answer = None while True: cursor = text.find("[", cursor) if cursor == -1: break cloze = text[cursor + 1:text.find("]", cursor)] if ":" in cloze: cloze_without_hint, hint = cloze.split(":", 1) else: cloze_without_hint, hint = cloze, "..." if current_index == index: question = question.replace(\ "[" + cloze + "]", "[" + hint + "]", 1) answer = cloze_without_hint else: question = question.replace(\ "[" + cloze + "]", cloze_without_hint, 1) cursor += 1 current_index += 1 for f in self.component_manager.all("hook", "postprocess_q_a_cloze"): question, answer = f.run(question, answer) return question, answer def fact_data(self, card): question, answer = self._q_a_from_cloze\ (card.fact["text"], card.extra_data["index"]) return {"f": question, "b": answer} def create_sister_cards(self, fact): cards = [] text = fact["text"] for f in self.component_manager.all("hook", "preprocess_cloze"): text = f.run(text) for match in cloze_re.finditer(text): card = Card(self, fact, self.fact_views[0]) card.extra_data["cloze"] = match.group(1) card.extra_data["index"] = len(cards) cards.append(card) return cards def _edit_clozes(self, fact, new_fact_data, cloze_fact_key, cloze_fact_view): """Auxiliary function used by other card types to when editing clozes. Should take into account that not all fact views are cloze-based. """ new_cards, edited_cards, deleted_cards = [], [], [] old_clozes = cloze_re.findall(fact[cloze_fact_key]) new_clozes = cloze_re.findall(new_fact_data[cloze_fact_key]) # If the number of clozes is equal, just edit the existing cards. if len(old_clozes) == len(new_clozes): for card in self.database().cards_from_fact(fact): if "cloze" in card.extra_data: index = card.extra_data["index"] card.extra_data["cloze"] = new_clozes[index] edited_cards.append(card) # If not, things are a little more complicated. else: new_clozes_processed = set() for card in self.database().cards_from_fact(fact): if "cloze" in card.extra_data: old_cloze = card.extra_data["cloze"] index = card.extra_data["index"] if old_cloze in new_clozes: new_index = new_clozes.index(old_cloze) card.extra_data["cloze"] = new_clozes[new_index] card.extra_data["index"] = new_index new_clozes_processed.add(new_clozes[new_index]) edited_cards.append(card) else: deleted_cards.append(card) else: edited_cards.append(card) for new_cloze in set(new_clozes).difference(new_clozes_processed): new_index = new_clozes.index(new_cloze) card = Card(self, fact, cloze_fact_view) card.extra_data["cloze"] = new_cloze card.extra_data["index"] = new_index new_cards.append(card) return new_cards, edited_cards, deleted_cards def edit_fact(self, fact, new_fact_data): return self._edit_clozes(fact, new_fact_data, "text", self.fact_views[0]) class ClozePlugin(Plugin): name = _("Cloze deletion") description = _("""A card type blanking out certain fragments in a text.\n E.g., the text \"The capital of [France] is [Paris]\", will give cards with questions \"The capital of France is [...].\" and \"The capital of [...] is Paris\".\n Editing the text will automatically update all sister cards.\n\nYou can also specify hints, e.g. [cloze:hint] will show [hint] in the question as opposed to [...].""") components = [Cloze] Remember to register the plugin adding to the bottom of the code above: from mnemosyne.libmnemosyne.plugin import register_user_plugin register_user_plugin(DecoratedVocabularyPlugin) Regards. -- You received this message because you are subscribed to the Google Groups "mnemosyne-proj-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/mnemosyne-proj-users/d43ce3f8-8a06-4449-b340-319c37777d80%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
# # cloze.py <[email protected]> # import re from mnemosyne.libmnemosyne.translator import _ from mnemosyne.libmnemosyne.card import Card from mnemosyne.libmnemosyne.plugin import Plugin from mnemosyne.libmnemosyne.card_type import CardType from mnemosyne.libmnemosyne.fact_view import FactView cloze_re = re.compile(r"\[(.+?)\]", re.DOTALL) class Cloze(CardType): """CardType to do cloze deletion on a string, e.g. "The political parties in the US are the [democrats] and the [republicans]." would give the following cards: Q:The political parties in the US are the [...] and the republicans. A:democrats Q:The political parties in the US are the democrats and the [...]. A:republicans Illustration of a CardType which does not use the traditional FactView mechanism. This is implemented by creating cards which contain extra_data entries "cloze" and "index", containing e.g. "democrats" and 0. Storing both the cloze and its index allows us to have enough data to support all possible editing operations. """ id = "5" name = _("Cloze deletion") fact_keys_and_names = [("text", _("Text"))] unique_fact_keys = ["text"] required_fact_keys = ["text"] v = FactView(_("Cloze"), "5.1") v.q_fact_keys = ["f"] # Generated on the fly. v.a_fact_keys = ["b"] # Generated on the fly. fact_views = [v] def fact_key_format_proxies(self): return {"text": "text", "f": "text", "b": "text"} def is_fact_data_valid(self, fact_data): text = fact_data["text"] for f in self.component_manager.all("hook", "preprocess_cloze"): text = f.run(text) return bool(cloze_re.search(text)) def _q_a_from_cloze(self, text, index): """Auxiliary function used by other card types to return question and answer for the cloze with a given index in a text which can have the following form: La [casa:house] es [grande:big] Use 'index=-1' to get the cloze text without brackets and without hints. """ for f in self.component_manager.all("hook", "preprocess_cloze"): text = f.run(text) cursor = 0 current_index = 0 question = text answer = None while True: cursor = text.find("[", cursor) if cursor == -1: break cloze = text[cursor + 1:text.find("]", cursor)] if ":" in cloze: cloze_without_hint, hint = cloze.split(":", 1) else: cloze_without_hint, hint = cloze, "..." if current_index == index: question = question.replace(\ "[" + cloze + "]", "[" + hint + "]", 1) answer = cloze_without_hint else: question = question.replace(\ "[" + cloze + "]", cloze_without_hint, 1) cursor += 1 current_index += 1 for f in self.component_manager.all("hook", "postprocess_q_a_cloze"): question, answer = f.run(question, answer) return question, answer def fact_data(self, card): question, answer = self._q_a_from_cloze\ (card.fact["text"], card.extra_data["index"]) return {"f": question, "b": answer} def create_sister_cards(self, fact): cards = [] text = fact["text"] for f in self.component_manager.all("hook", "preprocess_cloze"): text = f.run(text) for match in cloze_re.finditer(text): card = Card(self, fact, self.fact_views[0]) card.extra_data["cloze"] = match.group(1) card.extra_data["index"] = len(cards) cards.append(card) return cards def _edit_clozes(self, fact, new_fact_data, cloze_fact_key, cloze_fact_view): """Auxiliary function used by other card types to when editing clozes. Should take into account that not all fact views are cloze-based. """ new_cards, edited_cards, deleted_cards = [], [], [] old_clozes = cloze_re.findall(fact[cloze_fact_key]) new_clozes = cloze_re.findall(new_fact_data[cloze_fact_key]) # If the number of clozes is equal, just edit the existing cards. if len(old_clozes) == len(new_clozes): for card in self.database().cards_from_fact(fact): if "cloze" in card.extra_data: index = card.extra_data["index"] card.extra_data["cloze"] = new_clozes[index] edited_cards.append(card) # If not, things are a little more complicated. else: new_clozes_processed = set() for card in self.database().cards_from_fact(fact): if "cloze" in card.extra_data: old_cloze = card.extra_data["cloze"] index = card.extra_data["index"] if old_cloze in new_clozes: new_index = new_clozes.index(old_cloze) card.extra_data["cloze"] = new_clozes[new_index] card.extra_data["index"] = new_index new_clozes_processed.add(new_clozes[new_index]) edited_cards.append(card) else: deleted_cards.append(card) else: edited_cards.append(card) for new_cloze in set(new_clozes).difference(new_clozes_processed): new_index = new_clozes.index(new_cloze) card = Card(self, fact, cloze_fact_view) card.extra_data["cloze"] = new_cloze card.extra_data["index"] = new_index new_cards.append(card) return new_cards, edited_cards, deleted_cards def edit_fact(self, fact, new_fact_data): return self._edit_clozes(fact, new_fact_data, "text", self.fact_views[0]) class ClozePlugin(Plugin): name = _("Cloze deletion") description = _("""A card type blanking out certain fragments in a text.\n E.g., the text \"The capital of [France] is [Paris]\", will give cards with questions \"The capital of France is [...].\" and \"The capital of [...] is Paris\".\n Editing the text will automatically update all sister cards.\n\nYou can also specify hints, e.g. [cloze:hint] will show [hint] in the question as opposed to [...].""") components = [Cloze]
