When entering a map name, sort maps by some kind of similarity to the entered map name.

Previous behaviour was to ignore the entered map name, and reset it. This meant that typing a map name was actually
somewhat futile.
master
Cyp 2013-05-26 09:34:57 +02:00
parent 12dc9f7a24
commit d877928e9a
3 changed files with 75 additions and 11 deletions

View File

@ -2806,11 +2806,17 @@ static void processMultiopWidgets(UDWORD id)
sstrcpy(game.name,widgGetString(psWScreen, MULTIOP_GNAME));
break;
case MULTIOP_MAP:
widgSetString(psWScreen, MULTIOP_MAP,game.map);
case MULTIOP_GNAME_ICON:
break;
case MULTIOP_GNAME_ICON:
case MULTIOP_MAP:
widgDelete(psWScreen, MULTIOP_PLAYERS);
widgDelete(psWScreen, FRONTEND_SIDETEXT2); // del text too,
debug(LOG_WZ, "processMultiopWidgets[MULTIOP_MAP_ICON]: %s.wrf", MultiCustomMapsPath);
addMultiRequest(MultiCustomMapsPath, ".wrf", MULTIOP_MAP, current_tech, 0, widgGetString(psWScreen, MULTIOP_MAP));
widgSetString(psWScreen, MULTIOP_MAP, game.map);
break;
case MULTIOP_MAP_ICON:

View File

