1 /*
2 * Copyright (C) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <sstream>
17 #include "wifi_comparator_impl.h"
18 #include "network_selection_utils.h"
19 #include "wifi_logger.h"
20
21 namespace OHOS::Wifi::NetworkSelection {
22 DEFINE_WIFILOG_LABEL("WifiComparatorImpl")
23
WifiScorerComparator(const std::string & comparatorName)24 WifiScorerComparator::WifiScorerComparator(const std::string &comparatorName)
25 : comparatorName(comparatorName) {}
26
AddScorer(const std::shared_ptr<IWifiScorer> & scorer)27 void WifiScorerComparator::AddScorer(const std::shared_ptr<IWifiScorer> &scorer)
28 {
29 if (scorer) {
30 scorers.emplace_back(scorer);
31 }
32 }
33
GetBestCandidates(const std::vector<NetworkCandidate * > & candidates,std::vector<NetworkCandidate * > & selectedCandidates)34 void WifiScorerComparator::GetBestCandidates(const std::vector<NetworkCandidate *> &candidates,
35 std::vector<NetworkCandidate *> &selectedCandidates)
36 {
37 /* if candidates is empty, it is unnecessary to score the candidate */
38 if (candidates.empty()) {
39 return;
40 }
41 std::vector<NetworkCandidate *> bestNetworkCandidates; //bestNetworkCandidates have founded.
42 std::vector<ScoreResult> bestNetworkScoreResults; //score records of bestNetworkCandidates.
43 bestNetworkCandidates.emplace_back(candidates.at(0)); //at first,we assume the first one is the best.
44 for (std::size_t i = 1; i < candidates.size(); ++i) {
45 bool isWorseNetworkCandidate = false;
46 auto networkCandidate = candidates.at(i);
47 for (std::size_t j = 0; j < scorers.size(); j++) {
48 auto scorer = scorers.at(j);
49 ScoreResult scoreResult;
50 if (bestNetworkScoreResults.size() <= j) {
51 /*
52 * if current scorer does not score best networkCandidate, we should score the bestCandidate
53 * by current scorer at first.
54 */
55 bestNetworkScoreResults.emplace_back(scoreResult);
56 scorer->DoScore(*bestNetworkCandidates.front(), bestNetworkScoreResults.at(j));
57 }
58 scorer->DoScore(*networkCandidate, scoreResult); // score current networkCandidate.
59 if (scoreResult.score > bestNetworkScoreResults.at(j).score) {
60 /*
61 * if the score of current networkCandidate is better than the best networkCandidate, it means we found
62 * a better networkCandidate, then log the best networkCandidates which should be abandon. clear the
63 * vector for best networkCandidates and score records, then continue for the next network candidate .
64 */
65 LogWorseSelectedCandidates(bestNetworkCandidates, *networkCandidate, bestNetworkScoreResults);
66 bestNetworkScoreResults.erase(bestNetworkScoreResults.begin() + j, bestNetworkScoreResults.end());
67 bestNetworkScoreResults.emplace_back(scoreResult);
68 bestNetworkCandidates.clear();
69 break;
70 } else if (scoreResult.score < bestNetworkScoreResults.at(j).score) {
71 /*
72 * if the score of current networkCandidate is worse than the best networkCandidate, log the msg of
73 * current network candidate, and continue the next networkCandidate.
74 */
75 LogWorseCandidate(*networkCandidate, *bestNetworkCandidates.front(), scoreResult);
76 isWorseNetworkCandidate = true;
77 break;
78 }
79 }
80 if (!isWorseNetworkCandidate) {
81 /* if the current networkCandidate is not worse than the best, add it to bestNetworkCandidates. */
82 bestNetworkCandidates.emplace_back(networkCandidate);
83 }
84 }
85 LogSelectedCandidates(bestNetworkCandidates, bestNetworkScoreResults);
86 selectedCandidates.insert(selectedCandidates.end(), bestNetworkCandidates.begin(), bestNetworkCandidates.end());
87 }
88
LogSelectedCandidates(std::vector<NetworkCandidate * > & selectedCandidates,std::vector<ScoreResult> & scoreResults)89 void WifiScorerComparator::LogSelectedCandidates(std::vector<NetworkCandidate *> &selectedCandidates,
90 std::vector<ScoreResult> &scoreResults)
91 {
92 WIFI_LOGI("%{public}s get best candidates %{public}s which get scores %{public}s",
93 comparatorName.c_str(),
94 NetworkSelectionUtils::GetNetworkCandidatesInfo(selectedCandidates).c_str(),
95 NetworkSelectionUtils::GetScoreResultsInfo(scoreResults).c_str());
96 }
97
LogWorseSelectedCandidates(std::vector<NetworkCandidate * > & worseNetworkCandidates,NetworkCandidate & betterNetworkCandidate,std::vector<ScoreResult> & scoreResults)98 void WifiScorerComparator::LogWorseSelectedCandidates(std::vector<NetworkCandidate *> &worseNetworkCandidates,
99 NetworkCandidate &betterNetworkCandidate,
100 std::vector<ScoreResult> &scoreResults)
101 {
102 WIFI_LOGD("%{public}s find a better candidate %{public}s, "
103 "abandon candidates %{public}s which get scores %{public}s",
104 comparatorName.c_str(),
105 betterNetworkCandidate.ToString().c_str(),
106 NetworkSelectionUtils::GetNetworkCandidatesInfo(worseNetworkCandidates).c_str(),
107 NetworkSelectionUtils::GetScoreResultsInfo(scoreResults).c_str());
108 }
109
LogWorseCandidate(NetworkCandidate & worseNetworkCandidates,NetworkCandidate & selectedNetworkCandidate,ScoreResult & scoreResult)110 void WifiScorerComparator::LogWorseCandidate(NetworkCandidate &worseNetworkCandidates,
111 NetworkCandidate &selectedNetworkCandidate,
112 ScoreResult &scoreResult)
113 {
114 WIFI_LOGD("%{public}s find a worse candidate %{public}s which getScore %{public}s"
115 ",and current best candidate is %{public}s",
116 comparatorName.c_str(),
117 worseNetworkCandidates.ToString().c_str(),
118 scoreResult.ToString().c_str(),
119 selectedNetworkCandidate.ToString().c_str());
120 }
121 }
122 // namespace OHOS::Wifi
123