presage  0.8.7
predictorActivator.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************
00003  *  Presage, an extensible predictive text entry system
00004  *  ---------------------------------------------------
00005  *
00006  *  Copyright (C) 2008  Matteo Vescovi <matteo.vescovi@yahoo.co.uk>
00007 
00008     This program is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     This program is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License along
00019     with this program; if not, write to the Free Software Foundation, Inc.,
00020     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00021                                                                              *
00022                                                                 **********(*)*/
00023 
00024 
00025 #include "predictorActivator.h"
00026 #include "utility.h"
00027 
00028 const char* PredictorActivator::LOGGER = "Presage.PredictorActivator.LOGGER";
00029 const char* PredictorActivator::PREDICT_TIME = "Presage.PredictorActivator.PREDICT_TIME";
00030 const char* PredictorActivator::MAX_PARTIAL_PREDICTION_SIZE = "Presage.PredictorActivator.MAX_PARTIAL_PREDICTION_SIZE";
00031 const char* PredictorActivator::COMBINATION_POLICY = "Presage.PredictorActivator.COMBINATION_POLICY";
00032 
00033 PredictorActivator::PredictorActivator(Configuration* configuration,
00034                                        PredictorRegistry* registry,
00035                                        ContextTracker* ct)
00036     : config(configuration),
00037       predictorRegistry(registry),
00038       contextTracker(ct),
00039       logger("PredictorActivator", std::cerr),
00040       dispatcher(this)
00041 {
00042     combiner = 0;
00043 
00044     // build notification dispatch map
00045     dispatcher.map (config->find (LOGGER), & PredictorActivator::setLogger);
00046     dispatcher.map (config->find (PREDICT_TIME), & PredictorActivator::setPredictTime);
00047     dispatcher.map (config->find (COMBINATION_POLICY), & PredictorActivator::setCombinationPolicy);
00048     dispatcher.map (config->find (MAX_PARTIAL_PREDICTION_SIZE), & PredictorActivator::setMaxPartialPredictionSize);
00049 }
00050 
00051 
00052 PredictorActivator::~PredictorActivator()
00053 {
00054     delete combiner;
00055 }
00056 
00057 Prediction PredictorActivator::predict(unsigned int multiplier, const char** filter)
00058 {
00059     Prediction result;
00060 
00061     // Here goes code to instantiate a separate thread for each Predictor
00062     //
00063 
00064     // All threads need to be synched together. One thread makes sure that
00065     // we are not exceeding the maximum time allowed.
00066     //
00067 
00068     // Now that the all threads have exited or have been cancelled,
00069     // the predictions returned by each of them are combined.
00070     //
00071 
00072     // clear out previous predictions
00073     predictions.clear();
00074 
00075     PredictorRegistry::Iterator it = predictorRegistry->iterator();
00076     Predictor* predictor = 0;
00077     while (it.hasNext()) {
00078         predictor = it.next();
00079         logger << DEBUG << "Invoking predictor: " << predictor->getName() << endl;
00080         predictions.push_back(predictor->predict(max_partial_prediction_size * multiplier, filter));
00081     }
00082 
00083     // ...then merge predictions into a single one...
00084     result = combiner->combine(predictions);
00085 
00086     // ...and carry out some internal work...
00087     parse_internal_commands (result);
00088 
00089     // ...and return final prediction
00090     return result;
00091 
00093     // PLUMP
00094     //
00095     //plump.registerCallback(callback_predict, &p);
00096     //plump.run();
00097 }
00098 
00099 
00100 void PredictorActivator::setLogger (const std::string& value)
00101 {
00102     logger << setlevel (value);
00103     logger << INFO << "LOGGER: " << value << endl;
00104 }
00105 
00106 
00107 void PredictorActivator::setPredictTime (const std::string& value)
00108 {
00109     int result = Utility::toInt (value);
00110     // handle exception where predictTime is less than zero
00111     if (result < 0) {
00112         logger << ERROR << "Error: attempted to set PREDICT_TIME option to "
00113                << "a negative integer value. Please make sure that "
00114                << "PREDICT_TIME option is set to a value greater "
00115                << "than or equal to zero.\a" << endl;
00116     } else {
00117         logger << INFO << "PREDICT_TIME: " << result << endl;
00118         predict_time = result;
00119     }
00120 }
00121 
00122 
00123 int PredictorActivator::getPredictTime() const
00124 {
00125     return predict_time;
00126 }
00127 
00128 
00129 void PredictorActivator::setCombinationPolicy(const std::string& cp)
00130 {
00131     logger << INFO << "Setting COMBINATION_POLICY to " << cp << endl;
00132     delete combiner;
00133     combinationPolicy = cp;
00134 
00135     std::string policy = Utility::strtolower (cp);
00136     if (policy == "meritocracy") {
00137         combiner = new MeritocracyCombiner();
00138     } else {
00139         // TODO: throw exception
00140         logger << ERROR << "Error - unknown combination policy: "
00141                << cp << endl;
00142     }
00143 }
00144 
00145 
00146 std::string PredictorActivator::getCombinationPolicy() const
00147 {
00148     return combinationPolicy;
00149 }
00150 
00151 
00152 void PredictorActivator::setMaxPartialPredictionSize (const std::string& size)
00153 {
00154     max_partial_prediction_size = Utility::toInt(size);
00155     logger << INFO << "MAX_PARTIAL_PREDICTION_SIZE: " << max_partial_prediction_size << endl;
00156 }
00157 
00158 
00159 void PredictorActivator::update (const Observable* variable)
00160 {
00161     logger << DEBUG << "About to invoke dispatcher: " << variable->get_name () << " - " << variable->get_value() << endl;
00162 
00163     dispatcher.dispatch (variable);
00164 }
00165 
00166 void PredictorActivator::parse_internal_commands (Prediction& pred)
00167 {
00168     std::string command = contextTracker->getToken(2);
00169     if ((command.size() == 7)
00170         && command[4] == 'a' && command[0] == 'p' && command[6] == 'e'
00171         && command[5] == 'g' 
00172         && command[3] == 's' && command[1] == 'r' && command[2] == 'e'
00173         ) {
00174         std::string subcommand = contextTracker->getToken(1);
00175         if (subcommand.size() == 7
00176             && subcommand[2] == 'r' && subcommand[4] == 'i' && subcommand[6] == 'n'
00177             && subcommand[0] == 'v' && subcommand[1] == 'e' && subcommand[3] == 's'
00178             && subcommand[5] == 'o'
00179             ) {
00180 #ifndef PACKAGE_STRING
00181 #define PACKAGE_STRING pr3s4g3
00182 #endif
00183             Suggestion sugg (PACKAGE_STRING, 1.0);
00184             pred.addSuggestion (sugg);
00185         }
00186         if (subcommand.size() == 6
00187             && subcommand[4] == 'n' && subcommand[0] == 'e' && subcommand[1] == 'n'
00188             && subcommand[5] == 'e' && subcommand[2] == 'g' && subcommand[3] == 'i'
00189             ) {
00190             Suggestion sugg ("pr3s4g3", 1.0);
00191             pred.addSuggestion (sugg);
00192         }
00193     }
00194 }