Root/
| 1 | /* |
| 2 | Copyright 2010 Christian Vetter veaac.fdirct@gmail.com |
| 3 | |
| 4 | This file is part of MoNav. |
| 5 | |
| 6 | MoNav is free software: you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation, either version 3 of the License, or |
| 9 | (at your option) any later version. |
| 10 | |
| 11 | MoNav is distributed in the hope that it will be useful, |
| 12 | but WITHOUT ANY WARRANTY |
| 13 | { |
| 14 | |
| 15 | } |
| 16 | without even the implied warranty of |
| 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | GNU General Public License for more details. |
| 19 | |
| 20 | You should have received a copy of the GNU General Public License |
| 21 | along with MoNav. If not, see <http://www.gnu.org/licenses/>. |
| 22 | */ |
| 23 | |
| 24 | #include "unicodetournamenttrieclient.h" |
| 25 | #include "utils/qthelpers.h" |
| 26 | #include <QtDebug> |
| 27 | #include <algorithm> |
| 28 | #ifndef NOGUI |
| 29 | #include <QMessageBox> |
| 30 | #endif |
| 31 | |
| 32 | UnicodeTournamentTrieClient::UnicodeTournamentTrieClient() |
| 33 | { |
| 34 | trieFile = NULL; |
| 35 | subTrieFile = NULL; |
| 36 | dataFile = NULL; |
| 37 | trieData = NULL; |
| 38 | subTrieData = NULL; |
| 39 | placeID = -1; |
| 40 | } |
| 41 | |
| 42 | UnicodeTournamentTrieClient::~UnicodeTournamentTrieClient() |
| 43 | { |
| 44 | |
| 45 | } |
| 46 | |
| 47 | void UnicodeTournamentTrieClient::unload() |
| 48 | { |
| 49 | if ( trieFile != NULL ) |
| 50 | delete trieFile; |
| 51 | trieFile = NULL; |
| 52 | if ( subTrieFile != NULL ) |
| 53 | delete subTrieFile; |
| 54 | subTrieFile = NULL; |
| 55 | if ( dataFile != NULL ) |
| 56 | delete dataFile; |
| 57 | dataFile = NULL; |
| 58 | } |
| 59 | |
| 60 | QString UnicodeTournamentTrieClient::GetName() |
| 61 | { |
| 62 | return "Unicode Tournament Trie"; |
| 63 | } |
| 64 | |
| 65 | void UnicodeTournamentTrieClient::SetInputDirectory( const QString& dir ) |
| 66 | { |
| 67 | directory = dir; |
| 68 | } |
| 69 | |
| 70 | void UnicodeTournamentTrieClient::ShowSettings() |
| 71 | { |
| 72 | #ifndef NOGUI |
| 73 | QMessageBox::information( NULL, "Settings", "No settings available" ); |
| 74 | #endif |
| 75 | } |
| 76 | |
| 77 | bool UnicodeTournamentTrieClient::LoadData() |
| 78 | { |
| 79 | unload(); |
| 80 | QString filename = fileInDirectory( directory, "Unicode Tournament Trie" ); |
| 81 | trieFile = new QFile( filename + "_main" ); |
| 82 | subTrieFile = new QFile( filename + "_sub" ); |
| 83 | dataFile = new QFile( filename + "_ways" ); |
| 84 | |
| 85 | if ( !openQFile( trieFile, QIODevice::ReadOnly ) ) |
| 86 | return false; |
| 87 | if ( !openQFile( subTrieFile, QIODevice::ReadOnly ) ) |
| 88 | return false; |
| 89 | if ( !openQFile( dataFile, QIODevice::ReadOnly ) ) |
| 90 | return false; |
| 91 | |
| 92 | trieData = ( char* ) trieFile->map( 0, trieFile->size() ); |
| 93 | subTrieData = ( char* ) subTrieFile->map( 0, subTrieFile->size() ); |
| 94 | |
| 95 | if ( trieData == NULL ) { |
| 96 | qDebug( "Failed to Memory Map trie data" ); |
| 97 | return false; |
| 98 | } |
| 99 | if ( subTrieData == NULL ) { |
| 100 | qDebug( "Failed to Memory Map sub trie data" ); |
| 101 | return false; |
| 102 | } |
| 103 | |
| 104 | return true; |
| 105 | } |
| 106 | |
| 107 | bool UnicodeTournamentTrieClient::find( const char* trie, unsigned* resultNode, QString* missingPrefix, QString prefix ) |
| 108 | { |
| 109 | unsigned node = *resultNode; |
| 110 | for ( int i = 0; i < ( int ) prefix.length(); ) { |
| 111 | utt::Node element; |
| 112 | element.Read( trie + node ); |
| 113 | bool found = false; |
| 114 | for ( int c = 0; c < ( int ) element.labelList.size(); c++ ) { |
| 115 | const utt::Label& label = element.labelList[c]; |
| 116 | bool equal = true; |
| 117 | for ( int subIndex = 0; subIndex < ( int ) label.string.length(); ++subIndex ) { |
| 118 | if ( i + subIndex >= ( int ) prefix.length() ) { |
| 119 | *missingPrefix = label.string.mid( subIndex ); |
| 120 | break; |
| 121 | } |
| 122 | if ( label.string[subIndex] != prefix[i + subIndex] ) { |
| 123 | equal = false; |
| 124 | break; |
| 125 | } |
| 126 | } |
| 127 | if ( !equal ) |
| 128 | continue; |
| 129 | |
| 130 | i += label.string.length(); |
| 131 | node = label.index; |
| 132 | found = true; |
| 133 | break; |
| 134 | |
| 135 | } |
| 136 | if ( !found ) |
| 137 | return false; |
| 138 | } |
| 139 | |
| 140 | *resultNode = node; |
| 141 | return true; |
| 142 | } |
| 143 | |
| 144 | int UnicodeTournamentTrieClient::getSuggestion( const char* trie, QStringList* resultNames, unsigned node, int count, const QString prefix ) |
| 145 | { |
| 146 | std::vector< Suggestion > candidates( 1 ); |
| 147 | candidates[0].index = node; |
| 148 | candidates[0].prefix = prefix; |
| 149 | candidates[0].importance = std::numeric_limits< unsigned >::max(); |
| 150 | |
| 151 | while( count > 0 && candidates.size() > 0 ) { |
| 152 | const Suggestion next = candidates[0]; |
| 153 | candidates[0] = candidates.back(); |
| 154 | candidates.pop_back(); |
| 155 | |
| 156 | utt::Node element; |
| 157 | element.Read( trie + next.index ); |
| 158 | bool isThis = true; |
| 159 | for ( std::vector< utt::Label >::const_iterator c = element.labelList.begin(), e = element.labelList.end(); c != e; ++c ) { |
| 160 | assert( c->importance <= next.importance ); |
| 161 | if ( c->importance == next.importance ) |
| 162 | isThis = false; |
| 163 | } |
| 164 | if ( isThis && element.dataList.size() > 0 ) { |
| 165 | assert( next.prefix.length() > 0 ); |
| 166 | QString suggestion = next.prefix[0].toUpper(); |
| 167 | for ( int i = 1; i < ( int ) next.prefix.length(); ++i ) { |
| 168 | if ( suggestion[i - 1] == ' ' || suggestion[i - 1] == '-' ) |
| 169 | suggestion += next.prefix[i].toUpper(); |
| 170 | else |
| 171 | suggestion += next.prefix[i]; |
| 172 | } |
| 173 | resultNames->push_back( suggestion ); |
| 174 | count--; |
| 175 | } |
| 176 | for ( std::vector< utt::Label >::const_iterator c = element.labelList.begin(), e = element.labelList.end(); c != e; ++c ) { |
| 177 | Suggestion nextEntry; |
| 178 | nextEntry.prefix = next.prefix + c->string; |
| 179 | nextEntry.index = c->index; |
| 180 | nextEntry.importance = c->importance; |
| 181 | candidates.push_back( nextEntry ); |
| 182 | } |
| 183 | std::sort( candidates.begin(), candidates.end() ); |
| 184 | if ( ( int ) candidates.size() > count ) |
| 185 | candidates.resize( count ); |
| 186 | } |
| 187 | |
| 188 | return count; |
| 189 | } |
| 190 | |
| 191 | bool UnicodeTournamentTrieClient::GetPlaceSuggestions( const QString& input, int amount, QStringList* suggestions, QStringList* inputSuggestions ) |
| 192 | { |
| 193 | unsigned node = 0; |
| 194 | QString prefix; |
| 195 | QString name = input.toLower(); |
| 196 | |
| 197 | if ( !find( trieData, &node, &prefix, name ) ) |
| 198 | return false; |
| 199 | |
| 200 | if ( prefix.length() == 0 ) { |
| 201 | utt::Node element; |
| 202 | element.Read( trieData + node ); |
| 203 | for ( std::vector< utt::Label >::const_iterator c = element.labelList.begin(), e = element.labelList.end(); c != e; ++c ) |
| 204 | inputSuggestions->push_back( input + c->string ); |
| 205 | } |
| 206 | else { |
| 207 | inputSuggestions->push_back( input + prefix ); |
| 208 | } |
| 209 | getSuggestion( trieData, suggestions, node, amount, name + prefix ); |
| 210 | std::sort( inputSuggestions->begin(), inputSuggestions->end() ); |
| 211 | return true; |
| 212 | } |
| 213 | |
| 214 | bool UnicodeTournamentTrieClient::SelectPlace( int id ) |
| 215 | { |
| 216 | placeID = id; |
| 217 | return true; |
| 218 | } |
| 219 | |
| 220 | bool UnicodeTournamentTrieClient::GetStreetSuggestions( const QString& input, int amount, QStringList* suggestions, QStringList* inputSuggestions ) |
| 221 | { |
| 222 | if ( placeID < 0 ) |
| 223 | return false; |
| 224 | unsigned node = 0; |
| 225 | QString prefix; |
| 226 | QString name = input.toLower(); |
| 227 | |
| 228 | if ( !find( subTrieData + placeID, &node, &prefix, name ) ) |
| 229 | return false; |
| 230 | |
| 231 | if ( prefix.length() == 0 ) { |
| 232 | utt::Node element; |
| 233 | element.Read( subTrieData + placeID + node ); |
| 234 | for ( std::vector< utt::Label >::const_iterator c = element.labelList.begin(), e = element.labelList.end(); c != e; ++c ) |
| 235 | inputSuggestions->push_back( input + c->string ); |
| 236 | } |
| 237 | else { |
| 238 | inputSuggestions->push_back( input + prefix ); |
| 239 | } |
| 240 | getSuggestion( subTrieData + placeID, suggestions, node, amount, name + prefix ); |
| 241 | std::sort( inputSuggestions->begin(), inputSuggestions->end() ); |
| 242 | return true; |
| 243 | } |
| 244 | |
| 245 | bool UnicodeTournamentTrieClient::GetPlaceData( QString input, QVector< int >* placeIDs, QVector< UnsignedCoordinate >* placeCoordinates ) |
| 246 | { |
| 247 | unsigned node = 0; |
| 248 | QString prefix; |
| 249 | QString name = input.toLower(); |
| 250 | if ( !find( trieData, &node, &prefix, name ) ) |
| 251 | return false; |
| 252 | |
| 253 | utt::Node element; |
| 254 | element.Read( trieData + node ); |
| 255 | |
| 256 | for ( std::vector< utt::Data >::const_iterator i = element.dataList.begin(), e = element.dataList.end(); i != e; ++i ) { |
| 257 | utt::CityData data; |
| 258 | data.Read( subTrieData + i->start ); |
| 259 | placeCoordinates->push_back( data.coordinate ); |
| 260 | placeIDs->push_back( i->start + data.GetSize() ); |
| 261 | } |
| 262 | |
| 263 | return placeIDs->size() != 0; |
| 264 | } |
| 265 | |
| 266 | bool UnicodeTournamentTrieClient::GetStreetData( QString input, QVector< int >* segmentLength, QVector< UnsignedCoordinate >* coordinates ) |
| 267 | { |
| 268 | if ( placeID < 0 ) |
| 269 | return false; |
| 270 | unsigned node = 0; |
| 271 | QString prefix; |
| 272 | QString name = input.toLower(); |
| 273 | if ( !find( subTrieData + placeID, &node, &prefix, name ) ) |
| 274 | return false; |
| 275 | |
| 276 | utt::Node element; |
| 277 | element.Read( subTrieData + placeID + node ); |
| 278 | |
| 279 | for ( std::vector< utt::Data >::const_iterator i = element.dataList.begin(), e = element.dataList.end(); i != e; ++i ) { |
| 280 | unsigned* buffer = new unsigned[i->length * 2]; |
| 281 | dataFile->seek( i->start * sizeof( unsigned ) * 2 ); |
| 282 | dataFile->read( ( char* ) buffer, i->length * 2 * sizeof( unsigned ) ); |
| 283 | for ( unsigned start = 0; start < i->length; ++start ) { |
| 284 | UnsignedCoordinate temp; |
| 285 | temp.x = buffer[start * 2]; |
| 286 | temp.y = buffer[start * 2 + 1]; |
| 287 | coordinates->push_back( temp ); |
| 288 | } |
| 289 | delete[] buffer; |
| 290 | segmentLength->push_back( coordinates->size() ); |
| 291 | } |
| 292 | |
| 293 | return segmentLength->size() != 0; |
| 294 | } |
| 295 | |
| 296 | Q_EXPORT_PLUGIN2(unicodetournamenttrieclient, UnicodeTournamentTrieClient) |
| 297 |
Branches:
master
