/*
Meganekko Copyright (C) 2008 Alex Yatskov
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "Pch.h"
#include "FlashCardManager.h"
void FlashCardManager::XmlExportRoot(TiXmlDocument* parent) const
{
TiXmlElement* const rootElement = new TiXmlElement("Meganekko");
XmlExportOptions(rootElement);
XmlExportDecks(rootElement);
parent->LinkEndChild(rootElement);
}
void FlashCardManager::XmlExportOptions(TiXmlElement* parent) const
{
TiXmlElement* const optionsElement = new TiXmlElement("Options");
optionsElement->SetAttribute("timeReviewMin", m_options.timeReviewMin);
optionsElement->SetAttribute("timeReviewMax", m_options.timeReviewMax);
optionsElement->SetAttribute("timeReviewEntropy", m_options.timeReviewEntropy);
optionsElement->SetAttribute("autoSave", m_options.autoSave);
optionsElement->SetAttribute("fontNameNormal", wstrToUtf8(m_options.fontNameNormal).c_str());
optionsElement->SetAttribute("fontNameFixed", wstrToUtf8(m_options.fontNameFixed).c_str());
for (size_t i = 0; i < ARRAY_SIZE(m_options.fontSizes); ++i)
{
char attribute[16] = {0};
sprintf(attribute, "fontSize%d", static_cast(i));
optionsElement->SetAttribute(attribute, m_options.fontSizes[i]);
}
parent->LinkEndChild(optionsElement);
}
void FlashCardManager::XmlExportDecks(TiXmlElement* parent) const
{
TiXmlElement* const decksElement = new TiXmlElement("Decks");
for (size_t i = 0; i < DECK_TYPES; ++i)
{
XmlExportDeck(decksElement, static_cast(i));
}
parent->LinkEndChild(decksElement);
}
void FlashCardManager::XmlExportDeck(TiXmlElement* parent, DeckType deck) const
{
TiXmlElement* const deckElement = new TiXmlElement("Deck");
deckElement->SetAttribute("type", DeckTypeToString(deck).c_str());
for (CardList::const_iterator iter = m_cards.begin(); iter != m_cards.end(); ++iter)
{
if (iter->GetDeck() == deck)
{
XmlExportCard(deckElement, *iter);
}
}
parent->LinkEndChild(deckElement);
}
void FlashCardManager::XmlExportCard(TiXmlElement* parent, const FlashCard& card) const
{
TiXmlElement* const cardElement = new TiXmlElement("Card");
TiXmlElement* const questionElement = new TiXmlElement("Question");
TiXmlText* const questionText = new TiXmlText(wstrToUtf8(card.GetQuestion()).c_str());
questionText->SetCDATA(true);
questionElement->LinkEndChild(questionText);
cardElement->LinkEndChild(questionElement);
TiXmlElement* const answerElement = new TiXmlElement("Answer");
TiXmlText* const answerText = new TiXmlText(wstrToUtf8(card.GetAnswer()).c_str());
answerText->SetCDATA(true);
answerElement->LinkEndChild(answerText);
cardElement->LinkEndChild(answerElement);
cardElement->SetAttribute("enabled", card.GetEnabled());
cardElement->SetAttribute("countRemembered", card.GetCountRemembered());
cardElement->SetAttribute("countForgotten", card.GetCountForgotten());
cardElement->SetAttribute("countBungled", card.GetCountBungled());
cardElement->SetAttribute("timeReviewNext", card.GetTimeReviewNext());
cardElement->SetAttribute("timeReviewPrevious", card.GetTimeReviewPrevious());
cardElement->SetAttribute("timeAdded", card.GetTimeAdded());
parent->LinkEndChild(cardElement);
}
void FlashCardManager::XmlImportRoot(const TiXmlDocument* parent)
{
const TiXmlElement* const rootElement = parent->RootElement();
if (rootElement == NULL || strcmp(rootElement->Value(), "Meganekko") != 0)
{
return;
}
for (const TiXmlElement* baseElement = rootElement->FirstChildElement(); baseElement != NULL; baseElement = baseElement->NextSiblingElement())
{
const char* const value = baseElement->Value();
if (strcmp(value, "Options") == 0)
{
XmlImportOptions(baseElement);
}
else if (strcmp(value, "Decks") == 0)
{
XmlImportDecks(baseElement);
}
}
}
void FlashCardManager::XmlImportOptions(const TiXmlElement* parent)
{
int timeReviewMin = FlashCardOptions::DEFAULT.timeReviewMin;
parent->Attribute("timeReviewMin", &timeReviewMin);
int timeReviewMax = FlashCardOptions::DEFAULT.timeReviewMax;
parent->Attribute("timeReviewMax", &timeReviewMax);
int timeReviewEntropy = FlashCardOptions::DEFAULT.timeReviewEntropy;;
parent->Attribute("timeReviewEntropy", &timeReviewEntropy);
int autoSave = FlashCardOptions::DEFAULT.autoSave;;
parent->Attribute("autoSave", &autoSave);
const char* const fontNameNormal = parent->Attribute("fontNameNormal");
const char* const fontNameFixed = parent->Attribute("fontNameFixed");
for (size_t i = 0; i < ARRAY_SIZE(m_options.fontSizes); ++i)
{
char attribute[16] = {0};
sprintf(attribute, "fontSize%d", static_cast(i));
m_options.fontSizes[i] = FlashCardOptions::DEFAULT.fontSizes[i];
parent->Attribute(attribute, m_options.fontSizes + i);
}
m_options.timeReviewMin = timeReviewMin;
m_options.timeReviewMax = timeReviewMax;
m_options.timeReviewEntropy = timeReviewEntropy;
m_options.autoSave = IS_TRUE(autoSave);
m_options.fontNameNormal = fontNameNormal == NULL ? FlashCardOptions::DEFAULT.fontNameNormal : utf8toWStr(fontNameNormal);
m_options.fontNameFixed = fontNameFixed == NULL ? FlashCardOptions::DEFAULT.fontNameFixed : utf8toWStr(fontNameFixed);
}
void FlashCardManager::XmlImportDecks(const TiXmlElement* parent)
{
for (const TiXmlElement* decksElement = parent->FirstChildElement(); decksElement != NULL; decksElement = decksElement->NextSiblingElement())
{
const char* const value = decksElement->Value();
if (strcmp(value, "Deck") == 0)
{
const char* const deckString = decksElement->Attribute("type");
const DeckType deck = deckString == NULL ? DECK_TYPE_UNTESTED : StringToDeckType(deckString);
XmlImportDeck(decksElement, deck);
}
}
}
void FlashCardManager::XmlImportDeck(const TiXmlElement* parent, DeckType deck)
{
for (const TiXmlElement* deckElement = parent->FirstChildElement(); deckElement != NULL; deckElement = deckElement->NextSiblingElement())
{
const char* const value = deckElement->Value();
if (strcmp(value, "Card") == 0)
{
XmlImportCard(deckElement, deck);
}
}
}
void FlashCardManager::XmlImportCard(const TiXmlElement* parent, DeckType deck)
{
std::wstring question;
std::wstring answer;
for (const TiXmlElement* cardElement = parent->FirstChildElement(); cardElement != NULL; cardElement = cardElement->NextSiblingElement())
{
const char* const value = cardElement->Value();
if (strcmp(value, "Question") == 0)
{
question = utf8toWStr(cardElement->GetText());
}
else if (strcmp(value, "Answer") == 0)
{
answer = utf8toWStr(cardElement->GetText());
}
}
int enabled = 0;
parent->Attribute("enabled", &enabled);
int countRemembered = 0;
parent->Attribute("countRemembered", &countRemembered);
int countForgotten = 0;
parent->Attribute("countForgotten", &countForgotten);
int countBungled = 0;
parent->Attribute("countBungled", &countBungled);
int timeReviewNext = 0;
parent->Attribute("timeReviewNext", &timeReviewNext);
int timeReviewPrevious = 0;
parent->Attribute("timeReviewPrevious", &timeReviewPrevious);
int timeAdded = 0;
parent->Attribute("timeAdded", &timeAdded);
const bool valid =
timeAdded > 0 &&
timeAdded <= timeReviewPrevious &&
timeReviewPrevious <= timeReviewNext;
if (!valid)
{
timeAdded = timeReviewPrevious = timeReviewNext = time(NULL);
}
const FlashCard card(
this,
deck,
question,
answer,
IS_TRUE(enabled),
countRemembered,
countForgotten,
countBungled,
timeReviewPrevious,
timeReviewNext,
timeAdded
);
m_cards.push_front(card);
}