00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef USERANSWER_H
00017 #define USERANSWER_H
00018
00019 #ifndef USE_PCH
00020 #include <string>
00021 #include "debug.h"
00022 #include <libcw/events.h>
00023 #endif
00024
00025 #include "Target.h"
00026 #include "question_nt.h"
00027 #include "Counter.h"
00028
00029
00030
00031 class UserAnswer {
00032 private:
00033 std::string M_answer;
00034 ClientSession const& M_client_session;
00035 std::string const& M_target_name;
00036 public:
00037
00038 UserAnswer(std::string const& answer, ClientSession const& client_session, std::string const& target_name) :
00039 M_answer(answer), M_client_session(client_session), M_target_name(target_name) { }
00040
00041 std::string const& answer(void) const { return M_answer; }
00042
00043 std::string const& target_name(void) const { return M_target_name; }
00044
00045 bool is_match(boost::shared_ptr<Target> const& target) const;
00046
00047
00048 friend std::ostream& operator<<(std::ostream& os, UserAnswer const& answer);
00049 };
00050
00051
00052
00053 class UserAnswerEventType : public UserAnswer {
00054 public:
00055
00056 UserAnswerEventType(std::string const& answer, ClientSession const& client_session, std::string const& target_name) :
00057 UserAnswer(answer, client_session, target_name) { }
00058 };
00059
00060
00061 class UserQuestion {
00062 private:
00063 question_nt M_question_number;
00064 std::string M_question;
00065 public:
00066
00067 UserQuestion(question_nt question_number, std::string const& question) :
00068 M_question_number(question_number), M_question(question) { }
00069
00070 std::string const& question(void) const { return M_question; }
00071
00072 question_nt number(void) const { return M_question_number; }
00073 };
00074
00075
00076 class UserAnswerRequestData {
00077 private:
00078 ClientSession& M_client_session;
00079 boost::shared_ptr<UserQuestion> M_question;
00080
00081 public:
00082
00083 UserAnswerRequestData(ClientSession& client_session, question_nt question_number, std::string const& question) :
00084 M_client_session(client_session), M_question(NEW(UserQuestion(question_number, question))) { }
00085
00086
00087 std::string const& question(void) const { return M_question->question(); }
00088
00089 boost::shared_ptr<UserQuestion> user_question(void) { return M_question; }
00090
00091 ClientSession& client_session(void) { return M_client_session; }
00092
00093 ClientSession const& client_session(void) const { return M_client_session; }
00094 };
00095
00096
00097 class UserAnswerEventRequestBase : public event_request_base_tct<UserAnswerEventType> {
00098 public:
00099
00100 typedef UserAnswerRequestData event_request_data_ct;
00101 private:
00102 event_request_data_ct M_request_data;
00103 boost::shared_ptr<Target> M_target;
00104 public:
00105 UserAnswerEventRequestBase(event_client_tracker_ct* event_client_tracker, event_request_data_ct request_data);
00106 ~UserAnswerEventRequestBase();
00107
00108 UserAnswerEventRequestBase(UserAnswerEventRequestBase const& request) :
00109 event_request_base_tct<UserAnswerEventType>(request),
00110 M_request_data(request.M_request_data),
00111 M_target(request.M_target)
00112 { Dout(dc::objects, "Copy-constructing UserAnswerEventRequestBase from " << request); }
00113
00114
00115 boost::shared_ptr<Target> const& target(void) const { return M_target; }
00116
00117
00118 friend std::ostream& operator<<(std::ostream& os, UserAnswerEventRequestBase const& request);
00119 };
00120
00121
00122 class UserAnswerEventRequestQueue {
00123
00124 typedef std::deque<UserAnswerEventRequestBase*> event_requests_ct;
00125 private:
00126 Counter M_event_requests_locked;
00127 event_requests_ct M_event_requests;
00128 event_requests_ct M_event_requests_tmp;
00129 protected:
00130
00131 void add_request(UserAnswerEventRequestBase* request)
00132 {
00133 if (M_event_requests_locked)
00134 M_event_requests_tmp.push_back(request);
00135 else
00136 M_event_requests.push_back(request);
00137 }
00138
00139 ~UserAnswerEventRequestQueue() { destroy_requests(); }
00140 public:
00141
00142 void destroy_requests(void)
00143 {
00144 ASSERT(!M_event_requests_locked);
00145 while (!M_event_requests.empty())
00146 {
00147 M_event_requests.front()->release();
00148 M_event_requests.pop_front();
00149 }
00150 }
00151
00152 void trigger(UserAnswerEventRequestBase::event_type_ct const& event_type)
00153 {
00154 DoutEntering(dc::notice, "UserAnswerEventRequestQueue::trigger(" <<
00155 libcwd::type_info_of<UserAnswerEventRequestBase::event_type_ct>().demangled_name() <<
00156 " const& " << event_type << ")");
00157 {
00158 Increment tmp(M_event_requests_locked);
00159 event_requests_ct::iterator iter = M_event_requests.begin();
00160 while (iter != M_event_requests.end())
00161 {
00162 if ((*iter)->canceled())
00163 {
00164 Dout(dc::notice, "Removing canceled " << **iter);
00165 (*iter)->release();
00166 iter = M_event_requests.erase(iter);
00167 }
00168 else if (event_type.is_match((*iter)->target()))
00169 {
00170 Dout(dc::notice, "Calling handle() for " << **iter);
00171 (*iter)->handle(event_type);
00172 (*iter)->release();
00173 iter = M_event_requests.erase(iter);
00174 }
00175 else
00176 ++iter;
00177 }
00178 }
00179 if (M_event_requests_locked == 0)
00180 while (!M_event_requests_tmp.empty())
00181 {
00182 add_request(M_event_requests_tmp.front());
00183 M_event_requests_tmp.pop_front();
00184 }
00185 }
00186 };
00187
00188
00189 typedef event_data_server_tct<UserAnswerEventRequestBase, UserAnswerEventRequestQueue> UserAnswerEventServer;
00190
00191
00192 extern char const* question_target_name(question_nt number);
00193
00194 #endif // USERANSWER_H