[my-place] Refactoring: Code separation.
[platform/core/context/context-provider.git] / src / my-place / place / PlaceCateger.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "PlaceCateger.h"
18 #include "../utils/Median.h"
19 #include "../facade/UserPlacesParams.h"
20 #include "../facade/UserPlacesTypes.h"
21 #include <algorithm>
22 #include <Types.h>
23
24 void ctx::PlaceCateger::__reduceOutliers(ctx::Visits &visits)
25 {
26         int size = visits.size();
27         visits.erase(std::remove_if(
28                                         visits.begin(),
29                                         visits.end(),
30                                         [](Visit v)->bool {
31                                                 return v.categs[PLACE_CATEG_ID_HOME] < PLACES_CATEGER_MIN_VISITS_SCORE
32                                                                 && v.categs[PLACE_CATEG_ID_WORK] < PLACES_CATEGER_MIN_VISITS_SCORE
33                                                                 && v.categs[PLACE_CATEG_ID_OTHER] < PLACES_CATEGER_MIN_VISITS_SCORE;
34                                         }),
35                                 visits.end());
36         int newSize = visits.size();
37         if (size != newSize)
38                 _D("Visits number from %d to %d (visits min scores checking)", size, newSize);
39 }
40
41 /*
42  * Change category if home or work has to few visits
43  */
44 bool ctx::PlaceCateger::__reduceCategory(const PlaceCategId &categId, const ctx::Visits &visits)
45 {
46         return (categId == PLACE_CATEG_ID_HOME && visits.size() < PLACES_CATEGER_MIN_VISITS_PER_HOME)
47                 || (categId == PLACE_CATEG_ID_WORK && visits.size() < PLACES_CATEGER_MIN_VISITS_PER_WORK);
48 }
49
50 void ctx::PlaceCateger::categorize(ctx::Visits &visits, ctx::Place &place)
51 {
52         __reduceOutliers(visits);
53
54         place.categId = PLACE_CATEG_ID_NONE;
55         place.categConfidence = 0.0;
56
57         if (!visits.empty()) {
58                 const std::vector<PlaceCategId> categIds = {
59                         PLACE_CATEG_ID_HOME,
60                         PLACE_CATEG_ID_WORK,
61                         PLACE_CATEG_ID_OTHER
62                 };
63                 num_t sumScore = 0.0;
64                 num_t maxScore = 0.0;
65                 for (PlaceCategId categId : categIds) {
66                         std::vector<num_t> categVector = __categVectorFromVisits(visits, categId);
67                         int i, j;
68                         num_t score = median(categVector, i, j);
69                         sumScore += score;
70                         if (score > maxScore) {
71                                 maxScore = score;
72                                 place.categId = categId;
73                         }
74                 }
75                 if (sumScore > 0)
76                         place.categConfidence = maxScore / sumScore;
77                 if (__reduceCategory(place.categId, visits)) {
78                         place.categId = PLACE_CATEG_ID_OTHER;
79                         place.categConfidence = 0.0;
80                 }
81         }
82
83         place.name = __categId2Name(place.categId);
84 }
85
86 std::vector<ctx::num_t> ctx::PlaceCateger::__categVectorFromVisits(const ctx::Visits &visits, PlaceCategId categId)
87 {
88         std::vector<ctx::num_t> vec;
89         for (auto &visit : visits) {
90                 auto search = visit.categs.find(categId);
91                 if (search != visit.categs.end())
92                         vec.push_back(search->second);
93         }
94         return vec;
95 }
96
97 std::string ctx::PlaceCateger::__categId2Name(PlaceCategId categId) {
98         switch (categId) {
99         case PLACE_CATEG_ID_HOME:
100                 return "home";
101         case PLACE_CATEG_ID_WORK:
102                 return "work";
103         case PLACE_CATEG_ID_OTHER:
104                 return "other";
105         case PLACE_CATEG_ID_NONE:
106                 return "none";
107         default:
108                 return "";
109         }
110 }