MatchList::const_iterator filterOutBestMatch(const MatchList &input) { MatchList::const_iterator result = input.begin(); if (input.size() > 1) warning("Multiple entries found for id %d/%s", (*result)->first, getIdString((*result)->first)); for (MatchList::const_iterator i = input.begin(); i != input.end(); ++i) { // Reduce all entries to one single entry. // // We use the following rules for this (in this order): // - Prefer the entry with the higest size // - Prefer the entry, which starts at the smallest offest // // TODO: These rules might not be safe for all games, but hopefully // they will work fine. If there are any problems it should be rather // easy to identify them, since we print out a warning for multiple // entries found. if ((*result)->second.desc.hint.size <= (*i)->second.desc.hint.size) { if ((*result)->second.offset >= (*i)->second.offset) result = i; } } return result; }
upSimpleReport MatchResultList::regenerateReport() { // collect the numbers of all match groups in this round MatchMngr mm{db}; MatchGroupList mgl = mm.getMatchGroupsForCat(cat, round); if (mgl.size() > 1) { std::sort(mgl.begin(), mgl.end(), [](MatchGroup& mg1, MatchGroup& mg2){ if (mg1.getGroupNumber() < mg2.getGroupNumber()) return true; return false; }); } // prepare a subheader if we are in KO-rounds QString subHeader = QString(); if ((mgl.size() == 1) && (mgl.at(0).getGroupNumber() > 0)) { subHeader = GuiHelpers::groupNumToLongString(mgl.at(0).getGroupNumber()); } upSimpleReport result = createEmptyReport_Portrait(); QString repName = cat.getName() + tr(" -- Results of Round ") + QString::number(round); setHeaderAndHeadline(result.get(), repName, subHeader); // print a warning if the round is incomplete CatRoundStatus crs = cat.getRoundStatus(); if (round > crs.getFinishedRoundsCount()) { result->writeLine(tr("Note: the round is not finished yet; results are incomplete."), "", 1.0); } // print the results of each match group for (MatchGroup mg : mgl) { int grpNum = mg.getGroupNumber(); // print a header if we are in round-robin rounds if (grpNum > 0) { printIntermediateHeader(result, GuiHelpers::groupNumToLongString(grpNum)); } // print each finished match MatchList ml = mg.getMatches(); std::sort(ml.begin(), ml.end(), [](Match& m1, Match& m2){ return (m1.getMatchNumber() < m2.getMatchNumber()); }); printMatchList(result, ml, PlayerPairList(), GuiHelpers::groupNumToLongString(grpNum) + tr(" (cont.)"), true, false); result->skip(3.0); } // set header and footer setHeaderAndFooter(result, repName); return result; }
MatchList filterLanguageMatches(const int lang, const MatchList &input) { std::list<ExtractMap::const_iterator> result; for (MatchList::const_iterator i = input.begin(); i != input.end(); ++i) { if ((*i)->second.desc.lang == lang) result.push_back(*i); } return result; }
upSimpleReport MatchResultList_ByGroup::regenerateReport() { // collect the match groups with the requested match group number and // search in all rounds MatchMngr mm{db}; MatchGroupList mgl = mm.getMatchGroupsForCat(cat); MatchGroupList filteredList; for (MatchGroup mg: mgl) { if (mg.getGroupNumber() == grpNum) filteredList.push_back(mg); } // sort match groups by round number if (filteredList.size() > 1) { std::sort(filteredList.begin(), filteredList.end(), [](MatchGroup& mg1, MatchGroup& mg2){ if (mg1.getRound() < mg2.getRound()) return true; return false; }); } upSimpleReport result = createEmptyReport_Portrait(); QString repName = cat.getName() + tr(" -- Results of Group ") + QString::number(grpNum); setHeaderAndHeadline(result.get(), repName); for (MatchGroup mg : filteredList) { int round = mg.getRound(); printIntermediateHeader(result, tr("Round ") + QString::number(round)); MatchList maList = mg.getMatches(); std::sort(maList.begin(), maList.end(), [](Match& ma1, Match& ma2) { return ma1.getMatchNumber() < ma2.getMatchNumber(); }); printMatchList(result, maList, PlayerPairList(), tr("Results of round ") + QString::number(round) + tr(" (cont.)"), true, false); if (mg.getState() != STAT_MG_FINISHED) { result->skip(1.0); result->writeLine(tr("Note: this round is not finished yet; results for this group can be incomplete.")); } result->skip(3.0); } // set header and footer setHeaderAndFooter(result, repName); return result; }
void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority) { FSList subDirs; if (!directory.getChildren(subDirs)) return; String nextPattern, pattern; String::const_iterator sep = Common::find(origPattern.begin(), origPattern.end(), '/'); if (sep != origPattern.end()) { pattern = String(origPattern.begin(), sep); ++sep; if (sep != origPattern.end()) nextPattern = String(sep, origPattern.end()); } else { pattern = origPattern; } // TODO: The code we have for displaying all matches, which vary only in case, might // be a bit overhead, but as long as we want to display all useful information to the // user we will need to keep track of all directory names added so far. We might // want to reconsider this though. typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> MatchList; MatchList multipleMatches; MatchList::iterator matchIter; for (FSList::const_iterator i = subDirs.begin(); i != subDirs.end(); ++i) { String name = i->getName(); if (Common::matchString(name.c_str(), pattern.c_str(), ignoreCase)) { matchIter = multipleMatches.find(name); if (matchIter == multipleMatches.end()) { multipleMatches[name] = true; } else { if (matchIter->_value) { warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), matchIter->_key.c_str()); matchIter->_value = false; } warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), name.c_str()); } if (nextPattern.empty()) addDirectory(name, *i, priority); else addSubDirectoriesMatching(*i, nextPattern, ignoreCase, priority); } } }
Homography meanHomography(const Array<Feat>& feats1,const Array<Feat>& feats2,const MatchList& matches) { int nb=int(matches.size()); Matrix<double> A(2*nb,8); Vector<double> B(2*nb); A.fill(0); int k=0; // Completer: remplir A et B pour que H verifie AH=B for (MatchList::const_iterator it=matches.begin(); it!=matches.end(); k++,it++) { Vec2 m1=feats1[it->first].pos; Vec2 m2=feats2[it->second].pos; // ... } Matrix<double> C=pseudoInverse(A); // Moindres carr�s if(norm(C)==0) // non invertible return Homography(0.); Vector<double> H=C*B; return Homography(H.data()); // Painlesss Vector -> FVector conversion }
bool getExtractionData(const Game *g, Search &search, ExtractMap &map) { SearchMap searchMap; const int *needList = getNeedList(g); if (!needList) { fprintf(stderr, "ERROR: No entry need list available\n"); return false; } if (!setupSearch(g, needList, search, searchMap)) return false; // Process the data search Search::ResultList results; search.search(results); if (results.empty()) { fprintf(stderr, "ERROR: Couldn't find any required data\n"); return false; } ExtractMap temporaryExtractMap; for (const int *entry = needList; *entry != -1; ++entry) { typedef std::pair<SearchMap::const_iterator, SearchMap::const_iterator> KeyRange; KeyRange idRange = searchMap.equal_range(*entry); for (Search::ResultList::const_iterator i = results.begin(); i != results.end(); ++i) { for (SearchMap::const_iterator j = idRange.first; j != idRange.second; ++j) { if (j->second.hint == i->data) temporaryExtractMap.insert(ExtractMapEntry(*entry, ExtractData(j->second, i->offset))); } } } // Free up some memory results.clear(); searchMap.clear(); bool result = true; for (const int *entry = needList; *entry != -1; ++entry) { MatchList possibleMatches = filterPlatformMatches(g, temporaryExtractMap.equal_range(*entry)); if (possibleMatches.empty()) { fprintf(stderr, "ERROR: No entry found for id %d/%s\n", *entry, getIdString(*entry)); result = false; continue; } if (isLangSpecific(*entry)) { for (int i = 0; i < 3; ++i) { if (g->lang[i] == -1) continue; MatchList langMatches = filterLanguageMatches(g->lang[i], possibleMatches); MatchList::const_iterator bestMatch = filterOutBestMatch(langMatches); if (bestMatch == langMatches.end()) { // TODO: Add nice language name to output message. fprintf(stderr, "ERROR: No entry found for id %d/%s for language %d\n", *entry, getIdString(*entry), g->lang[i]); result = false; continue; } #ifdef DEBUG_EXTRACTION_TABLES if (((*bestMatch)->second.desc.platform != kPlatformUnknown && (*bestMatch)->second.desc.platform != g->platform)) printf("%s: %.8X %.8X %d %d\n", getIdString(*entry), (*bestMatch)->second.desc.hint.size, (*bestMatch)->second.desc.hint.byteSum, (*bestMatch)->second.desc.lang, (*bestMatch)->second.desc.platform); #endif map.insert(**bestMatch); } } else { MatchList::const_iterator bestMatch = filterOutBestMatch(possibleMatches); if (bestMatch == possibleMatches.end()) { fprintf(stderr, "ERROR: No entry found for id %d/%s\n", *entry, getIdString(*entry)); result = false; continue; } #ifdef DEBUG_EXTRACTION_TABLES if (((*bestMatch)->second.desc.platform != kPlatformUnknown && (*bestMatch)->second.desc.platform != g->platform)) printf("%s: %.8X %.8X %d %d\n", getIdString(*entry), (*bestMatch)->second.desc.hint.size, (*bestMatch)->second.desc.hint.byteSum, (*bestMatch)->second.desc.lang, (*bestMatch)->second.desc.platform); #endif map.insert(**bestMatch); } } return result; }