@ -73,6 +73,7 @@ bool MultiMenuUp = false;
static UDWORD context = 0;
UDWORD current_tech = 1;
UDWORD current_numplayers = 4;
static std::string current_searchString;
#define MULTIMENU_FORM_X 10 + D_W
#define MULTIMENU_FORM_Y 23 + D_H
@ -320,6 +321,56 @@ static void displayNumPlayersBut(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffse
}
static int stringRelevance(std::string const &string, std::string const &search)
{
QString str = QString::fromUtf8(string.c_str()).normalized(QString::NormalizationForm_KD);
QString sea = QString::fromUtf8(search.c_str()).normalized(QString::NormalizationForm_KD);
int strDim = str.size() + 1;
int seaDim = sea.size() + 1;
if (strDim > 10000 || seaDim > 10000 || strDim*seaDim > 100000)
{
return 0;
}
std::vector<unsigned> scores(strDim*seaDim);
for (int sum = 0; sum <= str.size() + sea.size(); ++sum)
for (int iStr = std::max(0, sum - sea.size()); iStr <= std::min(str.size(), sum - 0); ++iStr)
{
int iSea = sum - iStr;
unsigned score = 0;
if (iStr > 0 && iSea > 0)
{
score = (scores[iStr - 1 + (iSea - 1)*strDim] + 1) | 1;
QChar a = str[iStr - 1], b = sea[iSea - 1];
if (a == b)
{
score += 100;
}
else if (a.toUpper() == b.toUpper())
{
score += 80;
}
}
if (iStr > 0)
{
score = std::max(score, scores[iStr - 1 + iSea*strDim] & ~1);
}
if (iSea > 0)
{
score = std::max(score, scores[iStr + (iSea - 1)*strDim] & ~1);
}
scores[iStr + iSea*strDim] = score;
}
return scores[str.size() + sea.size()*strDim];
}
static bool reverseSortByFirst(std::pair<int, W_BUTTON *> const &a, std::pair<int, W_BUTTON *> const &b)
{
return a.first > b.first;
}
/** Searches in the given search directory for files ending with the
* given extension. Then will create a window with buttons for each
* found file.
@ -330,7 +381,7 @@ static void displayNumPlayersBut(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffse
* \param mode (purpose unknown)
* \param numPlayers (purpose unknown)
*/
void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD mode, UBYTE mapCam, UBYTE numPlayers)
void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD mode, UBYTE mapCam, UBYTE numPlayers, std::string const &searchString)
{
const unsigned int extensionLength = strlen(fileExtension);
const unsigned int buttonsX = (mode == MULTIOP_MAP) ? 22 : 17;
@ -340,6 +391,7 @@ void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD mo
{ // only save these when they select MAP button
current_tech = mapCam;
current_numplayers = numPlayers;
current_searchString = searchString;
}
char **fileList = PHYSFS_enumerateFiles(searchDir);
@ -408,6 +460,7 @@ void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD mo
if(mode == MULTIOP_MAP)
{
LEVEL_DATASET *mapData;
std::vector<std::pair<int, W_BUTTON *> > buttons;
bool first = true;
while ((mapData = enumerateMultiMaps(first, mapCam, numPlayers)) != NULL)
{
@ -420,10 +473,15 @@ void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD mo
button->setString(mapData->pName);
button->pUserData = mapData;
button->displayFunction = displayRequestOption;
requestList->addWidgetToLayout(button);
buttons.push_back(std::make_pair(stringRelevance(mapData->pName, searchString), button));
++nextButtonId;
}
std::stable_sort(buttons.begin(), buttons.end(), reverseSortByFirst);
for (std::vector<std::pair<int, W_BUTTON *> >::const_iterator i = buttons.begin(); i != buttons.end(); ++i)
{
requestList->addWidgetToLayout(i->second);
}
// if it's map select then add the cam style buttons.
sButInit = W_BUTINIT();
@ -532,19 +590,19 @@ bool runMultiRequester(UDWORD id, UDWORD *mode, QString *chosen, LEVEL_DATASET *
{
case M_REQUEST_C1:
closeMultiRequester();
addMultiRequest(MultiCustomMapsPath, ".wrf", MULTIOP_MAP, 1, current_numplayers);
addMultiRequest(MultiCustomMapsPath, ".wrf", MULTIOP_MAP, 1, current_numplayers, current_searchString);
break;
case M_REQUEST_C2:
closeMultiRequester();
addMultiRequest(MultiCustomMapsPath, ".wrf", MULTIOP_MAP, 2, current_numplayers);
addMultiRequest(MultiCustomMapsPath, ".wrf", MULTIOP_MAP, 2, current_numplayers, current_searchString);
break;
case M_REQUEST_C3:
closeMultiRequester();
addMultiRequest(MultiCustomMapsPath, ".wrf", MULTIOP_MAP, 3, current_numplayers);
addMultiRequest(MultiCustomMapsPath, ".wrf", MULTIOP_MAP, 3, current_numplayers, current_searchString);
break;
case M_REQUEST_AP:
closeMultiRequester();
addMultiRequest(MultiCustomMapsPath, ".wrf", MULTIOP_MAP, current_tech, 0);
addMultiRequest(MultiCustomMapsPath, ".wrf", MULTIOP_MAP, current_tech, 0, current_searchString);
break;
default:
for (unsigned numPlayers = 2; numPlayers <= MAX_PLAYERS_IN_GUI; ++numPlayers)
@ -552,7 +610,7 @@ bool runMultiRequester(UDWORD id, UDWORD *mode, QString *chosen, LEVEL_DATASET *
if (id == M_REQUEST_NP[numPlayers - 2])
{
closeMultiRequester();
addMultiRequest(MultiCustomMapsPath, ".wrf", MULTIOP_MAP, current_tech, numPlayers);
addMultiRequest(MultiCustomMapsPath, ".wrf", MULTIOP_MAP, current_tech, numPlayers, current_searchString);
break;
}
}

View File

@ -28,7 +28,7 @@
#include "stringdef.h"
// requester
extern void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD id,UBYTE mapCam, UBYTE numPlayers);
void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD id,UBYTE mapCam, UBYTE numPlayers, std::string const &searchString = std::string());
extern bool multiRequestUp;
extern W_SCREEN *psRScreen; // requester stuff.
bool runMultiRequester(UDWORD id, UDWORD *mode, QString *chosen, LEVEL_DATASET **chosenValue, bool *isHoverPreview);