//---------------------------------------------------------------------------
#include <fstream>
//---------------------------------------------------------------------------
#include <boost/algorithm/string/split.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/numeric/conversion/cast.hpp>
//---------------------------------------------------------------------------
#include "multiplechoicequestion.h"
#include "openquestion.h"
#include "survey.h"
//---------------------------------------------------------------------------
std::string Survey::m_path;
//---------------------------------------------------------------------------
Survey::Survey(std::vector<boost::shared_ptr<Question> > questions)
: m_questions(questions)
{
assert(std::find_if(m_questions.begin(),m_questions.end(),
!boost::lambda::_1) == m_questions.end()
&& "All questions must be initialized");
m_current = m_questions.begin();
}
//---------------------------------------------------------------------------
Survey::Survey(const std::string& filename)
{
assert(boost::filesystem::exists(filename));
if (!boost::filesystem::exists(filename))
{
throw std::logic_error("File does not exist");
}
const std::vector<std::string> v = FileToVector(filename);
m_questions.reserve(v.size());
BOOST_FOREACH(const std::string& s,v)
{
boost::shared_ptr<Question> q = Parse(s);
if (q) m_questions.push_back(q);
}
}
//---------------------------------------------------------------------------
///FileToVector reads a file and converts it to a std::vector<std::string>
///From http://www.richelbilderbeek.nl/CppFileToVector.htm
const std::vector<std::string> Survey::FileToVector(const std::string& filename)
{
assert(boost::filesystem::exists(filename));
std::vector<std::string> v;
std::ifstream in(filename.c_str());
std::string s;
for (int i=0; !in.eof(); ++i)
{
std::getline(in,s);
v.push_back(s);
}
return v;
}
//---------------------------------------------------------------------------
const Question * Survey::GetCurrentQuestion() const
{
return (*m_current).get();
}
//---------------------------------------------------------------------------
int Survey::GetNumberOfQuestions() const
{
return boost::numeric_cast<int>(m_questions.size());
}
//---------------------------------------------------------------------------
void Survey::Next()
{
++m_current;
if (m_current == m_questions.end())
{
std::random_shuffle(m_questions.begin(),m_questions.end());
m_current = m_questions.begin();
}
}
//---------------------------------------------------------------------------
boost::shared_ptr<Question> Survey::Parse(const std::string& s)
{
boost::shared_ptr<Question> q;
//Obtain the string to split
if (s.empty()) return q;
//Replace \, by {comma}
const std::string str_to_split = ReplaceAll(s,"\\,","{comma}");
//Write string to split to debug
std::vector<std::string> v = SeperateString(str_to_split,',');
//Replace {comma} by a comma for each std::string in v
BOOST_FOREACH(std::string& s,v) { s = ReplaceAll(s,"{comma}",","); }
if ( v.empty()
|| v.size() < 3
|| v[0].empty()
|| v[1].empty()
|| v[2].empty())
{
return q;
}
//const std::string filename = m_path + '/' + v[0];
const std::string& filename = v[0];
const std::string& question = v[1];
const std::string& answer = v[2];
if (v.size() == 3)
{
//Open question
const std::vector<std::string> answers(SeperateString(answer,'/'));
q.reset(new OpenQuestion(filename,question,answers));
}
else
{
//Multiple choice question
const std::vector<std::string> false_answers(v.begin() + 3,v.end());
q.reset(new MultipleChoiceQuestion(filename,question,answer,false_answers));
}
return q;
}
//---------------------------------------------------------------------------
const std::string Survey::ReplaceAll(
std::string s,
const std::string& replaceWhat,
const std::string& replaceWithWhat)
{
while(1)
{
const int pos = s.find(replaceWhat);
if (pos==-1) break;
s.replace(pos,replaceWhat.size(),replaceWithWhat);
}
return s;
}
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppSeperateString.htm
const std::vector<std::string> Survey::SeperateString(
const std::string& input,
const char seperator)
{
std::vector<std::string> v;
boost::algorithm::split(v,input,
std::bind2nd(std::equal_to<char>(),seperator),
boost::algorithm::token_compress_on);
return v;
}
//---------------------------------------------------------------------------
///Set the path of the current application
void Survey::SetPath(const std::string path)
{
m_path = path;
}
//---------------------------------------------------------------------------
|