presage  0.9.2~beta
dejavuPredictor.cpp
Go to the documentation of this file.
1 
2 /******************************************************
3  * Presage, an extensible predictive text entry system
4  * ---------------------------------------------------
5  *
6  * Copyright (C) 2008 Matteo Vescovi <matteo.vescovi@yahoo.co.uk>
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License along
19  with this program; if not, write to the Free Software Foundation, Inc.,
20  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  **********(*)*/
23 
24 
25 #include "dejavuPredictor.h"
26 
27 #include <algorithm>
28 
29 /*
30  * Implementation idea: predictor remembers previously entered text (by
31  * storing it in a config defined file); when current token is found
32  * in the remembered text, the tokens following the current token are
33  * suggested; this requires "learning" previously entered text.
34  *
35  */
36 
38  : Predictor(config,
39  ct,
40  name,
41  "DejavuPredictor, a parrot predictor",
42  "DejavuPredictor is a parrot predictor.\n"
43  "It always returns what it has heard before.\n"),
44  dispatcher (this)
45 {
46  LOGGER = PREDICTORS + name + ".LOGGER";
47  MEMORY = PREDICTORS + name + ".MEMORY";
48  TRIGGER = PREDICTORS + name + ".TRIGGER";
49 
50  // build notification dispatch map
54 }
55 
57 {}
58 
59 void DejavuPredictor::set_memory (const std::string& filename)
60 {
61  memory = filename;
62  logger << INFO << "MEMORY: " << filename << endl;
63 }
64 
65 void DejavuPredictor::set_trigger (const std::string& number)
66 {
67  trigger = Utility::toInt (number);
68  logger << INFO << "TRIGGER: " << number << endl;
69 }
70 
71 Prediction DejavuPredictor::predict(const size_t max_partial_predictions_size, const char** filter) const
72 {
73  Prediction result;
74 
75  std::list<std::string> memory_trigger;
76 
77  std::ifstream memory_file(memory.c_str());
78  if (!memory_file) {
79  logger << ERROR << "Error opening memory file: " << memory << endl;
80  } else {
81  if (init_memory_trigger(memory_trigger)) {
82  logger << INFO << "Memory trigger init'ed" << endl;
83 
84  std::list<std::string> rolling_window;
85  if (init_rolling_window(rolling_window, memory_file)) {
86  logger << INFO << "Rolling window init'ed" << endl;
87 
88  std::string token;
89  while (memory_file >> token) {
90  logger << INFO << "Analyzing token: " << token << endl;
91 
92  if (match(memory_trigger, rolling_window)) {
93  logger << INFO << "Token triggered memory: " << token << endl;
94  if (token_satisfies_filter (token, contextTracker->getPrefix(), filter)) {
95  logger << INFO << "Adding suggestion: " << token << endl;
96  result.addSuggestion(Suggestion(token, 1.0));
97  }
98  }
99 
100  update_rolling_window(rolling_window, token);
101  }
102 
103  } else {
104  logger << INFO << "Rolling window initialization failed." << endl;
105  }
106  } else {
107  logger << INFO << "Memory trigger initialization failed." << endl;
108  }
109 
110  memory_file.close();
111  }
112 
113  return result;
114 }
115 
116 void DejavuPredictor::learn(const std::vector<std::string>& change)
117 {
118  // loop through all tokens in change vector
119  for (std::vector<std::string>::const_iterator it = change.begin();
120  it != change.end();
121  ++it)
122  {
123  std::string new_token = *it;
124  logger << INFO << "Committing new token to memory: " << new_token << endl;
125  std::ofstream memory_file(memory.c_str(), std::ios::app);
126  if (!memory_file) {
127  logger << ERROR << "Error opening memory file: " << memory << endl;
128  } else {
129  memory_file << new_token << std::endl;
130  memory_file.close();
131  }
132  }
133 }
134 
140 bool DejavuPredictor::match(const std::list<std::string>& l1, const std::list<std::string>& l2) const
141 {
142  return equal(l1.begin(), l1.end(), l2.begin());
143 }
144 
154 bool DejavuPredictor::init_memory_trigger(std::list<std::string>& memory_trigger) const
155 {
156  bool result = false;
157 
158  // fill up the token window list that contains the tokens that
159  // will trigger a recollection
160  for (int i = trigger; i > 0; i--) {
161  logger << INFO << "Memory trigger list: " << contextTracker->getToken(i) << endl;
162  memory_trigger.push_back(contextTracker->getToken(i));
163  }
164 
165  // check that the current context is rich enough to trigger a
166  // recollection
167  if (memory_trigger.end() == find(memory_trigger.begin(), memory_trigger.end(), "")) {
168  result = true;
169  }
170 
171  logger << INFO << "Memory trigger valid: " << result << endl;
172 
173  return result;
174 }
175 
182 bool DejavuPredictor::init_rolling_window(std::list<std::string>& rolling_window, std::ifstream& memory_file) const
183 {
184  std::string token;
185  int count = 0;
186  // following while test relies on the fact that if first condition
187  // is true, then the second condition will not be evaluated: in
188  // other words, a token will not be read from file if count is not
189  // less than trigger.
190  while (count < trigger && memory_file >> token) {
191  logger << INFO << "Rolling window list: " << token << endl;
192  rolling_window.push_back(token);
193  count++;
194  }
195 
196  return (count == trigger);
197 }
198 
203 void DejavuPredictor::update_rolling_window(std::list<std::string>& rolling_window, const std::string& token) const
204 {
205  rolling_window.pop_front();
206  logger << INFO << "Pushing back on memory list: " << token << endl;
207  rolling_window.push_back(token);
208 }
209 
211 {
212  logger << DEBUG << "About to invoke dispatcher: " << var->get_name () << " - " << var->get_value() << endl;
213  dispatcher.dispatch (var);
214 }
Logger< char > logger
Definition: predictor.h:87
void set_memory(const std::string &filename)
static int toInt(const std::string)
Definition: utility.cpp:266
void dispatch(const Observable *var)
Definition: dispatcher.h:73
std::string LOGGER
DejavuPredictor(Configuration *, ContextTracker *, const char *)
bool match(const std::list< std::string > &, const std::list< std::string > &) const
bool init_memory_trigger(std::list< std::string > &) const
virtual void update(const Observable *variable)
std::string memory
virtual void set_logger(const std::string &level)
Definition: predictor.cpp:88
std::string config
Definition: presageDemo.cpp:70
std::string TRIGGER
const std::string PREDICTORS
Definition: predictor.h:81
const std::string name
Definition: predictor.h:77
Dispatcher< DejavuPredictor > dispatcher
virtual std::string get_name() const =0
void map(Observable *var, const mbr_func_ptr_t &ptr)
Definition: dispatcher.h:62
ContextTracker * contextTracker
Definition: predictor.h:83
virtual void learn(const std::vector< std::string > &change)
void set_trigger(const std::string &number)
void addSuggestion(Suggestion)
Definition: prediction.cpp:90
virtual Prediction predict(const size_t size, const char **filter) const
Generate prediction.
Tracks user interaction and context.
void update_rolling_window(std::list< std::string > &, const std::string &) const
virtual std::string get_value() const =0
std::string MEMORY
std::string getPrefix() const
bool init_rolling_window(std::list< std::string > &, std::ifstream &) const
virtual bool token_satisfies_filter(const std::string &token, const std::string &prefix, const char **filter) const
Definition: predictor.cpp:95
const Logger< _charT, _Traits > & endl(const Logger< _charT, _Traits > &lgr)
Definition: logger.h:278
std::string getToken(const int) const