From: Mu-Woong Lee Date: Mon, 11 Jan 2016 12:54:59 +0000 (+0900) Subject: Import statistics-context-provider into src/statistics X-Git-Tag: submit/tizen/20160118.014643^2~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dff50c4591079653d41e79d5c62772eaa348e7e9;p=platform%2Fcore%2Fcontext%2Fcontext-provider.git Import statistics-context-provider into src/statistics Change-Id: I35a81227cc11518143aeae3b300ed71534cd97bf Signed-off-by: Mu-Woong Lee --- diff --git a/include/statistics_context_provider.h b/include/statistics_context_provider.h new file mode 100644 index 0000000..b45c3fd --- /dev/null +++ b/include/statistics_context_provider.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_STATISTICS_CONTEXT_PROVIDER_H__ +#define __CONTEXT_STATISTICS_CONTEXT_PROVIDER_H__ + +namespace ctx { + bool init_statistics_context_provider(); +} + +#endif /* __CONTEXT_STATISTICS_CONTEXT_PROVIDER_H__ */ diff --git a/packaging/context-provider.spec b/packaging/context-provider.spec index 84efb12..5746f9d 100644 --- a/packaging/context-provider.spec +++ b/packaging/context-provider.spec @@ -8,12 +8,27 @@ Source0: %{name}-%{version}.tar.gz %define BUILD_PROFILE %{?profile}%{!?profile:%{?tizen_profile_name}} +# Using the active window hooking for app monitoring, via ecore-x +%define ACTIVE_WINDOW_HOOK off + BuildRequires: cmake + BuildRequires: pkgconfig(context-common) BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(capi-system-device) BuildRequires: pkgconfig(capi-system-runtime-info) +BuildRequires: pkgconfig(capi-appfw-package-manager) +BuildRequires: pkgconfig(capi-appfw-application) +BuildRequires: pkgconfig(capi-appfw-app-manager) +BuildRequires: pkgconfig(pkgmgr) +BuildRequires: pkgconfig(pkgmgr-info) +BuildRequires: pkgconfig(capi-media-sound-manager) + +%if "%{ACTIVE_WINDOW_HOOK}" == "on" +BuildRequires: pkgconfig(ecore) +BuildRequires: pkgconfig(ecore-x) +%endif %if "%{?BUILD_PROFILE}" == "mobile" BuildRequires: pkgconfig(capi-network-bluetooth) @@ -23,6 +38,8 @@ BuildRequires: pkgconfig(tapi) BuildRequires: pkgconfig(msg-service) BuildRequires: pkgconfig(capi-messaging-email) BuildRequires: pkgconfig(motion) +BuildRequires: pkgconfig(contacts-service2) +BuildRequires: pkgconfig(capi-content-media-content) %endif %if "%{?BUILD_PROFILE}" == "wearable" @@ -37,6 +54,7 @@ BuildRequires: pkgconfig(motion) %if "%{?BUILD_PROFILE}" == "tv" BuildRequires: pkgconfig(capi-network-bluetooth) BuildRequires: pkgconfig(capi-network-wifi) +BuildRequires: pkgconfig(capi-content-media-content) %endif %description @@ -62,7 +80,8 @@ export CFLAGS+=" -DTIZEN_ENGINEER_MODE" export CXXFLAGS+=" -DTIZEN_ENGINEER_MODE" export FFLAGS+=" -DTIZEN_ENGINEER_MODE" -cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DMAJORVER=${MAJORVER} -DFULLVER=%{version} -DPROFILE=%{?BUILD_PROFILE} +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DMAJORVER=${MAJORVER} -DFULLVER=%{version} \ + -DPROFILE=%{?BUILD_PROFILE} -DACTIVE_WINDOW_HOOK=%{ACTIVE_WINDOW_HOOK} make %{?jobs:-j%jobs} %install diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a5a98d7..06f3799 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,10 +1,16 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) ADD_SUBDIRECTORY(device) -GET_DIRECTORY_PROPERTY(target DIRECTORY device DEFINITION target) -GET_DIRECTORY_PROPERTY(deps DIRECTORY device DEFINITION deps) -SET(target_all "${target_all} -l${target}") -SET(deps_list "${deps_list} ${deps}") +GET_DIRECTORY_PROPERTY(target_sub DIRECTORY device DEFINITION target) +GET_DIRECTORY_PROPERTY(deps_sub DIRECTORY device DEFINITION deps) +SET(target_all "${target_all} -l${target_sub}") +SET(deps_list "${deps_list} ${deps_sub}") + +ADD_SUBDIRECTORY(statistics) +GET_DIRECTORY_PROPERTY(target_sub DIRECTORY statistics DEFINITION target) +GET_DIRECTORY_PROPERTY(deps_sub DIRECTORY statistics DEFINITION deps) +SET(target_all "${target_all} -l${target_sub}") +SET(deps_list "${deps_list} ${deps_sub}") SEPARATE_ARGUMENTS(deps_list) LIST(REMOVE_DUPLICATES deps_list) diff --git a/src/statistics/CMakeLists.txt b/src/statistics/CMakeLists.txt new file mode 100644 index 0000000..d0ee7d6 --- /dev/null +++ b/src/statistics/CMakeLists.txt @@ -0,0 +1,62 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(target "ctx-statistics") + +# Common Options +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/shared +) + +# Common Profile +FILE(GLOB srcs ./*.cpp) +FILE(GLOB srcs ${srcs} shared/*.cpp) +FILE(GLOB srcs ${srcs} app/*.cpp) +FILE(GLOB srcs ${srcs} prediction/*.cpp) + +SET(deps "capi-system-runtime-info pkgmgr pkgmgr-info capi-appfw-package-manager") +SET(deps "${deps} capi-appfw-application capi-appfw-app-manager") +SET(deps "${deps} capi-media-sound-manager") + +IF("${ACTIVE_WINDOW_HOOK}" STREQUAL "on") + ADD_DEFINITIONS("-D_USE_ACTIVE_WINDOW_HOOKING_") + SET(deps "${deps} ecore ecore-x") + SET(srcs ${srcs} app/app_use_monitor/active_window_monitor.cpp) +ELSE("${ACTIVE_WINDOW_HOOK}" STREQUAL "on") + SET(srcs ${srcs} app/app_use_monitor/launch_monitor.cpp) +ENDIF("${ACTIVE_WINDOW_HOOK}" STREQUAL "on") + +# Mobile Profile +IF("${PROFILE}" STREQUAL "mobile") + FILE(GLOB srcs ${srcs} media/*.cpp) + FILE(GLOB srcs ${srcs} social/*.cpp) + SET(deps "${deps} contacts-service2 capi-content-media-content") +ENDIF("${PROFILE}" STREQUAL "mobile") + +# Wearable Profile +#IF("${PROFILE}" STREQUAL "wearable") +#ENDIF("${PROFILE}" STREQUAL "wearable") + +# TV Profile +IF("${PROFILE}" STREQUAL "tv") + FILE(GLOB srcs ${srcs} media/*.cpp) + SET(deps "${deps} capi-content-media-content") +ENDIF("${PROFILE}" STREQUAL "tv") + +MESSAGE("Statistics Provider Sources: ${srcs}") + +# Build +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(stats_pkgs REQUIRED ${deps_common} ${deps}) + +FOREACH(flag ${stats_pkgs_CFLAGS}) + SET(extra_cflags "${extra_cflags} ${flag}") +ENDFOREACH(flag) + +ADD_LIBRARY(${target} SHARED ${srcs}) +TARGET_LINK_LIBRARIES(${target} ${stats_pkgs_LDFLAGS}) +SET_TARGET_PROPERTIES(${target} PROPERTIES COMPILE_FLAGS ${extra_cflags}) +SET_TARGET_PROPERTIES(${target} PROPERTIES COMPILE_DEFINITIONS "LOG_TAG=\"CONTEXT-STATS\"") +SET_TARGET_PROPERTIES(${target} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${target} PROPERTIES VERSION ${FULLVER}) + +# Install +INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT RuntimeLibraries) diff --git a/src/statistics/app/app_stats_provider.cpp b/src/statistics/app/app_stats_provider.cpp new file mode 100644 index 0000000..59a224b --- /dev/null +++ b/src/statistics/app/app_stats_provider.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "app_stats_provider.h" +#include "db_handle.h" + +#include "db_init.h" +#include "install_monitor.h" + +#ifdef _USE_ACTIVE_WINDOW_HOOKING_ +#include "app_use_monitor/active_window_monitor.h" +#else +#include "app_use_monitor/launch_monitor.h" +#endif + +static ctx::app_install_monitor *install_mon = NULL; +static ctx::app_use_monitor *launch_mon = NULL; + +ctx::app_statistics_provider *ctx::app_statistics_provider::__instance = NULL; + +ctx::app_statistics_provider::app_statistics_provider() +{ +} + +ctx::app_statistics_provider::~app_statistics_provider() +{ + delete install_mon; + delete launch_mon; + install_mon = NULL; + launch_mon = NULL; +} + +ctx::context_provider_iface *ctx::app_statistics_provider::create(void *data) +{ + IF_FAIL_RETURN(!__instance, __instance); + + __instance = new(std::nothrow) app_statistics_provider(); + IF_FAIL_RETURN_TAG(__instance, NULL, _E, "Memory allocation failed"); + + _I(BLUE("Created")); + + if (!__instance->init()) { + destroy(data); + return NULL; + } + + return __instance; +} + +void ctx::app_statistics_provider::destroy(void *data) +{ + IF_FAIL_VOID(__instance); + delete __instance; + __instance = NULL; + _I(BLUE("Destroyed")); +} + +bool ctx::app_statistics_provider::is_supported(const char* subject) +{ + return true; +} + +void ctx::app_statistics_provider::submit_trigger_item() +{ + context_manager::register_trigger_item(APP_SUBJ_FREQUENCY, OPS_READ, + "{" TRIG_DEF_RANK "," TRIG_DEF_TOTAL_COUNT "}", + "{" + "\"AppId\":{\"type\":\"string\"}," + TRIG_DEF_TIME_OF_DAY "," TRIG_DEF_DAY_OF_WEEK + "}"); +} + +bool ctx::app_statistics_provider::init() +{ + app_db_initializer *initializer = new(std::nothrow) app_db_initializer(); + IF_FAIL_RETURN_TAG(initializer, false, _E, "Memory allocation failed"); + + install_mon = new(std::nothrow) ctx::app_install_monitor(); + launch_mon = new(std::nothrow) ctx::app_use_monitor(); + IF_FAIL_CATCH_TAG(install_mon && launch_mon, _E, "Memory allocation failed"); + return true; + +CATCH: + delete install_mon; + delete launch_mon; + install_mon = NULL; + launch_mon = NULL; + return false; +} + +int ctx::app_statistics_provider::subscribe(const char* subject, ctx::json option, ctx::json* request_result) +{ + return ERR_NOT_SUPPORTED; +} + +int ctx::app_statistics_provider::unsubscribe(const char* subject, ctx::json option) +{ + return ERR_NOT_SUPPORTED; +} + +int ctx::app_statistics_provider::read(const char* subject, ctx::json option, ctx::json* request_result) +{ + ctx::app_db_handle *handle = new(std::nothrow) ctx::app_db_handle(); + IF_FAIL_RETURN_TAG(handle, ERR_OPERATION_FAILED, _E, "Memory allocation failed"); + + int err = handle->read(subject, option); + if (err != ERR_NONE) { + delete handle; + return err; + } + + return ERR_NONE; +} + +int ctx::app_statistics_provider::write(const char* subject, ctx::json data, ctx::json* request_result) +{ + return ERR_NOT_SUPPORTED; +} diff --git a/src/statistics/app/app_stats_provider.h b/src/statistics/app/app_stats_provider.h new file mode 100644 index 0000000..f5804bd --- /dev/null +++ b/src/statistics/app/app_stats_provider.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_APP_STATS_PROVIDER_H__ +#define __CONTEXT_APP_STATS_PROVIDER_H__ + +#include +#include "app_stats_types.h" + +namespace ctx { + + class app_statistics_provider : public context_provider_iface { + public: + static context_provider_iface *create(void *data); + static void destroy(void *data); + static bool is_supported(const char *subject); + static void submit_trigger_item(); + + int subscribe(const char *subject, ctx::json option, ctx::json *request_result); + int unsubscribe(const char *subject, ctx::json option); + int read(const char *subject, ctx::json option, ctx::json *request_result); + int write(const char *subject, ctx::json data, ctx::json *request_result); + + private: + static app_statistics_provider *__instance; + + app_statistics_provider(); + ~app_statistics_provider(); + bool init(); + + }; /* class app_statistics_provider */ + +} /* namespace ctx */ + +#endif /* __CONTEXT_APP_STATS_PROVIDER_H__ */ diff --git a/src/statistics/app/app_stats_types.h b/src/statistics/app/app_stats_types.h new file mode 100644 index 0000000..96ed505 --- /dev/null +++ b/src/statistics/app/app_stats_types.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_APP_STATS_TYPES_H__ +#define __CONTEXT_APP_STATS_TYPES_H__ + +#include + +#define APP_HISTORY_PRIV "apphistory.read" +#define APP_SUBJ_RECENTLY_USED "stats/app/recently" +#define APP_SUBJ_FREQUENTLY_USED "stats/app/often" +#define APP_SUBJ_RARELY_USED "stats/app/rarely" +#define APP_SUBJ_PEAK_TIME "stats/app/peak_time" +#define APP_SUBJ_COMMON_SETTING "stats/app/setting" +#define APP_SUBJ_FREQUENCY "stats/app/frequency" + +#define APP_TABLE_REMOVABLE_APP "Log_RemovableApp" +#define APP_TABLE_REMOVABLE_APP_COLUMNS \ + "AppId TEXT NOT NULL UNIQUE" + +#define APP_TABLE_USAGE_LOG "Log_AppLaunch" +#define APP_TABLE_USAGE_LOG_COLUMNS \ + "AppId TEXT NOT NULL, Duration INTEGER NOT NULL DEFAULT 0, " \ + "SystemVolume INTEGER, MediaVolume INTEGER, AudioJack INTEGER, " \ + "BSSID TEXT, " \ + "UTC TIMESTAMP DEFAULT (strftime('%s', 'now')), " \ + "LocalTime TIMESTAMP DEFAULT (strftime('%s', 'now', 'localtime'))" + +#define APP_TEMP_USAGE_FREQ "Temp_AppLaunchFreq" +#define APP_TEMP_USAGE_FREQ_SQL \ + "CREATE TABLE IF NOT EXISTS " APP_TEMP_USAGE_FREQ \ + " (AppId TEXT NOT NULL UNIQUE, TotalCount INTEGER DEFAULT 0);" + +#endif diff --git a/src/statistics/app/app_use_monitor/active_window_monitor.cpp b/src/statistics/app/app_use_monitor/active_window_monitor.cpp new file mode 100644 index 0000000..1aca2c7 --- /dev/null +++ b/src/statistics/app/app_use_monitor/active_window_monitor.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include "../app_stats_types.h" +#include "active_window_monitor.h" + +/* Active window changes frequently. + * We thus consider the apps being foregrounded at least 3 secs */ +#define MIN_VALID_USE_TIME 2 + +#define ONE_DAY_IN_SEC 86400 + +static Ecore_Event_Handler *window_property_event_handler = NULL; + +ctx::app_use_monitor::app_use_monitor() + : last_cleanup_time(0) + , last_timestamp(0) + , last_pid(-1) +{ + start_logging(); +} + +ctx::app_use_monitor::~app_use_monitor() +{ + stop_logging(); +} + +bool ctx::app_use_monitor::start_logging() +{ + /* This ecore_x based approach does not work with virtualization features */ + if(window_property_event_handler == NULL) { + ecore_x_init(NULL); + ecore_x_event_mask_set(ecore_x_window_root_first_get(), ECORE_X_EVENT_MASK_WINDOW_PROPERTY); + window_property_event_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, on_window_property_changed, this); + IF_FAIL_RETURN_TAG(window_property_event_handler, false, _E, "ecore_event_handler_add() failed"); + _D("Active window monitoring started"); + } + + return true; +} + +void ctx::app_use_monitor::stop_logging() +{ + if (window_property_event_handler) { + ecore_event_handler_del(window_property_event_handler); + window_property_event_handler = NULL; + _D("Active window monitoring stopped"); + } +} + +Eina_Bool ctx::app_use_monitor::on_window_property_changed(void* data, int type, void* event) +{ + IF_FAIL_RETURN_TAG(data && event, ECORE_CALLBACK_PASS_ON, _W, "Invalid window event"); + + Ecore_X_Event_Window_Property *property = static_cast(event); + Ecore_X_Atom atom = ecore_x_atom_get("_NET_ACTIVE_WINDOW"); + + IF_FAIL_RETURN(property->atom == atom, ECORE_CALLBACK_PASS_ON); + + int pid = 0; + Ecore_X_Window win = 0; + + ecore_x_window_prop_window_get(property->win, atom, &win, 1); + ecore_x_netwm_pid_get(win, &pid); + + IF_FAIL_RETURN_TAG(pid > 0, ECORE_CALLBACK_PASS_ON, _W, "Invalid pid"); + + app_use_monitor *instance = static_cast(data); + instance->on_active_window_changed(pid); + + return ECORE_CALLBACK_PASS_ON; +} + +void ctx::app_use_monitor::on_active_window_changed(int pid) +{ + IF_FAIL_VOID(last_pid != pid); + _D("Active window changed: PID-%d", pid); + + int timestamp = static_cast(time(NULL)); + int duration = timestamp - last_timestamp; + + if (!last_app_id.empty() > 0 && duration >= MIN_VALID_USE_TIME) + verify_used_app(last_app_id.c_str(), duration); + + last_timestamp = timestamp; + last_pid = pid; + + char *app_id = NULL; + app_manager_get_app_id(pid, &app_id); + last_app_id = (app_id ? app_id : ""); + g_free(app_id); + _D("Current Active App: %s", last_app_id.c_str()); +} + +void ctx::app_use_monitor::verify_used_app(const char *app_id, int duration) +{ + app_info_h app_info = NULL; + int err = app_manager_get_app_info(app_id, &app_info); + IF_FAIL_VOID_TAG(err == APP_MANAGER_ERROR_NONE && app_info, _E, "app_manager_get_app_info() failed"); + + bool nodisp = false; + err = app_info_is_nodisplay(app_info, &nodisp); + IF_FAIL_CATCH_TAG(err == APP_MANAGER_ERROR_NONE, _E, "app_info_is_nodisplay() failed"); + IF_FAIL_CATCH(!nodisp); + + insert_log(app_id, duration); + +CATCH: + if (app_info) + app_info_destroy(app_info); +} + +void ctx::app_use_monitor::insert_log(const char *app_id, int duration) +{ + int audiojack; + int system_volume; + int media_volume; + std::string bssid; + + std::stringstream cols; + std::stringstream vals; + + /* App ID */ + cols << STATS_APP_ID << ","; + vals << "'" << app_id << "',"; + + /* Audio Jack */ + if (ctx::system_info::get_audio_jack_state(&audiojack)) { + cols << STATS_AUDIO_JACK << ","; + vals << audiojack << ","; + } + + /* Volume */ + if (ctx::system_info::get_volume(&system_volume, &media_volume)) { + cols << STATS_SYSTEM_VOLUME << "," << STATS_MEDIA_VOLUME << ","; + vals << system_volume << "," << media_volume << ","; + } + + /* BSSID */ + if (ctx::system_info::get_wifi_bssid(bssid)) { + cols << STATS_BSSID << ","; + vals << "'" << bssid << "',"; + } + + /* Time */ + cols << STATS_UNIV_TIME << ","; + vals << "(strftime('%s', 'now')) - " << duration << ","; + + cols << STATS_LOCAL_TIME << ","; + vals << "(strftime('%s', 'now', 'localtime')) - " << duration << ","; + + /* Duration */ + cols << STATS_DURATION; + vals << duration; + + std::stringstream query; + append_cleanup_query(query); + query << "INSERT INTO " << APP_TABLE_USAGE_LOG << " (" + << cols.str() << ") VALUES (" << vals.str() << ")"; + + db_manager::execute(0, query.str().c_str(), NULL); +} + +void ctx::app_use_monitor::append_cleanup_query(std::stringstream &query) +{ + IF_FAIL_VOID(last_timestamp - last_cleanup_time >= ONE_DAY_IN_SEC); + + last_cleanup_time = last_timestamp; + + query << "DELETE FROM " APP_TABLE_USAGE_LOG " WHERE " \ + STATS_UNIV_TIME " < strftime('%s', 'now') - " << LOG_RETENTION_PERIOD << ";"; +} diff --git a/src/statistics/app/app_use_monitor/active_window_monitor.h b/src/statistics/app/app_use_monitor/active_window_monitor.h new file mode 100644 index 0000000..443d2bc --- /dev/null +++ b/src/statistics/app/app_use_monitor/active_window_monitor.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_APP_USE_MONITOR_H__ +#define __CONTEXT_APP_USE_MONITOR_H__ + +#include +#include +#include + +namespace ctx { + + class app_use_monitor { + private: + int last_cleanup_time; + int last_timestamp; + int last_pid; + std::string last_app_id; + + bool start_logging(void); + void stop_logging(void); + + void verify_used_app(const char *app_id, int duration); + void insert_log(const char *app_id, int duration); + void append_cleanup_query(std::stringstream &query); + + void on_active_window_changed(int pid); + static Eina_Bool on_window_property_changed(void* data, int type, void* event); + + public: + app_use_monitor(); + ~app_use_monitor(); + }; /* class app_use_monitor */ + +} /* namespace ctx */ + +#endif /* __CONTEXT_APP_USE_MONITOR_H__ */ diff --git a/src/statistics/app/app_use_monitor/launch_monitor.cpp b/src/statistics/app/app_use_monitor/launch_monitor.cpp new file mode 100644 index 0000000..4421063 --- /dev/null +++ b/src/statistics/app/app_use_monitor/launch_monitor.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include "../app_stats_types.h" +#include "launch_monitor.h" + +ctx::app_use_monitor::app_use_monitor() +{ + start_logging(); +} + +ctx::app_use_monitor::~app_use_monitor() +{ + stop_logging(); +} + +bool ctx::app_use_monitor::start_logging() +{ + int err = app_manager_set_app_context_event_cb(app_context_event_cb, this); + IF_FAIL_RETURN_TAG(err == APP_MANAGER_ERROR_NONE, false, _E, "app_manager_set_app_context_event_cb() failed"); + return true; +} + +void ctx::app_use_monitor::stop_logging() +{ + app_manager_unset_app_context_event_cb(); +} + +void ctx::app_use_monitor::app_context_event_cb(app_context_h app_context, app_context_event_e event, void *user_data) +{ + char *app_id = NULL; + int err = app_context_get_app_id(app_context, &app_id); + IF_FAIL_VOID_TAG(err == APP_MANAGER_ERROR_NONE, _E, "app_context_get_app_id() failed"); + + app_use_monitor *monitor = static_cast(user_data); + + if (event == APP_CONTEXT_EVENT_LAUNCHED) { + monitor->log_launch_event(app_id); + } else if (event == APP_CONTEXT_EVENT_TERMINATED) { + monitor->log_terminate_event(app_id); + } + g_free(app_id); +} + +void ctx::app_use_monitor::log_launch_event(const char* app_id) +{ + int audiojack; + int system_volume; + int media_volume; + std::string bssid; + json data; + data.set(NULL, STATS_APP_ID, app_id); + + if (ctx::system_info::get_audio_jack_state(&audiojack)) + data.set(NULL, STATS_AUDIO_JACK, audiojack); + + if (ctx::system_info::get_volume(&system_volume, &media_volume)) { + data.set(NULL, STATS_SYSTEM_VOLUME, system_volume); + data.set(NULL, STATS_MEDIA_VOLUME, media_volume); + } + + if (ctx::system_info::get_wifi_bssid(bssid)) + data.set(NULL, STATS_BSSID, bssid); + + db_manager::insert(0, APP_TABLE_USAGE_LOG, data, NULL); +} + +void ctx::app_use_monitor::log_terminate_event(const char* app_id) +{ + std::stringstream query; + query << + "UPDATE " APP_TABLE_USAGE_LOG \ + " SET " STATS_DURATION " = strftime('%s', 'now') - " STATS_UNIV_TIME \ + " WHERE " STATS_COL_ROW_ID " = (" \ + "SELECT MAX(" STATS_COL_ROW_ID ") FROM " APP_TABLE_USAGE_LOG \ + " WHERE " STATS_APP_ID " = '" << app_id << "'" \ + " AND " STATS_DURATION " = 0)"; + db_manager::execute(0, query.str().c_str(), NULL); +} diff --git a/src/statistics/app/app_use_monitor/launch_monitor.h b/src/statistics/app/app_use_monitor/launch_monitor.h new file mode 100644 index 0000000..43b3f66 --- /dev/null +++ b/src/statistics/app/app_use_monitor/launch_monitor.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_APP_USE_MONITOR_H__ +#define __CONTEXT_APP_USE_MONITOR_H__ + +#include +#include + +namespace ctx { + + class app_use_monitor : public db_listener_iface { + private: + bool start_logging(void); + void stop_logging(void); + + void log_launch_event(const char* app_id); + void log_terminate_event(const char* app_id); + + void on_creation_result_received(unsigned int query_id, int error) {} + void on_insertion_result_received(unsigned int query_id, int error, int64_t row_id) {} + void on_query_result_received(unsigned int query_id, int error, std::vector& records) {} + + static void app_context_event_cb(app_context_h app_context, app_context_event_e event, void *user_data); + + public: + app_use_monitor(); + ~app_use_monitor(); + }; /* class app_use_monitor */ + +} /* namespace ctx */ + +#endif /* __CONTEXT_APP_USE_MONITOR_H__ */ diff --git a/src/statistics/app/db_handle.cpp b/src/statistics/app/db_handle.cpp new file mode 100644 index 0000000..5491d24 --- /dev/null +++ b/src/statistics/app/db_handle.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "app_stats_types.h" +#include "db_handle.h" + +ctx::app_db_handle::app_db_handle() +{ +} + +ctx::app_db_handle::~app_db_handle() +{ +} + +int ctx::app_db_handle::read(const char* subject, ctx::json filter) +{ + std::string query; + + if (STR_EQ(subject, APP_SUBJ_RECENTLY_USED)) { + query = create_sql_recently_used(filter); + + } else if (STR_EQ(subject, APP_SUBJ_FREQUENTLY_USED)) { + query = create_sql_frequently_used(filter); + + } else if (STR_EQ(subject, APP_SUBJ_RARELY_USED)) { + query = create_sql_rarely_used(filter); + + } else if (STR_EQ(subject, APP_SUBJ_PEAK_TIME)) { + query = create_sql_peak_time(filter); + + } else if (STR_EQ(subject, APP_SUBJ_COMMON_SETTING)) { + query = create_sql_common_setting(filter); + + } else if (STR_EQ(subject, APP_SUBJ_FREQUENCY)) { + is_trigger_item = true; + query = create_sql_frequency(filter); + } + + IF_FAIL_RETURN(!query.empty(), ERR_OPERATION_FAILED); + + bool ret = execute_query(subject, filter, query.c_str()); + IF_FAIL_RETURN(ret, ERR_OPERATION_FAILED); + + return ERR_NONE; +} + +std::string ctx::app_db_handle::create_where_clause_with_device_status(ctx::json filter) +{ + std::stringstream where_clause; + std::string bssid; + int audio_jack; + + where_clause << stats_db_handle_base::create_where_clause(filter); + + if (filter.get(NULL, STATS_BSSID, &bssid)) + where_clause << " AND " STATS_BSSID " = '" << bssid << "'"; + + if (filter.get(NULL, STATS_AUDIO_JACK, &audio_jack)) + where_clause << " AND " STATS_AUDIO_JACK " = " << audio_jack; + + return where_clause.str(); +} + +std::string ctx::app_db_handle::create_sql_peak_time(ctx::json filter) +{ + return stats_db_handle_base::create_sql_peak_time(filter, APP_TABLE_USAGE_LOG, create_where_clause(filter)); +} + +std::string ctx::app_db_handle::create_sql_common_setting(ctx::json filter) +{ + return stats_db_handle_base::create_sql_common_setting(filter, APP_TABLE_USAGE_LOG, create_where_clause(filter)); +} + +std::string ctx::app_db_handle::create_sql_frequency(ctx::json filter) +{ + ctx::json filter_cleaned; + std::string week_str; + std::string time_of_day; + std::string app_id; + + if (!filter.get(NULL, STATS_APP_ID, &app_id)) { + _E("Invalid parameter"); + return ""; + } + + if (filter.get(NULL, STATS_DAY_OF_WEEK, &week_str)) + filter_cleaned.set(NULL, STATS_DAY_OF_WEEK, week_str); + + if (filter.get(NULL, STATS_TIME_OF_DAY, &time_of_day)) + filter_cleaned.set(NULL, STATS_TIME_OF_DAY, time_of_day); + + std::string where_clause = create_where_clause(filter_cleaned); + + std::stringstream query; + + query << + "DELETE FROM " APP_TEMP_USAGE_FREQ ";"; + + query << + "INSERT INTO " APP_TEMP_USAGE_FREQ \ + " SELECT " STATS_APP_ID ", COUNT(*) AS " STATS_TOTAL_COUNT \ + " FROM " APP_TABLE_USAGE_LOG \ + " WHERE " << where_clause << + " GROUP BY " STATS_APP_ID ";"; + + query << + "INSERT OR IGNORE INTO " APP_TEMP_USAGE_FREQ " (" STATS_APP_ID ")" \ + " VALUES ('" << app_id << "');"; + + query << + "SELECT S." STATS_APP_ID ", S." STATS_TOTAL_COUNT ", 1+COUNT(lesser." STATS_TOTAL_COUNT ") AS " STATS_RANK \ + " FROM " APP_TEMP_USAGE_FREQ " AS S" \ + " LEFT JOIN " APP_TEMP_USAGE_FREQ " AS lesser" \ + " ON S." STATS_TOTAL_COUNT " < lesser." STATS_TOTAL_COUNT \ + " WHERE S." STATS_APP_ID " = '" << app_id << "'"; + + return query.str(); +} + +std::string ctx::app_db_handle::create_sql_recently_used(ctx::json filter) +{ + std::stringstream query; + int limit = DEFAULT_LIMIT; + + filter.get(NULL, STATS_RESULT_SIZE, &limit); + + query << + "SELECT " STATS_APP_ID ", " \ + "COUNT(*) AS " STATS_TOTAL_COUNT ", " \ + "SUM(" STATS_DURATION ") AS " STATS_TOTAL_DURATION ", " \ + "MAX(" STATS_UNIV_TIME ") AS " STATS_LAST_TIME \ + " FROM " APP_TABLE_USAGE_LOG \ + " WHERE " << create_where_clause_with_device_status(filter) << + " GROUP BY " STATS_APP_ID \ + " ORDER BY MAX(" STATS_UNIV_TIME ") DESC" \ + " LIMIT " << limit; + + return query.str(); +} + +std::string ctx::app_db_handle::create_sql_frequently_used(ctx::json filter) +{ + std::stringstream query; + int limit = DEFAULT_LIMIT; + + filter.get(NULL, STATS_RESULT_SIZE, &limit); + + query << + "SELECT " STATS_APP_ID ", " \ + "COUNT(*) AS " STATS_TOTAL_COUNT ", " \ + "SUM(" STATS_DURATION ") AS " STATS_TOTAL_DURATION ", " \ + "MAX(" STATS_UNIV_TIME ") AS " STATS_LAST_TIME \ + " FROM " APP_TABLE_USAGE_LOG \ + " WHERE " << create_where_clause_with_device_status(filter) << + " GROUP BY " STATS_APP_ID \ + " ORDER BY COUNT(*) DESC" \ + " LIMIT " << limit; + + return query.str(); +} + +std::string ctx::app_db_handle::create_sql_rarely_used(ctx::json filter) +{ + std::stringstream query; + int limit = DEFAULT_LIMIT; + + filter.get(NULL, STATS_RESULT_SIZE, &limit); + + query << + "SELECT i." STATS_APP_ID ", " \ + "COUNT(u." STATS_DURATION ") AS " STATS_TOTAL_COUNT ", " \ + "IFNULL(SUM(u." STATS_DURATION "),0) AS " STATS_TOTAL_DURATION ", " \ + "IFNULL(MAX(u." STATS_UNIV_TIME "),-1) AS " STATS_LAST_TIME \ + " FROM " APP_TABLE_REMOVABLE_APP " i LEFT OUTER JOIN (" \ + " SELECT * FROM " APP_TABLE_USAGE_LOG \ + " WHERE " << create_where_clause_with_device_status(filter) << ") u" \ + " ON i." STATS_APP_ID " = u." STATS_APP_ID \ + " GROUP BY i." STATS_APP_ID \ + " ORDER BY " STATS_TOTAL_COUNT " ASC" \ + " LIMIT " << limit; + + return query.str(); +} + +void ctx::app_db_handle::reply_trigger_item(int error, ctx::json &json_result) +{ + IF_FAIL_VOID_TAG(STR_EQ(req_subject.c_str(), APP_SUBJ_FREQUENCY), _E, "Invalid subject"); + + ctx::json results; + std::string val_str; + int val; + + json_result.get(NULL, STATS_APP_ID, &val_str); + results.set(NULL, STATS_APP_ID, val_str); + json_result.get(NULL, STATS_TOTAL_COUNT, &val); + results.set(NULL, STATS_TOTAL_COUNT, val); + json_result.get(NULL, STATS_RANK, &val); + results.set(NULL, STATS_RANK, val); + + context_manager::reply_to_read(req_subject.c_str(), req_filter, error, results); +} diff --git a/src/statistics/app/db_handle.h b/src/statistics/app/db_handle.h new file mode 100644 index 0000000..8cb2659 --- /dev/null +++ b/src/statistics/app/db_handle.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_APP_DB_HANDLE_H__ +#define __CONTEXT_APP_DB_HANDLE_H__ + +#include +#include +#include + +namespace ctx { + class app_db_handle : public stats_db_handle_base { + public: + app_db_handle(); + ~app_db_handle(); + + int read(const char* subject, ctx::json filter); + + private: + std::string create_where_clause_with_device_status(ctx::json filter); + std::string create_sql_recently_used(ctx::json filter); + std::string create_sql_frequently_used(ctx::json filter); + std::string create_sql_rarely_used(ctx::json filter); + std::string create_sql_peak_time(ctx::json filter); + std::string create_sql_common_setting(ctx::json filter); + std::string create_sql_frequency(ctx::json filter); + void reply_trigger_item(int error, ctx::json &json_result); + }; +} + +#endif /* __CONTEXT_APP_DB_HANDLE_H__ */ diff --git a/src/statistics/app/db_init.cpp b/src/statistics/app/db_init.cpp new file mode 100644 index 0000000..a5a7af9 --- /dev/null +++ b/src/statistics/app/db_init.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "app_stats_types.h" +#include "db_init.h" + +#define EMPTY_CHECKER_QID 999 + +ctx::app_db_initializer::app_db_initializer() +{ + create_table(); + check_app_list(); +} + +ctx::app_db_initializer::~app_db_initializer() +{ +} + +void ctx::app_db_initializer::create_table() +{ + static bool done = false; + IF_FAIL_VOID(!done); + + db_manager::create_table(0, APP_TABLE_USAGE_LOG, APP_TABLE_USAGE_LOG_COLUMNS, NULL, NULL); + db_manager::create_table(0, APP_TABLE_REMOVABLE_APP, APP_TABLE_REMOVABLE_APP_COLUMNS, NULL, NULL); + db_manager::execute(0, APP_TEMP_USAGE_FREQ_SQL, NULL); + + done = true; +} + +void ctx::app_db_initializer::check_app_list() +{ + db_manager::execute(EMPTY_CHECKER_QID, "SELECT * FROM " APP_TABLE_REMOVABLE_APP " LIMIT 1", this); +} + +void ctx::app_db_initializer::duplicate_app_list() +{ + int err; + package_manager_filter_h filter; + + err = package_manager_filter_create(&filter); + IF_FAIL_VOID_TAG(err == PACKAGE_MANAGER_ERROR_NONE, _E, "package_manager_filter_create() failed"); + + err = package_manager_filter_add_bool(filter, PACKAGE_MANAGER_PKGINFO_PROP_REMOVABLE, true); + IF_FAIL_CATCH_TAG(err == PACKAGE_MANAGER_ERROR_NONE, _E, "package_manager_filter_add_bool() failed"); + + err = package_manager_filter_foreach_package_info(filter, package_info_cb, this); + IF_FAIL_CATCH_TAG(err == PACKAGE_MANAGER_ERROR_NONE, _E, "package_manager_filter_foreach_package_info() failed"); + +CATCH: + if (filter) + package_manager_filter_destroy(filter); +} + +bool ctx::app_db_initializer::package_info_cb(package_info_h package_info, void *user_data) +{ + int err = package_info_foreach_app_from_package(package_info, PACKAGE_INFO_UIAPP, app_info_cb, user_data); + IF_FAIL_RETURN_TAG(err == PACKAGE_MANAGER_ERROR_NONE, false, _E, "package_info_foreach_app_from_package() failed"); + return true; +} + +bool ctx::app_db_initializer::app_info_cb(package_info_app_component_type_e comp_type, const char *app_id, void *user_data) +{ + json data; + data.set(NULL, STATS_APP_ID, app_id); + return db_manager::insert(0, APP_TABLE_REMOVABLE_APP, data, NULL); +} + +void ctx::app_db_initializer::on_creation_result_received(unsigned int query_id, int error) +{ +} + +void ctx::app_db_initializer::on_insertion_result_received(unsigned int query_id, int error, int64_t row_id) +{ +} + +void ctx::app_db_initializer::on_query_result_received(unsigned int query_id, int error, std::vector& records) +{ + if (query_id != EMPTY_CHECKER_QID) { + _E("Unknown Query ID: %d", query_id); + delete this; + return; + } + + if (records.empty()) + duplicate_app_list(); + + delete this; +} diff --git a/src/statistics/app/db_init.h b/src/statistics/app/db_init.h new file mode 100644 index 0000000..b042675 --- /dev/null +++ b/src/statistics/app/db_init.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_APP_DB_INITIALIZER_H__ +#define __CONTEXT_APP_DB_INITIALIZER_H__ + +#include +#include + +namespace ctx { + + class app_db_initializer : public db_listener_iface { + private: + void create_table(); + void check_app_list(); + void duplicate_app_list(); + + void on_creation_result_received(unsigned int query_id, int error); + void on_insertion_result_received(unsigned int query_id, int error, int64_t row_id); + void on_query_result_received(unsigned int query_id, int error, std::vector& records); + + static bool package_info_cb(package_info_h package_info, void *user_data); + static bool app_info_cb(package_info_app_component_type_e comp_type, const char *app_id, void *user_data); + + public: + app_db_initializer(); + ~app_db_initializer(); + }; + +} /* namespace ctx */ + +#endif diff --git a/src/statistics/app/install_monitor.cpp b/src/statistics/app/install_monitor.cpp new file mode 100644 index 0000000..7cec212 --- /dev/null +++ b/src/statistics/app/install_monitor.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "app_stats_types.h" +#include "install_monitor.h" + +static package_manager_event_type_e last_event_type; + +ctx::app_install_monitor::app_install_monitor() + : pkgmgr_h(NULL) +{ + start_monitoring(); +} + +ctx::app_install_monitor::~app_install_monitor() +{ + stop_monitoring(); +} + +bool ctx::app_install_monitor::start_monitoring() +{ + int err = package_manager_create(&pkgmgr_h); + IF_FAIL_RETURN_TAG(err == PACKAGE_MANAGER_ERROR_NONE, false, _E, "package_manager_create() failed"); + + err = package_manager_set_event_cb(pkgmgr_h, package_event_cb, this); + IF_FAIL_RETURN_TAG(err == PACKAGE_MANAGER_ERROR_NONE, false, _E, "package_manager_set_event_cb() failed"); + + return true; +} + +void ctx::app_install_monitor::stop_monitoring() +{ + if(pkgmgr_h) { + package_manager_unset_event_cb(pkgmgr_h); + package_manager_destroy(pkgmgr_h); + pkgmgr_h = NULL; + } +} + +void ctx::app_install_monitor::package_event_cb(const char *type, const char *package, package_manager_event_type_e event_type, package_manager_event_state_e event_state, int progress, package_manager_error_e error, void *user_data) +{ + IF_FAIL_VOID_TAG(error == PACKAGE_MANAGER_ERROR_NONE, _E, "package_manager error: %d", error); + + if (!(event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL && event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) && + !(event_type == PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL && event_state == PACKAGE_MANAGER_EVENT_STATE_STARTED)) { + _D("Skipping event type-%d / state-%d", event_type, event_state); + return; + } + + package_info_h pkg_info; + int err = package_manager_get_package_info(package, &pkg_info); + IF_FAIL_VOID_TAG(err == PACKAGE_MANAGER_ERROR_NONE, _E, "package_manager_get_package_info() failed"); + + last_event_type = event_type; + + err = package_info_foreach_app_from_package(pkg_info, PACKAGE_INFO_UIAPP, app_info_cb, user_data); + if (err != PACKAGE_MANAGER_ERROR_NONE) + _E("package_info_foreach_app_from_package() failed"); + + package_info_destroy(pkg_info); +} + +bool ctx::app_install_monitor::app_info_cb(package_info_app_component_type_e comp_type, const char *app_id, void *user_data) +{ + if (last_event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL) { + json data; + data.set(NULL, STATS_APP_ID, app_id); + db_manager::insert(0, APP_TABLE_REMOVABLE_APP, data, NULL); + } else if (last_event_type == PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL) { + db_manager::execute(0, create_deletion_query(APP_TABLE_REMOVABLE_APP, app_id).c_str(), NULL); + db_manager::execute(0, create_deletion_query(APP_TABLE_USAGE_LOG, app_id).c_str(), NULL); + } + + return true; +} + +std::string ctx::app_install_monitor::create_deletion_query(const char* table_name, const char* app_id) +{ + std::stringstream query; + query << "DELETE FROM " << table_name; + query << " WHERE " STATS_APP_ID " = '" << app_id << "'"; + return query.str(); +} diff --git a/src/statistics/app/install_monitor.h b/src/statistics/app/install_monitor.h new file mode 100644 index 0000000..0bfee65 --- /dev/null +++ b/src/statistics/app/install_monitor.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_APP_INSTALL_MONITOR_H__ +#define __CONTEXT_APP_INSTALL_MONITOR_H__ + +#include +#include + +namespace ctx { + + class app_install_monitor : public db_listener_iface { + private: + package_manager_h pkgmgr_h; + + bool start_monitoring(); + void stop_monitoring(); + + void on_creation_result_received(unsigned int query_id, int error) {} + void on_insertion_result_received(unsigned int query_id, int error, int64_t row_id) {} + void on_query_result_received(unsigned int query_id, int error, std::vector& records) {} + + static std::string create_deletion_query(const char* table_name, const char* app_id); + static void package_event_cb(const char *type, const char *package, package_manager_event_type_e event_type, package_manager_event_state_e event_state, int progress, package_manager_error_e error, void *user_data); + static bool app_info_cb(package_info_app_component_type_e comp_type, const char *app_id, void *user_data); + + public: + app_install_monitor(); + ~app_install_monitor(); + }; + +} /* namespace ctx */ + +#endif diff --git a/src/statistics/media/db_handle.cpp b/src/statistics/media/db_handle.cpp new file mode 100644 index 0000000..50d0dec --- /dev/null +++ b/src/statistics/media/db_handle.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "media_stats_types.h" +#include "db_handle.h" + +ctx::media_db_handle::media_db_handle() +{ +} + +ctx::media_db_handle::~media_db_handle() +{ +} + +int ctx::media_db_handle::read(const char* subject, ctx::json filter) +{ + //TODO: filter validation (in the API side?) + std::string query; + + if (STR_EQ(subject, MEDIA_SUBJ_PEAK_TIME_FOR_MUSIC)) { + query = create_sql_peak_time(MEDIA_TYPE_MUSIC, filter); + + } else if (STR_EQ(subject, MEDIA_SUBJ_PEAK_TIME_FOR_VIDEO)) { + query = create_sql_peak_time(MEDIA_TYPE_VIDEO, filter); + + } else if (STR_EQ(subject, MEDIA_SUBJ_COMMON_SETTING_FOR_MUSIC)) { + query = create_sql_common_setting(MEDIA_TYPE_MUSIC, filter); + + } else if (STR_EQ(subject, MEDIA_SUBJ_COMMON_SETTING_FOR_VIDEO)) { + query = create_sql_common_setting(MEDIA_TYPE_VIDEO, filter); + + } else if (STR_EQ(subject, MEDIA_SUBJ_MUSIC_FREQUENCY)) { + is_trigger_item = true; + query = create_sql_frequency(MEDIA_TYPE_MUSIC, filter); + + } else if (STR_EQ(subject, MEDIA_SUBJ_VIDEO_FREQUENCY)) { + is_trigger_item = true; + query = create_sql_frequency(MEDIA_TYPE_VIDEO, filter); + } + + IF_FAIL_RETURN(!query.empty(), ERR_OPERATION_FAILED); + + bool ret = execute_query(subject, filter, query.c_str()); + IF_FAIL_RETURN(ret, ERR_OPERATION_FAILED); + + return ERR_NONE; +} + +std::string ctx::media_db_handle::create_where_clause(int media_type, ctx::json filter) +{ + std::stringstream where_clause; + + where_clause << CX_MEDIA_TYPE " = " << media_type << " AND "; + where_clause << stats_db_handle_base::create_where_clause(filter); + + return where_clause.str(); +} + +std::string ctx::media_db_handle::create_sql_peak_time(int media_type, ctx::json filter) +{ + std::string where = create_where_clause(media_type, filter); + return stats_db_handle_base::create_sql_peak_time(filter, MEDIA_TABLE_NAME, where); +} + +std::string ctx::media_db_handle::create_sql_common_setting(int media_type, ctx::json filter) +{ + std::string where = create_where_clause(media_type, filter); + return stats_db_handle_base::create_sql_common_setting(filter, MEDIA_TABLE_NAME, where); +} + +std::string ctx::media_db_handle::create_sql_frequency(int media_type, ctx::json filter) +{ + ctx::json filter_cleaned; + std::string week_str; + std::string time_of_day; + + if (filter.get(NULL, STATS_DAY_OF_WEEK, &week_str)) + filter_cleaned.set(NULL, STATS_DAY_OF_WEEK, week_str); + + if (filter.get(NULL, STATS_TIME_OF_DAY, &time_of_day)) + filter_cleaned.set(NULL, STATS_TIME_OF_DAY, time_of_day); + + std::string where_clause = create_where_clause(media_type, filter_cleaned); + + std::stringstream query; + query << + "SELECT IFNULL(COUNT(*),0) AS " STATS_TOTAL_COUNT \ + " FROM " MEDIA_TABLE_NAME \ + " WHERE " << where_clause; + + return query.str(); +} + +void ctx::media_db_handle::reply_trigger_item(int error, ctx::json &json_result) +{ + IF_FAIL_VOID_TAG(STR_EQ(req_subject.c_str(), MEDIA_SUBJ_MUSIC_FREQUENCY) || + STR_EQ(req_subject.c_str(), MEDIA_SUBJ_VIDEO_FREQUENCY), _E, "Invalid subject"); + + ctx::json results; + int val; + + json_result.get(NULL, STATS_TOTAL_COUNT, &val); + results.set(NULL, STATS_TOTAL_COUNT, val); + + context_manager::reply_to_read(req_subject.c_str(), req_filter, error, results); +} diff --git a/src/statistics/media/db_handle.h b/src/statistics/media/db_handle.h new file mode 100644 index 0000000..a42c247 --- /dev/null +++ b/src/statistics/media/db_handle.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_MEDIA_DB_HANDLE_H__ +#define __CONTEXT_MEDIA_DB_HANDLE_H__ + +#include +#include +#include + +namespace ctx { + class media_db_handle : public stats_db_handle_base { + public: + media_db_handle(); + ~media_db_handle(); + + int read(const char* subject, ctx::json filter); + + private: + std::string create_where_clause(int media_type, ctx::json filter); + std::string create_sql_peak_time(int media_type, ctx::json filter); + std::string create_sql_common_setting(int media_type, ctx::json filter); + std::string create_sql_frequency(int media_type, ctx::json filter); + void reply_trigger_item(int error, ctx::json &json_result); + }; +} + +#endif /* __CONTEXT_MEDIA_DB_HANDLE_H__ */ diff --git a/src/statistics/media/media_content_monitor.cpp b/src/statistics/media/media_content_monitor.cpp new file mode 100644 index 0000000..4fbeed7 --- /dev/null +++ b/src/statistics/media/media_content_monitor.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "media_stats_types.h" +#include "db_handle.h" +#include "media_content_monitor.h" + +#define PLAYCOUNT_RETENTION_PERIOD 259200 /* 1 month in secs */ +#define ONE_DAY_IN_SEC 86400 + +ctx::media_content_monitor::media_content_monitor() + : started(false) + , last_cleanup_time(0) +{ + db_manager::create_table(0, MEDIA_TABLE_NAME, MEDIA_TABLE_COLUMNS, NULL, NULL); + db_manager::execute(0, MEDIA_PLAYCOUNT_TABLE_SCHEMA, NULL); + + started = start_monitoring(); +} + +ctx::media_content_monitor::~media_content_monitor() +{ + if (started) + stop_monitoring(); +} + +bool ctx::media_content_monitor::start_monitoring() +{ + int err; + err = media_content_connect(); + IF_FAIL_RETURN_TAG(err == MEDIA_CONTENT_ERROR_NONE, false, _E, "media_content_connect() failed"); + + err = media_content_set_db_updated_cb(on_media_content_db_updated, this); + if (err != MEDIA_CONTENT_ERROR_NONE) { + media_content_disconnect(); + _E("media_content_set_db_updated_cb() failed"); + return false; + } + + return true; +} + +void ctx::media_content_monitor::stop_monitoring() +{ + media_content_unset_db_updated_cb(); + media_content_disconnect(); +} + +void ctx::media_content_monitor::on_media_content_db_updated( + media_content_error_e error, int pid, + media_content_db_update_item_type_e update_item, + media_content_db_update_type_e update_type, + media_content_type_e media_type, + char *uuid, char *path, char *mime_type, void *user_data) +{ + IF_FAIL_VOID(error == MEDIA_CONTENT_ERROR_NONE && uuid != NULL); + IF_FAIL_VOID(update_item == MEDIA_ITEM_FILE && update_type == MEDIA_CONTENT_UPDATE); + IF_FAIL_VOID(media_type == MEDIA_CONTENT_TYPE_MUSIC || media_type == MEDIA_CONTENT_TYPE_VIDEO); + + media_info_h media = NULL; + media_info_get_media_from_db(uuid, &media); + IF_FAIL_VOID_TAG(media, _E, "media_info_get_media_from_db() failed"); + + int cnt = -1; + media_info_get_played_count(media, &cnt); + media_info_destroy(media); + IF_FAIL_VOID_TAG(cnt >= 0, _E, "Invalid play count"); + + media_content_monitor *instance = static_cast(user_data); + instance->update_play_count(uuid, + (media_type == MEDIA_CONTENT_TYPE_MUSIC) ? MEDIA_TYPE_MUSIC : MEDIA_TYPE_VIDEO, + cnt); +} + +void ctx::media_content_monitor::append_cleanup_query(std::stringstream &query) +{ + int timestamp = static_cast(time(NULL)); + IF_FAIL_VOID(timestamp - last_cleanup_time >= ONE_DAY_IN_SEC); + + last_cleanup_time = timestamp; + + query << + "DELETE FROM Log_MediaPlayCount WHERE UTC < strftime('%s', 'now') - " << PLAYCOUNT_RETENTION_PERIOD << ";" \ + "DELETE FROM " MEDIA_TABLE_NAME " WHERE UTC < strftime('%s', 'now') - " << LOG_RETENTION_PERIOD << ";"; +} + +void ctx::media_content_monitor::update_play_count(const char *uuid, int type, int count) +{ + std::stringstream query; + query << + /* Inserting the media record to the play count table, if not exist */ + "INSERT OR IGNORE INTO Log_MediaPlayCount" \ + " (UUID, MediaType) VALUES ('" << uuid << "'," << type <<");" \ + /* Updating the play count and getting the diff from the previous count */ + "UPDATE Log_MediaPlayCount SET Diff = " << count << " - Count," \ + " Count = " << count << ", UTC = strftime('%s', 'now')" \ + " WHERE UUID = '" << uuid << "';"; + append_cleanup_query(query); + query << + /* Checking whether the play count changes */ + "SELECT MediaType FROM Log_MediaPlayCount" \ + " WHERE UUID = '" << uuid << "' AND Diff > 0;"; + + db_manager::execute(0, query.str().c_str(), this); +} + +void ctx::media_content_monitor::on_query_result_received(unsigned int query_id, int error, std::vector& records) +{ + IF_FAIL_VOID(!records.empty()); + + int media_type = 0; + records[0].get(NULL, CX_MEDIA_TYPE, &media_type); + + insert_log(media_type); +} + +void ctx::media_content_monitor::insert_log(int media_type) +{ + int system_volume = -1, media_volume = -1, audiojack = -1; + + json data; + data.set(NULL, CX_MEDIA_TYPE, media_type); + + if (ctx::system_info::get_audio_jack_state(&audiojack)) + data.set(NULL, STATS_AUDIO_JACK, audiojack); + + if (ctx::system_info::get_volume(&system_volume, &media_volume)) { + data.set(NULL, STATS_SYSTEM_VOLUME, system_volume); + data.set(NULL, STATS_MEDIA_VOLUME, media_volume); + } + + db_manager::insert(0, MEDIA_TABLE_NAME, data, NULL); +} diff --git a/src/statistics/media/media_content_monitor.h b/src/statistics/media/media_content_monitor.h new file mode 100644 index 0000000..d51d54c --- /dev/null +++ b/src/statistics/media/media_content_monitor.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_MEDIA_CONTENT_MONITOR_H__ +#define __CONTEXT_MEDIA_CONTENT_MONITOR_H__ + +#include +#include +#include + +namespace ctx { + + class media_content_monitor : public db_listener_iface { + private: + bool started; + int last_cleanup_time; + + bool start_monitoring(); + void stop_monitoring(); + + void append_cleanup_query(std::stringstream &query); + void update_play_count(const char *uuid, int type, int count); + void insert_log(int media_type); + + void on_creation_result_received(unsigned int query_id, int error) {} + void on_insertion_result_received(unsigned int query_id, int error, int64_t row_id) {} + void on_query_result_received(unsigned int query_id, int error, std::vector& records); + + static void on_media_content_db_updated(media_content_error_e error, int pid, + media_content_db_update_item_type_e update_item, + media_content_db_update_type_e update_type, + media_content_type_e media_type, + char *uuid, char *path, char *mime_type, void *user_data); + + public: + media_content_monitor(); + ~media_content_monitor(); + }; + +} /* namespace ctx */ + +#endif diff --git a/src/statistics/media/media_stats_provider.cpp b/src/statistics/media/media_stats_provider.cpp new file mode 100644 index 0000000..d6ad2b7 --- /dev/null +++ b/src/statistics/media/media_stats_provider.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "media_stats_provider.h" +#include "db_handle.h" +#include "media_content_monitor.h" + +static ctx::media_content_monitor *content_mon = NULL; + +ctx::media_statistics_provider *ctx::media_statistics_provider::__instance = NULL; + +ctx::media_statistics_provider::media_statistics_provider() +{ +} + +ctx::media_statistics_provider::~media_statistics_provider() +{ + delete content_mon; + content_mon = NULL; +} + +ctx::context_provider_iface *ctx::media_statistics_provider::create(void *data) +{ + IF_FAIL_RETURN(!__instance, __instance); + + __instance = new(std::nothrow) media_statistics_provider(); + IF_FAIL_RETURN_TAG(__instance, NULL, _E, "Memory allocation failed"); + + _I(BLUE("Created")); + + if (!__instance->init()) { + destroy(data); + return NULL; + } + + return __instance; +} + +void ctx::media_statistics_provider::destroy(void *data) +{ + IF_FAIL_VOID(__instance); + delete __instance; + __instance = NULL; + _I(BLUE("Destroyed")); +} + +bool ctx::media_statistics_provider::is_supported(const char* subject) +{ + return true; +} + +void ctx::media_statistics_provider::submit_trigger_item() +{ + context_manager::register_trigger_item(MEDIA_SUBJ_MUSIC_FREQUENCY, OPS_READ, + "{" TRIG_DEF_TOTAL_COUNT "}", + "{" TRIG_DEF_TIME_OF_DAY "," TRIG_DEF_DAY_OF_WEEK "}"); + + context_manager::register_trigger_item(MEDIA_SUBJ_VIDEO_FREQUENCY, OPS_READ, + "{" TRIG_DEF_TOTAL_COUNT "}", + "{" TRIG_DEF_TIME_OF_DAY "," TRIG_DEF_DAY_OF_WEEK "}"); +} + +bool ctx::media_statistics_provider::init() +{ + content_mon = new(std::nothrow) ctx::media_content_monitor(); + IF_FAIL_RETURN_TAG(content_mon, false, _E, "Memory allocation failed"); + return true; +} + +int ctx::media_statistics_provider::subscribe(const char* subject, ctx::json option, ctx::json* request_result) +{ + return ERR_NOT_SUPPORTED; +} + +int ctx::media_statistics_provider::unsubscribe(const char* subject, ctx::json option) +{ + return ERR_NOT_SUPPORTED; +} + +int ctx::media_statistics_provider::read(const char* subject, ctx::json option, ctx::json* request_result) +{ + media_db_handle *handle = new(std::nothrow) media_db_handle(); + IF_FAIL_RETURN_TAG(handle, ERR_OPERATION_FAILED, _E, "Memory allocation failed"); + + int err = handle->read(subject, option); + if (err != ERR_NONE) { + delete handle; + return err; + } + + return ERR_NONE; +} + +int ctx::media_statistics_provider::write(const char* subject, ctx::json data, ctx::json* request_result) +{ + return ERR_NOT_SUPPORTED; +} diff --git a/src/statistics/media/media_stats_provider.h b/src/statistics/media/media_stats_provider.h new file mode 100644 index 0000000..49949c3 --- /dev/null +++ b/src/statistics/media/media_stats_provider.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_MEDIA_STATS_PROVIDER_H__ +#define __CONTEXT_MEDIA_STATS_PROVIDER_H__ + +#include +#include "media_stats_types.h" + +namespace ctx { + + class media_statistics_provider : public context_provider_iface { + public: + static context_provider_iface *create(void *data); + static void destroy(void *data); + static bool is_supported(const char *subject); + static void submit_trigger_item(); + + int subscribe(const char* subject, ctx::json option, ctx::json* request_result); + int unsubscribe(const char* subject, ctx::json option); + int read(const char* subject, ctx::json option, ctx::json* request_result); + int write(const char* subject, ctx::json data, ctx::json* request_result); + + private: + static media_statistics_provider *__instance; + + media_statistics_provider(); + ~media_statistics_provider(); + bool init(); + + }; /* class media_statistics_provider */ + +} /* namespace ctx */ + +#endif /* __CONTEXT_CONTEXT_MEDIA_STATS_PROVIDER_H__ */ diff --git a/src/statistics/media/media_stats_types.h b/src/statistics/media/media_stats_types.h new file mode 100644 index 0000000..79cfe3f --- /dev/null +++ b/src/statistics/media/media_stats_types.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_MEDIA_STATS_TYPES_H__ +#define __CONTEXT_MEDIA_STATS_TYPES_H__ + +#include + +#define MEDIA_HISTORY_PRIV "mediahistory.read" +#define MEDIA_SUBJ_PEAK_TIME_FOR_MUSIC "stats/music/peak_time" +#define MEDIA_SUBJ_PEAK_TIME_FOR_VIDEO "stats/video/peak_time" +#define MEDIA_SUBJ_COMMON_SETTING_FOR_MUSIC "stats/music/setting" +#define MEDIA_SUBJ_COMMON_SETTING_FOR_VIDEO "stats/video/setting" +#define MEDIA_SUBJ_MUSIC_FREQUENCY "stats/music/frequency" +#define MEDIA_SUBJ_VIDEO_FREQUENCY "stats/video/frequency" + +#define MEDIA_TABLE_NAME "Log_MediaPlayback" +#define MEDIA_TABLE_COLUMNS \ + "MediaType INTEGER NOT NULL, " \ + "SystemVolume INTEGER, MediaVolume INTEGER, AudioJack INTEGER, " \ + "UTC TIMESTAMP DEFAULT (strftime('%s', 'now')), " \ + "LocalTime TIMESTAMP DEFAULT (strftime('%s', 'now', 'localtime'))" + +#define MEDIA_PLAYCOUNT_TABLE_SCHEMA \ + "CREATE TABLE IF NOT EXISTS Log_MediaPlayCount" \ + " (UUID TEXT NOT NULL PRIMARY KEY, MediaType INTEGER NOT NULL," \ + " Count INTEGER DEFAULT 0, Diff INTEGER DEFAULT 0, " \ + " UTC TIMESTAMP DEFAULT (strftime('%s', 'now')))" + +#define CX_MEDIA_TYPE "MediaType" + +enum media_type_e { + MEDIA_TYPE_MUSIC = 1, + MEDIA_TYPE_VIDEO, +}; + +#endif diff --git a/src/statistics/prediction/assoc_rule.cpp b/src/statistics/prediction/assoc_rule.cpp new file mode 100644 index 0000000..05be246 --- /dev/null +++ b/src/statistics/prediction/assoc_rule.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assoc_rule.h" + +std::ostream& ctx::operator<<(std::ostream &out, const ctx::AssocRule &rule) +{ + return out << rule.antecedent << " => " << rule.consequent + << "; support:" << rule.support << "; confidence:" << rule.confidence; +} + +bool ctx::operator==(const ctx::AssocRule& left, const ctx::AssocRule& right) +{ + return left.antecedent == right.antecedent && + left.consequent == right.consequent && + left.support == right.support && + left.confidence == right.confidence; +} diff --git a/src/statistics/prediction/assoc_rule.h b/src/statistics/prediction/assoc_rule.h new file mode 100644 index 0000000..252684e --- /dev/null +++ b/src/statistics/prediction/assoc_rule.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_ASSOC_RULE_H_ +#define INCLUDE_ASSOC_RULE_H_ + +#include "item_set.h" +#include + +namespace ctx { + + struct AssocRule { + ItemSet antecedent; + ItemSet consequent; + double support; + double confidence; + + AssocRule(const ItemSet& antecedent_, + const ItemSet& consequent_, + const double& support_, + const double& confidence_) + : antecedent(antecedent_) + , consequent(consequent_) + , support(support_) + , confidence(confidence_) {} + }; + + bool operator==(const AssocRule& left, const AssocRule& right); + + std::ostream& operator<<(std::ostream &out, const AssocRule &rule); + +} /* namespace ctx */ + +#endif /* INCLUDE_ASSOC_RULE_H_ */ diff --git a/src/statistics/prediction/assoc_rule_miner.cpp b/src/statistics/prediction/assoc_rule_miner.cpp new file mode 100644 index 0000000..a639af8 --- /dev/null +++ b/src/statistics/prediction/assoc_rule_miner.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assoc_rule_miner.h" +#include "single_category_item_id_filter.h" +#include "basket_filter.h" +#include "basket_compressor.h" +#include "baskets_agregator.h" +#include "assoc_rule_producer.h" +#include "weight_apriori.h" + +std::list ctx::AssocRuleMiner::mine_from_baskets( + std::list& initBaskets, + ctx::ItemCatalogue& itemCatalogue, + double minSupport, + double minConfidence, + std::string consequentCategory) +{ + SingleCategoryItemIdFilter itemIdFilter(consequentCategory, itemCatalogue); + BasketFilter::filter_in_place(initBaskets,itemIdFilter); + + std::list compressedBaskets = BasketCompressor::compress(initBaskets); + + BasketsAgregator basketsAgregator(compressedBaskets); + basketsAgregator.generate_bitsets(itemCatalogue.maxId()); + auto freqItemSets = WeightApriori::find_frequent_itemid_sets(basketsAgregator, minSupport); + auto rulesOfIds = AssocRuleProducer::generate_rules(freqItemSets, itemIdFilter, minConfidence); + return remove_assoc_rule_ids(rulesOfIds, itemCatalogue); +} + +std::list ctx::AssocRuleMiner::mine_from_events( + const ctx::EventSet& events, + double minSupport, + double minConfidence, + std::string consequentCategory) +{ + ItemCatalogue itemCatalogue; + + BasketProducer basketProducer(itemCatalogue); + for (auto& event : events) { + basketProducer.put_event(event); + } + + std::list initBaskets = basketProducer.make_baskets(); + + return mine_from_baskets(initBaskets, itemCatalogue, minSupport, minConfidence, consequentCategory); +} + +std::list ctx::AssocRuleMiner::remove_assoc_rule_ids( + const std::list& rulesOfIds, + const ctx::ItemCatalogue& itemCatalogue) +{ + std::list result; + for (const AssocRuleOfIds ruleOfIds : rulesOfIds) { + AssocRule rule(remove_assoc_rule_ids(ruleOfIds.antecedent, itemCatalogue), + remove_assoc_rule_ids(ruleOfIds.consequent, itemCatalogue), + ruleOfIds.support, + ruleOfIds.confidence); + result.push_back(rule); + } + return result; +} + +ctx::ItemSet ctx::AssocRuleMiner::remove_assoc_rule_ids(const ctx::ItemIdSet& itemIdSet, const ctx::ItemCatalogue& itemCatalogue) +{ + ItemSet itemSet; + for (int id : itemIdSet) { + itemSet.push_back(itemCatalogue.item_of_id(id)); + } + return itemSet; +} diff --git a/src/statistics/prediction/assoc_rule_miner.h b/src/statistics/prediction/assoc_rule_miner.h new file mode 100644 index 0000000..6d57e3f --- /dev/null +++ b/src/statistics/prediction/assoc_rule_miner.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ASSOC_RULE_MINER_H_ +#define ASSOC_RULE_MINER_H_ + +#include +#include +#include "event_set.h" +#include "assoc_rule.h" +#include "assoc_rule_of_ids.h" +#include "basket_producer.h" +#include "i_item_id_filter.h" + +namespace ctx { + + class AssocRuleMiner { + + public: + static std::list mine_from_events( + const EventSet& events, + double minSupport, + double minConfidence, + std::string consequentCategory); + static std::list mine_from_baskets( + std::list& initBaskets, + ItemCatalogue& itemCatalogue, + double minSupport, + double minConfidence, + std::string consequentCategory); + private: + static std::list remove_assoc_rule_ids(const std::list& rulesOfIds, const ItemCatalogue& itemCatalogue); + static ItemSet remove_assoc_rule_ids(const ItemIdSet& itemIdSet, const ItemCatalogue& itemCatalogue); + + }; + +} /* namespace ctx */ + +#endif /* ASSOC_RULE_MINER_H_ */ diff --git a/src/statistics/prediction/assoc_rule_of_ids.h b/src/statistics/prediction/assoc_rule_of_ids.h new file mode 100644 index 0000000..b7dea9a --- /dev/null +++ b/src/statistics/prediction/assoc_rule_of_ids.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ASSOC_RULE_OF_IDS_H_ +#define ASSOC_RULE_OF_IDS_H_ + +#include "item_id_set.h" + +namespace ctx { + + /* rule of the form antecedent => consequent */ + class AssocRuleOfIds { + + public: + ItemIdSet antecedent; + ItemIdSet consequent; + double support; + double confidence; + }; + + inline bool operator==(const AssocRuleOfIds& left, const AssocRuleOfIds& right) + { + return left.support == right.support + && left.confidence == right.confidence + && left.antecedent == right.antecedent + && left.consequent == right.consequent; + } + +} /* namespace ctx */ + +#endif /* ASSOC_RULE_OF_IDS_H_ */ diff --git a/src/statistics/prediction/assoc_rule_producer.cpp b/src/statistics/prediction/assoc_rule_producer.cpp new file mode 100644 index 0000000..da9f5d2 --- /dev/null +++ b/src/statistics/prediction/assoc_rule_producer.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assoc_rule_producer.h" + +ctx::AssocRuleOfIds ctx::AssocRuleProducer::rule_template(const ctx::ItemIdSet& sourceItemIdSet, + const ctx::IItemIdFilter& itemIdFilter) +{ + AssocRuleOfIds ruleTempl; + for (int itemId : sourceItemIdSet) { + ItemIdSet &destination = itemIdFilter.pass(itemId) + ? ruleTempl.consequent + : ruleTempl.antecedent; + destination.push_back(itemId); + } + return ruleTempl; +} + +std::list ctx::AssocRuleProducer::generate_rules( + const std::list>& freqItemIdSets, + const ctx::IItemIdFilter& itemIdFilter, double minConfidence) +{ + std::list rules; + + for (auto & pair : freqItemIdSets) { + ItemIdSet freqItemIdSet = pair.first; + double support = pair.second; + AssocRuleOfIds rule = AssocRuleProducer::rule_template(freqItemIdSet, itemIdFilter); + if (rule.antecedent.size() > 0 && rule.consequent.size() > 0) { + rule.support = support; + double antecedentSupport = AssocRuleProducer::supportOf(freqItemIdSets, rule.antecedent); + rule.confidence = support / antecedentSupport; + if (rule.confidence >= minConfidence) { + rules.push_back(rule); + } + } + } + return rules; +} + +double ctx::AssocRuleProducer::supportOf( + const std::list> &allFreqItemIdSets, const ctx::ItemIdSet &wanted) +{ + for (auto & pair : allFreqItemIdSets) { + if (pair.first == wanted) { + return pair.second; + } + } + return 0.0; +} diff --git a/src/statistics/prediction/assoc_rule_producer.h b/src/statistics/prediction/assoc_rule_producer.h new file mode 100644 index 0000000..03eaecf --- /dev/null +++ b/src/statistics/prediction/assoc_rule_producer.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ASSOC_RULE_PRODUCER_H_ +#define ASSOC_RULE_PRODUCER_H_ + +#include "assoc_rule_of_ids.h" +#include "basket.h" +#include "i_item_id_filter.h" +#include + +namespace ctx { + + class AssocRuleProducer { + + public: + static std::list generate_rules( + const std::list> &freqItemIdSets, + const IItemIdFilter &itemIdFilter, + double minConfidence); + + static AssocRuleOfIds rule_template(const ItemIdSet &sourceItemIdSet, const IItemIdFilter &antecedentItemIdFilter); + + private: + static double supportOf(const std::list> &allFreqItemIdSets, const ItemIdSet &wanted); + + }; + +} /* namespace ctx */ + +#endif /* ASSOC_RULE_PRODUCER_H_ */ diff --git a/src/statistics/prediction/basket.cpp b/src/statistics/prediction/basket.cpp new file mode 100644 index 0000000..35357ce --- /dev/null +++ b/src/statistics/prediction/basket.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "basket.h" + +void ctx::Basket::compute_bitset(int maxId) +{ + mBitSet.resize(maxId+1, false); + for (int itemId : itemIdSet) { + mBitSet[itemId] = true; + } +} + +bool ctx::Basket::includes(const ctx::ItemIdSet& potentialSubset) +{ + for (int itemId : potentialSubset) { + if (!mBitSet[itemId]) { + return false; + } + } + return true; +} diff --git a/src/statistics/prediction/basket.h b/src/statistics/prediction/basket.h new file mode 100644 index 0000000..2b40eb6 --- /dev/null +++ b/src/statistics/prediction/basket.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_BASKET_H_ +#define INCLUDE_BASKET_H_ + +#include "item_id_set.h" +#include + +namespace ctx { + + class Basket { + + public: + ItemIdSet itemIdSet; + int weight; + + Basket(const ItemIdSet& itemIdSet_, const int& weight_) : itemIdSet(itemIdSet_), weight(weight_) {}; + void compute_bitset(int maxId); + bool includes(const ItemIdSet& potentialSubset); // compute_bitset() should be invoked first + + private: + std::vector mBitSet; + + }; + + // TODO If there is no "inline" below the project does not compile. + inline bool operator==(const Basket& left, const Basket& right) + { + return left.weight == right.weight && left.itemIdSet == right.itemIdSet; + } + +} /* namespace ctx */ + +#endif /* INCLUDE_BASKET_H_ */ diff --git a/src/statistics/prediction/basket_compressor.cpp b/src/statistics/prediction/basket_compressor.cpp new file mode 100644 index 0000000..f46c40d --- /dev/null +++ b/src/statistics/prediction/basket_compressor.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "basket_compressor.h" +#include +#include + +std::string ctx::BasketCompressor::itemset_string(const ctx::ItemIdSet& itemIdSet) +{ + std::stringstream ss; + for (int itemId : itemIdSet) { + ss << itemId << ','; + } + return ss.str(); +} + +std::list ctx::BasketCompressor::compress(const std::list& inputBaskets) +{ + std::map basketsMap; + // TODO: maybe it is worth to resign from string keys and use std::map instead. + + for (const Basket& basket : inputBaskets) { + std::string itemSetStr = itemset_string(basket.itemIdSet); + + auto findResult = basketsMap.find(itemSetStr); + if (findResult == basketsMap.end()) { + basketsMap.insert(std::pair(itemSetStr, basket)); + } else { + Basket& compressedBasket = findResult->second; + compressedBasket.weight += basket.weight; + } + } + + std::list compressedBaskets; + for (auto pair : basketsMap) { + compressedBaskets.push_back(pair.second); + } + return compressedBaskets; +} diff --git a/src/statistics/prediction/basket_compressor.h b/src/statistics/prediction/basket_compressor.h new file mode 100644 index 0000000..a0f5a95 --- /dev/null +++ b/src/statistics/prediction/basket_compressor.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASKET_COMPRESSOR_H_ +#define BASKET_COMPRESSOR_H_ + +#include +#include +#include "basket.h" + +namespace ctx { + + class BasketCompressor { + + public: + static std::list compress(const std::list &inputBaskets); + + private: + static std::string itemset_string(const ItemIdSet &itemIdSet); + + }; + +} /* namespace ctx */ + +#endif /* BASKET_COMPRESSOR_H_ */ diff --git a/src/statistics/prediction/basket_filter.cpp b/src/statistics/prediction/basket_filter.cpp new file mode 100644 index 0000000..da03b6c --- /dev/null +++ b/src/statistics/prediction/basket_filter.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "basket_filter.h" + +void ctx::BasketFilter::filter_in_place(std::list& baskets, const ctx::IItemIdFilter& itemIdFilter) +{ + baskets.remove_if([&itemIdFilter] (Basket &basket) -> bool { return !BasketPass(basket, itemIdFilter); }); +} + +bool ctx::BasketFilter::BasketPass(const ctx::Basket& basket, const ctx::IItemIdFilter& itemIdFilter) +{ + for (int itemId : basket.itemIdSet) { + if (itemIdFilter.pass(itemId)) { + return true; + } + } + return false; +} diff --git a/src/statistics/prediction/basket_filter.h b/src/statistics/prediction/basket_filter.h new file mode 100644 index 0000000..18a03fd --- /dev/null +++ b/src/statistics/prediction/basket_filter.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASKET_FILTER_H_ +#define BASKET_FILTER_H_ + +#include "basket.h" +#include "i_item_id_filter.h" +#include + +namespace ctx { + + class BasketFilter { + + public: + static void filter_in_place(std::list &inputBaskets, const IItemIdFilter &itemIdFilter); + + private: + static bool BasketPass(const Basket &basket, const IItemIdFilter &itemIdFilter); + + }; + +} /* namespace ctx */ + +#endif /* BASKET_FILTER_H_ */ diff --git a/src/statistics/prediction/basket_producer.cpp b/src/statistics/prediction/basket_producer.cpp new file mode 100644 index 0000000..99a3af9 --- /dev/null +++ b/src/statistics/prediction/basket_producer.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "basket_producer.h" +#include + +void ctx::BasketProducer::put_event(const ctx::Event& event) +{ + int iid = mItemCatalogue.id_of(event.item); + put_change(event.interval.start, iid); // positive value indicates start + put_change(event.interval.end, -iid); // negative value indicates end +} + +std::list ctx::BasketProducer::make_baskets() +{ + std::list baskets; + + time_t intervalStart; + std::set currentItemIds; + + bool first = true; + for (auto changePair : mChanges) { + if (first) { + first = false; + } else { + time_t intervalEnd = changePair.first; + int weight = intervalEnd - intervalStart; + ItemIdSet itemIdSet; + for (int itemId : currentItemIds) { + itemIdSet.push_back(itemId); + } + baskets.push_back(Basket(itemIdSet, weight)); + } + + for (int itemId : changePair.second) { + if (itemId > 0) { // item with itemId starts now + currentItemIds.insert(itemId); + } else { // item with -itemId ends now + currentItemIds.erase(-itemId); + } + } + + intervalStart = changePair.first; + } + + return baskets; +} + +void ctx::BasketProducer::put_change(time_t time, int value) +{ + if (mChanges.find(time) == mChanges.end()) { + mChanges[time] = std::list(); + } + mChanges[time].push_back(value); +} diff --git a/src/statistics/prediction/basket_producer.h b/src/statistics/prediction/basket_producer.h new file mode 100644 index 0000000..c265d94 --- /dev/null +++ b/src/statistics/prediction/basket_producer.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_BASKET_PRODUCER_H_ +#define INCLUDE_BASKET_PRODUCER_H_ + +#include "event.h" +#include "basket.h" +#include "item_catalogue.h" +#include + +namespace ctx { + + class BasketProducer { + + public: + BasketProducer(ItemCatalogue& itemCatalogue) : mItemCatalogue(itemCatalogue) {}; + void put_event(const Event& e); + std::list make_baskets(); + + private: + void put_change(time_t time, int value); + + ItemCatalogue& mItemCatalogue; + + /* + * Changes in timestamps. + * If an item starts than its id is stored. + * If an item ends than its negated id is stored. + */ + std::map> mChanges; + + }; + +} /* namespace ctx */ + +#endif /* INCLUDE_BASKET_PRODUCER_H_ */ diff --git a/src/statistics/prediction/baskets_agregator.cpp b/src/statistics/prediction/baskets_agregator.cpp new file mode 100644 index 0000000..7a57e9b --- /dev/null +++ b/src/statistics/prediction/baskets_agregator.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "baskets_agregator.h" + +ctx::BasketsAgregator::BasketsAgregator(std::list& baskets) : mBaskets(baskets) +{ +} + +ctx::ItemIdSet ctx::BasketsAgregator::unique_item_ids() +{ + ItemIdSet allItemIds; + for (const Basket& basket : mBaskets) { + for (int itemId : basket.itemIdSet) { + allItemIds.push_back(itemId); + } + } + allItemIds.sort(); + allItemIds.unique(); + return allItemIds; +} + +void ctx::BasketsAgregator::generate_bitsets(int maxId) +{ + for (Basket& basket : mBaskets) { + basket.compute_bitset(maxId); + } +} + +double ctx::BasketsAgregator::supportOf(const ctx::ItemIdSet& itemIdSet) +{ + int matchedCount = 0; + int unmatchedCount = 0; + for (Basket& basket : mBaskets) { + if (basket.includes(itemIdSet)) { + matchedCount += basket.weight; + } else { + unmatchedCount += basket.weight; + } + } + return (double) matchedCount / (double) (matchedCount + unmatchedCount); +} diff --git a/src/statistics/prediction/baskets_agregator.h b/src/statistics/prediction/baskets_agregator.h new file mode 100644 index 0000000..e3093fe --- /dev/null +++ b/src/statistics/prediction/baskets_agregator.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_BASKETS_AGREGATOR_H_ +#define INCLUDE_BASKETS_AGREGATOR_H_ + +#include +#include +#include "basket.h" + +namespace ctx { + + class BasketsAgregator { + + public: + BasketsAgregator(std::list& baskets); + void generate_bitsets(int maxId); + ItemIdSet unique_item_ids(); + double supportOf(const ItemIdSet &itemIdSet); + + private: + std::list& mBaskets; + + }; + +} /* namespace ctx */ + +#endif /* INCLUDE_BASKETS_AGREGATOR_H_ */ diff --git a/src/statistics/prediction/event.cpp b/src/statistics/prediction/event.cpp new file mode 100644 index 0000000..817e108 --- /dev/null +++ b/src/statistics/prediction/event.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "event.h" + +bool ctx::operator==(const ctx::Event& left, const ctx::Event& right) +{ + return left.item == right.item && left.interval == right.interval; +} + +bool ctx::operator!=(const ctx::Event& left, const ctx::Event& right) +{ + return !(left == right); +} diff --git a/src/statistics/prediction/event.h b/src/statistics/prediction/event.h new file mode 100644 index 0000000..029296f --- /dev/null +++ b/src/statistics/prediction/event.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_EVENT_H_ +#define INCLUDE_EVENT_H_ + +#include "item.h" +#include "interval.h" + +namespace ctx { + + struct Event { + Item item; + Interval interval; + + /* long time event */ + Event(const Item& item_, const Interval& interval_) : item(item_), interval(interval_) {} + + /* instant event */ + Event(const Item& item_, const time_t& start_time_) : item(item_), interval(start_time_, start_time_ + 1) {} + }; + + bool operator==(const Event& left, const Event& right); + bool operator!=(const Event& left, const Event& right); + +} /* namespace ctx */ + +#endif /* INCLUDE_EVENT_H_ */ diff --git a/src/statistics/prediction/event_set.h b/src/statistics/prediction/event_set.h new file mode 100644 index 0000000..dda0bc2 --- /dev/null +++ b/src/statistics/prediction/event_set.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_EVENT_SET_H_ +#define INCLUDE_EVENT_SET_H_ + +#include "event.h" + +namespace ctx { + + typedef std::list EventSet; + +} /* namespace ctx */ + +#endif /* INCLUDE_EVENT_SET_H_ */ diff --git a/src/statistics/prediction/i_item_id_filter.h b/src/statistics/prediction/i_item_id_filter.h new file mode 100644 index 0000000..dd4c386 --- /dev/null +++ b/src/statistics/prediction/i_item_id_filter.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef I_ITEM_ID_FILTER_H_ +#define I_ITEM_ID_FILTER_H_ + +namespace ctx { + + class IItemIdFilter { + + public: + virtual ~IItemIdFilter() {} + virtual bool pass(int itemId) const = 0; + + }; + +} /* namespace ctx */ + +#endif /* I_ITEM_ID_FILTER_H_ */ diff --git a/src/statistics/prediction/interval.cpp b/src/statistics/prediction/interval.cpp new file mode 100644 index 0000000..b6dc8f9 --- /dev/null +++ b/src/statistics/prediction/interval.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "interval.h" + +bool ctx::operator==(const Interval& left, const Interval& right) +{ + return left.start == right.start && left.end == right.end; +} + +bool ctx::operator!=(const Interval& left, const Interval& right) +{ + return !(left == right); +} diff --git a/src/statistics/prediction/interval.h b/src/statistics/prediction/interval.h new file mode 100644 index 0000000..2153aa0 --- /dev/null +++ b/src/statistics/prediction/interval.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_INTERVAL_H_ +#define INCLUDE_INTERVAL_H_ + +#include + +namespace ctx { + + struct Interval { + time_t start; + time_t end; + + Interval(time_t start_, time_t end_) : start(start_), end(end_) {} + }; + + bool operator==(const Interval& left, const Interval& right); + bool operator!=(const Interval& left, const Interval& right); + +} /* namespace ctx */ + +#endif /* INCLUDE_INTERVAL_H_ */ diff --git a/src/statistics/prediction/item.cpp b/src/statistics/prediction/item.cpp new file mode 100644 index 0000000..9a80ca9 --- /dev/null +++ b/src/statistics/prediction/item.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "item.h" + +ctx::Item::Item(const std::string &s) +{ + size_t leftBracket = s.find('['); + size_t rightBracket = s.find(']', leftBracket); + category = s.substr(leftBracket + 1, rightBracket - 1); + value = s.substr(rightBracket + 1); + return; +} + +bool ctx::Item::operator==(const ctx::Item& other) const +{ + return other.category == category && other.value == value; +} + +bool ctx::Item::operator!=(const ctx::Item& other) const +{ + return !operator==(other); +} + +std::ostream& ctx::operator<<(std::ostream& out, const ctx::Item& item) +{ + return out << '[' << item.category << ']' << item.value; +} diff --git a/src/statistics/prediction/item.h b/src/statistics/prediction/item.h new file mode 100644 index 0000000..edf7d28 --- /dev/null +++ b/src/statistics/prediction/item.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_ITEM_H_ +#define INCLUDE_ITEM_H_ + +#include +#include + +namespace ctx { + + struct Item { + std::string category; + std::string value; + + Item(const std::string &category_, const std::string &value_) : category(category_), value(value_) {} + Item(const std::string &s); // in the form of "[Category]Value" + + bool operator==(const Item& other) const; + bool operator!=(const Item& other) const; + }; + + std::ostream& operator<<(std::ostream& out, const Item& item); + +} /* namespace ctx */ + +namespace std { + + template <> struct hash { + size_t operator()(const ctx::Item &item) const { + hash hasher; + return hasher(item.category + ":" + item.value); + } + }; + +} + +#endif /* INCLUDE_ITEM_H_ */ diff --git a/src/statistics/prediction/item_catalogue.cpp b/src/statistics/prediction/item_catalogue.cpp new file mode 100644 index 0000000..666b5a8 --- /dev/null +++ b/src/statistics/prediction/item_catalogue.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "item_catalogue.h" +#include "item_string_converter.h" + +int ctx::ItemCatalogue::id_of(const ctx::Item& item) +{ + std::string s = ItemStringConverter::item_to_string(item); + std::map::iterator it = mItemIdsOfStrings.find(s); + if (it == mItemIdsOfStrings.end()) { // new item + mMaxId++; + mItemIdsOfStrings[s] = mMaxId; + mItemStrings.push_back(s); + extendCategoryItemIds(item.category, mMaxId); + return mMaxId; + } else { // existing item + return mItemIdsOfStrings[s]; + } +} + +bool ctx::ItemCatalogue::exists_item_of_id(int id) const +{ + return id > 0 && id <= mMaxId; +} + +ctx::Item ctx::ItemCatalogue::item_of_id(int id) const +{ + return ItemStringConverter::string_to_item(mItemStrings[id]); +} + +std::set ctx::ItemCatalogue::category_item_ids(std::string category) const +{ + auto it = mCategoryItemIds.find(category); + if (it == mCategoryItemIds.end()) { + return std::set(); + } else { + return it->second; + } +} + +void ctx::ItemCatalogue::extendCategoryItemIds(std::string category, int itemId) +{ + if (mCategoryItemIds.find(category) == mCategoryItemIds.end()) { + mCategoryItemIds[category] = std::set(); + } + mCategoryItemIds[category].insert(itemId); +} diff --git a/src/statistics/prediction/item_catalogue.h b/src/statistics/prediction/item_catalogue.h new file mode 100644 index 0000000..96b5279 --- /dev/null +++ b/src/statistics/prediction/item_catalogue.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_ITEMCATALOGUE_H_ +#define INCLUDE_ITEMCATALOGUE_H_ + +#include "item.h" +#include +#include +#include + +namespace ctx { + + class ItemCatalogue { + + public: + ItemCatalogue() : mMaxId(0) { + mItemStrings.push_back(std::string("")); + } + + int id_of(Item const &item); + + bool exists_item_of_id(int id) const; + Item item_of_id(int id) const; + std::set category_item_ids(std::string category) const; + int maxId() const {return mMaxId;}; + + private: + /* Translates item string to its id */ + std::map mItemIdsOfStrings; + + /* Translating category string to int */ + std::map> mCategoryItemIds; + + /* Stores item strings (index is item's id) */ + std::vector mItemStrings; + + /* Preserves maximal item's id */ + int mMaxId; + + void extendCategoryItemIds(std::string category, int itemId); + + }; + +} /* namespace ctx */ + +#endif /* INCLUDE_ITEMCATALOGUE_H_ */ diff --git a/src/statistics/prediction/item_id_set.h b/src/statistics/prediction/item_id_set.h new file mode 100644 index 0000000..0604fed --- /dev/null +++ b/src/statistics/prediction/item_id_set.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_ITEM_ID_SET_H_ +#define INCLUDE_ITEM_ID_SET_H_ + +#include + +namespace ctx { + + /* A set storing item ids */ + typedef std::list ItemIdSet; + +} /* namespace ctx */ + +#endif /* INCLUDE_ITEM_ID_SET_H_ */ diff --git a/src/statistics/prediction/item_set.cpp b/src/statistics/prediction/item_set.cpp new file mode 100644 index 0000000..c8dc55b --- /dev/null +++ b/src/statistics/prediction/item_set.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "item_set.h" +#include + +std::ostream& ctx::operator<<(std::ostream& out, const ctx::ItemSet& itemSet) +{ + bool first = true; + for (auto& item : itemSet) { + if (first) { + first = false; + } else { + out << ", "; + } + out << item; + } + return out; +} + +bool ctx::itemset_includes_in(const ctx::ItemSet& small, const ctx::ItemSet& big) +{ + for (const Item& s : small) + if (std::find(big.begin(), big.end(), s) == big.end()) + return false; + return true; +} diff --git a/src/statistics/prediction/item_set.h b/src/statistics/prediction/item_set.h new file mode 100644 index 0000000..98a1b6d --- /dev/null +++ b/src/statistics/prediction/item_set.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_ITEM_SET_H_ +#define INCLUDE_ITEM_SET_H_ + +#include +#include "item.h" + +namespace ctx { + + /* A set storing item ids */ + typedef std::list ItemSet; + + std::ostream& operator<<(std::ostream& out, const ItemSet& itemSet); + + bool itemset_includes_in(const ItemSet& small, const ItemSet& big); + +} /* namespace ctx */ + +#endif /* INCLUDE_ITEM_SET_H_ */ diff --git a/src/statistics/prediction/item_string_converter.cpp b/src/statistics/prediction/item_string_converter.cpp new file mode 100644 index 0000000..399847a --- /dev/null +++ b/src/statistics/prediction/item_string_converter.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "item_string_converter.h" +#include + +std::string ctx::ItemStringConverter::item_to_string(const ctx::Item &item) +{ + return item.category + SEPARATOR + item.value; +} + +ctx::Item ctx::ItemStringConverter::string_to_item(const std::string& s) +{ + size_t pos = s.find(SEPARATOR); + //assert(pos != std::string::npos); + return Item(s.substr(0, pos), s.substr(pos + 1)); +} diff --git a/src/statistics/prediction/item_string_converter.h b/src/statistics/prediction/item_string_converter.h new file mode 100644 index 0000000..961c1f3 --- /dev/null +++ b/src/statistics/prediction/item_string_converter.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_ITEMSTRINGCONVERTER_H_ +#define INCLUDE_ITEMSTRINGCONVERTER_H_ + +#include "item.h" + +namespace ctx { + + class ItemStringConverter { + + public: + static const char SEPARATOR = ':'; + static std::string item_to_string(const Item &item); + static Item string_to_item(const std::string& s); + + }; + +} /* namespace ctx */ + +#endif /* INCLUDE_ITEMSTRINGCONVERTER_H_ */ diff --git a/src/statistics/prediction/single_category_item_id_filter.cpp b/src/statistics/prediction/single_category_item_id_filter.cpp new file mode 100644 index 0000000..6646e8d --- /dev/null +++ b/src/statistics/prediction/single_category_item_id_filter.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "single_category_item_id_filter.h" + +ctx::SingleCategoryItemIdFilter::SingleCategoryItemIdFilter(std::string category, const ctx::ItemCatalogue &itemCatalogue) +{ + mAcceptedItemIds = itemCatalogue.category_item_ids(category); +} + +bool ctx::SingleCategoryItemIdFilter::pass(int itemId) const +{ + return mAcceptedItemIds.find(itemId) != mAcceptedItemIds.end(); +} diff --git a/src/statistics/prediction/single_category_item_id_filter.h b/src/statistics/prediction/single_category_item_id_filter.h new file mode 100644 index 0000000..4ef9cf4 --- /dev/null +++ b/src/statistics/prediction/single_category_item_id_filter.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SINGLE_CATEGORY_ITEM_ID_FILTER_H_ +#define SINGLE_CATEGORY_ITEM_ID_FILTER_H_ + +#include "i_item_id_filter.h" +#include "item_catalogue.h" + +namespace ctx { + + class SingleCategoryItemIdFilter : public IItemIdFilter { + + public: + SingleCategoryItemIdFilter(std::string category, const ItemCatalogue& itemCatalogue); + bool pass(int itemId) const override; + + private: + std::set mAcceptedItemIds; + + }; + +} /* namespace ctx */ + +#endif /* SINGLE_CATEGORY_ITEM_ID_FILTER_H_ */ diff --git a/src/statistics/prediction/weight_apriori.cpp b/src/statistics/prediction/weight_apriori.cpp new file mode 100644 index 0000000..92aaebc --- /dev/null +++ b/src/statistics/prediction/weight_apriori.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "weight_apriori.h" +#include +#include + +std::list ctx::WeightApriori::find_wider_candidates(const std::list &narrowFreqSets, int widerSize) +{ + std::list candidates; + for (auto iter1 = narrowFreqSets.begin(); iter1 != narrowFreqSets.end(); ++iter1) { + auto iter2 = iter1; ++iter2; + for (;iter2 != narrowFreqSets.end(); ++iter2) { + ItemIdSet itemIdSet1 = *iter1; + ItemIdSet itemIdSet2 = *iter2; + itemIdSet1.merge(itemIdSet2); + itemIdSet1.unique(); + if (int(itemIdSet1.size()) == widerSize) { + candidates.push_back(itemIdSet1); + } + } + } + candidates.sort(); + candidates.unique(); + return candidates; +} + +void ctx::WeightApriori::prune_wider_candidates(std::list& widerCandidates, const std::list& narrowFreqSets) +{ + std::list pruned; + for (auto iter = widerCandidates.begin(); iter != widerCandidates.end();) { + if (survives_prunning(*iter, narrowFreqSets)) { + ++iter; + } else { + iter = widerCandidates.erase(iter); + } + } +} + +bool ctx::WeightApriori::survives_prunning(ctx::ItemIdSet& widerCandidate, const std::list& narrowFreqSets) +{ + int removedItemId = widerCandidate.front(); + widerCandidate.pop_front(); + for (auto iter = widerCandidate.begin();; ++iter) { + if (std::find(narrowFreqSets.begin(), narrowFreqSets.end(), widerCandidate) == narrowFreqSets.end()) { + return false; // Caution: In this case the original contents of widerCandidate is not preserved. + } + if (iter == widerCandidate.end()) { + widerCandidate.push_back(removedItemId); // Restoring original contents of widerCandidate. + return true; + } + int newRemovedItemId = *iter; + *iter = removedItemId; + removedItemId = newRemovedItemId; + } +} + +std::list> ctx::WeightApriori::find_frequent_itemid_sets(ctx::BasketsAgregator &basketAgregator, double supportThreshold) +{ + std::list> allFreqItemsets; + std::list freqItemsetsOfCurrSize; + std::list candidates; + + int candidateSize = 1; + candidates = single_size_candidates(basketAgregator); + + while (!candidates.empty()) { + for (ItemIdSet candidate : candidates) { + double support = basketAgregator.supportOf(candidate); + if (support >= supportThreshold) { + freqItemsetsOfCurrSize.push_back(candidate); + allFreqItemsets.push_back(std::make_pair(candidate,support)); + } + } + candidates = find_wider_candidates(freqItemsetsOfCurrSize, ++candidateSize); + freqItemsetsOfCurrSize.clear(); + } + return allFreqItemsets; +} + +std::list ctx::WeightApriori::single_size_candidates(ctx::BasketsAgregator& basketAgregator) +{ + std::list candidates; + for (int itemId : basketAgregator.unique_item_ids()) { + candidates.push_back({itemId}); + } + return candidates; +} diff --git a/src/statistics/prediction/weight_apriori.h b/src/statistics/prediction/weight_apriori.h new file mode 100644 index 0000000..94aecf2 --- /dev/null +++ b/src/statistics/prediction/weight_apriori.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_WEIGHT_APRIORI_H_ +#define INCLUDE_WEIGHT_APRIORI_H_ + +#include "baskets_agregator.h" +#include +#include + +namespace ctx { + + class WeightApriori { + + public: + static std::list find_wider_candidates(const std::list &narrowFreqSets, int widerSize); + static void prune_wider_candidates(std::list &widerCandidates, const std::list &narrowFreqSets); + + static bool survives_prunning(ItemIdSet &widerCandidate, const std::list &narrowFreqSets); + + /* Find frequent itemsets along with its support value. */ + static std::list> find_frequent_itemid_sets(BasketsAgregator &basketAgregator, double supportThreshold); + + private: + static std::list single_size_candidates(BasketsAgregator &basketAgregator); + + }; + +} /* namespace ctx */ + +#endif /* INCLUDE_WEIGHT_APRIORI_H_ */ diff --git a/src/statistics/shared/common_types.h b/src/statistics/shared/common_types.h new file mode 100644 index 0000000..f173df9 --- /dev/null +++ b/src/statistics/shared/common_types.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_STATS_COMMON_TYPES_H__ +#define __CONTEXT_STATS_COMMON_TYPES_H__ + +#define LOG_RETENTION_PERIOD 7776000 /* 90 days in secs */ + +#define DEFAULT_TIMESPAN 30 +#define DEFAULT_LIMIT 10 + +#define STATS_QUERY_RESULT "QueryResult" +#define STATS_RESULT_SIZE "ResultSize" +#define STATS_COL_ROW_ID "row_id" + +#define STATS_TIMESPAN "TimeSpan" +#define STATS_START_TIME "StartTime" +#define STATS_END_TIME "EndTime" +#define STATS_LAST_TIME "LastTime" +#define STATS_TOTAL_COUNT "TotalCount" +#define STATS_AVERAGE_COUNT "AvgCount" +#define STATS_DURATION "Duration" +#define STATS_TOTAL_DURATION "TotalDuration" +#define STATS_DAY_OF_WEEK "DayOfWeek" +#define STATS_HOUR_OF_DAY "HourOfDay" +#define STATS_TIME_OF_DAY "TimeOfDay" +#define STATS_TOTAL_COUNT "TotalCount" +#define STATS_APP_ID "AppId" +#define STATS_PKG_ID "PkgId" +#define STATS_AUDIO_JACK "AudioJack" +#define STATS_SYSTEM_VOLUME "SystemVolume" +#define STATS_MEDIA_VOLUME "MediaVolume" +#define STATS_BSSID "BSSID" +#define STATS_UNIV_TIME "UTC" +#define STATS_LOCAL_TIME "LocalTime" +#define STATS_RANK "Rank" + +#define STATS_SUN "Sun" +#define STATS_MON "Mon" +#define STATS_TUE "Tue" +#define STATS_WED "Wed" +#define STATS_THU "Thu" +#define STATS_FRI "Fri" +#define STATS_SAT "Sat" +#define STATS_WEEKDAY "Weekday" +#define STATS_WEEKEND "Weekend" + +enum stats_day_of_week_e { + STATS_DAY_OF_WEEK_WEEKDAY = 1, + STATS_DAY_OF_WEEK_WEEKEND, + STATS_DAY_OF_WEEK_ALL, + STATS_DAY_OF_WEEK_SUN, + STATS_DAY_OF_WEEK_MON, + STATS_DAY_OF_WEEK_TUE, + STATS_DAY_OF_WEEK_WED, + STATS_DAY_OF_WEEK_THU, + STATS_DAY_OF_WEEK_FRI, + STATS_DAY_OF_WEEK_SAT, +}; + +#define TRIG_DEF_RANK "\"Rank\":{\"type\":\"integer\",\"min\":1}" +#define TRIG_DEF_TOTAL_COUNT "\"TotalCount\":{\"type\":\"integer\",\"min\":0}" +#define TRIG_DEF_TIME_OF_DAY "\"TimeOfDay\":{\"type\":\"string\"}" +#define TRIG_DEF_DAY_OF_WEEK "\"DayOfWeek\":{\"type\":\"string\",\"values\":[\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\",\"Sun\",\"Weekday\",\"Weekend\"]}" + +#endif diff --git a/src/statistics/shared/db_handle_base.cpp b/src/statistics/shared/db_handle_base.cpp new file mode 100644 index 0000000..e3d0602 --- /dev/null +++ b/src/statistics/shared/db_handle_base.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "common_types.h" +#include "db_handle_base.h" + +#define DAY_OF_WEEK(SECOND) "CAST(strftime('%w', " SECOND ", 'unixepoch') AS INTEGER)" +#define HOUR_OF_DAY(SECOND) "CAST(strftime('%H', " SECOND ", 'unixepoch') AS INTEGER)" + +ctx::stats_db_handle_base::stats_db_handle_base() + : is_trigger_item(false) +{ +} + +ctx::stats_db_handle_base::~stats_db_handle_base() +{ +} + +int ctx::stats_db_handle_base::generate_qid() +{ + static int qid = 0; + + if (qid++ < 0) qid = 1; + return qid; +} + +bool ctx::stats_db_handle_base::execute_query(const char* subject, ctx::json filter, const char* query) +{ + bool ret = db_manager::execute(generate_qid(), query, this); + IF_FAIL_RETURN(ret, false); + + req_subject = subject; + req_filter = filter; + + return true; +} + +std::string ctx::stats_db_handle_base::create_where_clause(ctx::json filter) +{ + std::stringstream where_clause; + int week = 0; + int start = 0; + int end = 0; + int timespan = DEFAULT_TIMESPAN; + std::string app_id; + std::string week_str; + std::string time_of_day; + + if (filter.get(NULL, STATS_DAY_OF_WEEK, &week_str)) { + // In case of string (from Trigger) + if (week_str == STATS_WEEKDAY) { + week = STATS_DAY_OF_WEEK_WEEKDAY; + + } else if (week_str == STATS_WEEKEND) { + week = STATS_DAY_OF_WEEK_WEEKEND; + + } else if (week_str == STATS_SUN) { + week = STATS_DAY_OF_WEEK_SUN; + + } else if (week_str == STATS_MON) { + week = STATS_DAY_OF_WEEK_MON; + + } else if (week_str == STATS_TUE) { + week = STATS_DAY_OF_WEEK_TUE; + + } else if (week_str == STATS_WED) { + week = STATS_DAY_OF_WEEK_WED; + + } else if (week_str == STATS_THU) { + week = STATS_DAY_OF_WEEK_THU; + + } else if (week_str == STATS_FRI) { + week = STATS_DAY_OF_WEEK_FRI; + + } else if (week_str == STATS_SAT) { + week = STATS_DAY_OF_WEEK_SAT; + } + } else { + // In case of integer (from History) + filter.get(NULL, STATS_DAY_OF_WEEK, &week); + } + + switch(week) { + case STATS_DAY_OF_WEEK_WEEKDAY: + where_clause << "(" DAY_OF_WEEK(STATS_LOCAL_TIME) " > 0 AND " DAY_OF_WEEK(STATS_LOCAL_TIME) " < 6) AND "; + break; + case STATS_DAY_OF_WEEK_WEEKEND: + where_clause << "(" DAY_OF_WEEK(STATS_LOCAL_TIME) " = 0 OR " DAY_OF_WEEK(STATS_LOCAL_TIME) " = 6) AND "; + break; + case STATS_DAY_OF_WEEK_SUN: + case STATS_DAY_OF_WEEK_MON: + case STATS_DAY_OF_WEEK_TUE: + case STATS_DAY_OF_WEEK_WED: + case STATS_DAY_OF_WEEK_THU: + case STATS_DAY_OF_WEEK_FRI: + case STATS_DAY_OF_WEEK_SAT: + where_clause << DAY_OF_WEEK(STATS_LOCAL_TIME) " = " << week - STATS_DAY_OF_WEEK_SUN << " AND "; + break; + default: + break; + } + + if (filter.get(NULL, STATS_APP_ID, &app_id)) + where_clause << STATS_APP_ID " = '" << app_id << "' AND "; + + if (filter.get(NULL, STATS_START_TIME, &start)) + where_clause << STATS_UNIV_TIME " >= " << start << " AND "; + + if (filter.get(NULL, STATS_END_TIME, &end)) + where_clause << STATS_UNIV_TIME " <= " << end << " AND "; + + if (filter.get(NULL, STATS_TIME_OF_DAY, &time_of_day)) { + size_t pivot = time_of_day.find('-'); + if (pivot != std::string::npos) { + std::string from = time_of_day.substr(0, pivot); + std::string to = time_of_day.substr(pivot + 1); + where_clause << "(" HOUR_OF_DAY(STATS_LOCAL_TIME) " >= " << from \ + << " AND " HOUR_OF_DAY(STATS_LOCAL_TIME) " < " << to << ") AND "; + } + } + + filter.get(NULL, STATS_TIMESPAN, ×pan); + where_clause << STATS_UNIV_TIME " > strftime('%s', 'now', '-" << timespan <<" day')"; + + return where_clause.str(); +} + +std::string ctx::stats_db_handle_base::create_sql_peak_time(ctx::json filter, const char* table_name, std::string where_clause) +{ + std::stringstream query; + int limit = DEFAULT_LIMIT; + + filter.get(NULL, STATS_RESULT_SIZE, &limit); + + query << + "SELECT " \ + HOUR_OF_DAY(STATS_LOCAL_TIME) " AS " STATS_HOUR_OF_DAY ", COUNT(*) AS " STATS_TOTAL_COUNT \ + " FROM " << table_name << \ + " WHERE " << where_clause << \ + " GROUP BY " HOUR_OF_DAY(STATS_LOCAL_TIME) \ + " ORDER BY " STATS_TOTAL_COUNT " DESC" \ + " LIMIT " << limit; + + return query.str(); +} + +std::string ctx::stats_db_handle_base::create_sql_common_setting(ctx::json filter, const char* table_name, std::string where_clause) +{ + std::stringstream query; + + query << + "SELECT ( SELECT " STATS_AUDIO_JACK \ + " FROM " << table_name << \ + " WHERE " << where_clause << \ + " GROUP BY " STATS_AUDIO_JACK \ + " ORDER BY count(" STATS_AUDIO_JACK ") DESC" \ + " LIMIT 1 ) AS " STATS_AUDIO_JACK \ + ", ( SELECT " STATS_SYSTEM_VOLUME \ + " FROM " << table_name << \ + " WHERE " << where_clause << \ + " GROUP BY " STATS_SYSTEM_VOLUME \ + " ORDER BY count(" STATS_SYSTEM_VOLUME ") DESC" \ + " LIMIT 1 ) AS " STATS_SYSTEM_VOLUME \ + ", ( SELECT " STATS_MEDIA_VOLUME \ + " FROM " << table_name << \ + " WHERE " << where_clause << \ + " GROUP BY " STATS_MEDIA_VOLUME \ + " ORDER BY count(" STATS_MEDIA_VOLUME ") DESC" \ + " LIMIT 1 ) AS " STATS_MEDIA_VOLUME; + + return query.str(); +} + +void ctx::stats_db_handle_base::on_creation_result_received(unsigned int query_id, int error) +{ +} + +void ctx::stats_db_handle_base::on_insertion_result_received(unsigned int query_id, int error, int64_t row_id) +{ + delete this; +} + +void ctx::stats_db_handle_base::json_vector_to_array(std::vector &vec_json, ctx::json &json_result) +{ + std::vector::iterator json_vec_end = vec_json.end(); + + for(std::vector::iterator json_vec_pos = vec_json.begin(); json_vec_pos != json_vec_end; ++json_vec_pos) { + json origin_j = *json_vec_pos; + json_result.array_append(NULL, STATS_QUERY_RESULT, origin_j); + } +} + +void ctx::stats_db_handle_base::on_query_result_received(unsigned int query_id, int error, std::vector& records) +{ + if (is_trigger_item) { + if (records.size() == 1) { + reply_trigger_item(error, records[0]); + } else { + _E("Invalid query result"); + json dummy; + context_manager::reply_to_read(req_subject.c_str(), req_filter, ERR_OPERATION_FAILED, dummy); + } + } else { + json results = "{\"" STATS_QUERY_RESULT "\":[]}"; + json_vector_to_array(records, results); + context_manager::reply_to_read(req_subject.c_str(), req_filter, error, results); + } + + delete this; +} diff --git a/src/statistics/shared/db_handle_base.h b/src/statistics/shared/db_handle_base.h new file mode 100644 index 0000000..6e05696 --- /dev/null +++ b/src/statistics/shared/db_handle_base.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_STATS_DB_HANDLE_BASE_H__ +#define __CONTEXT_STATS_DB_HANDLE_BASE_H__ + +#include +#include +#include + +namespace ctx { + class stats_db_handle_base : public db_listener_iface { + protected: + bool is_trigger_item; + std::string req_subject; + ctx::json req_filter; + + stats_db_handle_base(); + ~stats_db_handle_base(); + + std::string create_where_clause(ctx::json filter); + std::string create_sql_peak_time(ctx::json filter, const char* table_name, std::string where_clause); + std::string create_sql_common_setting(ctx::json filter, const char* table_name, std::string where_clause); + + bool execute_query(const char* subject, ctx::json filter, const char* query); + virtual void reply_trigger_item(int error, ctx::json &json_result) = 0; + static int generate_qid(); + + private: + void json_vector_to_array(std::vector &vec_json, ctx::json &json_result); + + void on_creation_result_received(unsigned int query_id, int error); + void on_insertion_result_received(unsigned int query_id, int error, int64_t row_id); + void on_query_result_received(unsigned int query_id, int error, std::vector& records); + }; +} + +#endif /* __CONTEXT_STATS_DB_HANDLE_BASE_H__ */ diff --git a/src/statistics/shared/system_info.cpp b/src/statistics/shared/system_info.cpp new file mode 100644 index 0000000..548e328 --- /dev/null +++ b/src/statistics/shared/system_info.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "system_info.h" + +#define CONNECTED 1 +#define NOT_CONNECTED 0 + +bool ctx::system_info::get_audio_jack_state(int* state) +{ + int value = NOT_CONNECTED; + int err = runtime_info_get_value_int(RUNTIME_INFO_KEY_AUDIO_JACK_STATUS, &value); + IF_FAIL_RETURN(err == RUNTIME_INFO_ERROR_NONE, false); + + *state = (value == NOT_CONNECTED ? NOT_CONNECTED : CONNECTED); + + return true; +} + +bool ctx::system_info::get_volume(int* system_volume, int* media_volume) +{ + int err; + + err = sound_manager_get_volume(SOUND_TYPE_SYSTEM, system_volume); + IF_FAIL_RETURN(err == RUNTIME_INFO_ERROR_NONE, false); + + err = sound_manager_get_volume(SOUND_TYPE_MEDIA, media_volume); + IF_FAIL_RETURN(err == RUNTIME_INFO_ERROR_NONE, false); + + return true; +} + +bool ctx::system_info::get_wifi_bssid(std::string& bssid) +{ +#if 0 + /* NOTE: This routine does not work, because the wifi API does not support multi-sessions in one process */ + int err; + char *str_buf = NULL; + wifi_ap_h ap = NULL; + + err = wifi_initialize(); + IF_FAIL_RETURN_TAG(err == WIFI_ERROR_NONE, false, _W, "wifi_initialize() failed (%d)", err); + + err = wifi_get_connected_ap(&ap); + if (err != WIFI_ERROR_NONE) { + _D("wifi_get_connected_ap() failed (%d)", err); + wifi_deinitialize(); + return false; + } + + wifi_ap_get_bssid(ap, &str_buf); + bssid = (str_buf != NULL ? str_buf : ""); + g_free(str_buf); + + wifi_ap_destroy(ap); + wifi_deinitialize(); + + return !bssid.empty(); +#endif + bssid = ctx::shared::wifi_bssid; + return true; +} diff --git a/src/statistics/shared/system_info.h b/src/statistics/shared/system_info.h new file mode 100644 index 0000000..025a056 --- /dev/null +++ b/src/statistics/shared/system_info.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_SYSTEM_INFO_READER_H__ +#define __CONTEXT_SYSTEM_INFO_READER_H__ + +#include + +namespace ctx { + namespace system_info { + bool get_audio_jack_state(int* state); + bool get_volume(int* system_volume, int* media_volume); + bool get_wifi_bssid(std::string& bssid); + } +} + +#endif /* __CONTEXT_SYSTEM_INFO_READER_H__ */ diff --git a/src/statistics/social/db_handle.cpp b/src/statistics/social/db_handle.cpp new file mode 100644 index 0000000..ccdb1c2 --- /dev/null +++ b/src/statistics/social/db_handle.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "social_stats_types.h" +#include "db_handle.h" + +ctx::social_db_handle::social_db_handle() +{ +} + +ctx::social_db_handle::~social_db_handle() +{ +} + +int ctx::social_db_handle::read(const char* subject, ctx::json filter) +{ + std::string query; + + if (STR_EQ(subject, SOCIAL_SUBJ_FREQ_ADDRESS)) { + query = create_sql_freq_address(filter); + + } else if (STR_EQ(subject, SOCIAL_SUBJ_FREQUENCY)) { + is_trigger_item = true; + query = create_sql_frequency(filter); + } + + IF_FAIL_RETURN(!query.empty(), ERR_OPERATION_FAILED); + + bool ret = execute_query(subject, filter, query.c_str()); + IF_FAIL_RETURN(ret, ERR_OPERATION_FAILED); + + return ERR_NONE; +} + +std::string ctx::social_db_handle::create_where_clause(ctx::json filter) +{ + std::stringstream where_clause; + int comm_type = -1; + + where_clause << stats_db_handle_base::create_where_clause(filter); + + filter.get(NULL, SOCIAL_COMMUNICATION_TYPE, &comm_type); + + switch(comm_type) { + case SOCIAL_COMMUNICATION_TYPE_CALL: + where_clause << + " AND " SOCIAL_PHONE_LOG_TYPE " >= " << CONTACTS_PLOG_TYPE_VOICE_INCOMMING << + " AND " SOCIAL_PHONE_LOG_TYPE " <= " << CONTACTS_PLOG_TYPE_VIDEO_BLOCKED; + break; + case SOCIAL_COMMUNICATION_TYPE_MESSAGE: + where_clause << + " AND " SOCIAL_PHONE_LOG_TYPE " >= " << CONTACTS_PLOG_TYPE_MMS_INCOMMING << + " AND " SOCIAL_PHONE_LOG_TYPE " <= " << CONTACTS_PLOG_TYPE_MMS_BLOCKED; + break; + default: + break; + } + + return where_clause.str(); +} + +std::string ctx::social_db_handle::create_sql_freq_address(ctx::json filter) +{ + std::stringstream query; + int limit = DEFAULT_LIMIT; + + filter.get(NULL, STATS_RESULT_SIZE, &limit); + + query << + "SELECT " SOCIAL_ADDRESS ", " \ + "COUNT(*) AS " STATS_TOTAL_COUNT ", " \ + "SUM(" STATS_DURATION ") AS " STATS_TOTAL_DURATION ", " \ + "MAX(" STATS_UNIV_TIME ") AS " STATS_LAST_TIME \ + " FROM " SOCIAL_TABLE_CONTACT_LOG \ + " WHERE " << create_where_clause(filter) << + " GROUP BY " SOCIAL_ADDRESS \ + " ORDER BY COUNT(*) DESC" \ + " LIMIT " << limit; + + return query.str(); +} + +std::string ctx::social_db_handle::create_sql_frequency(ctx::json filter) +{ + ctx::json filter_cleaned; + std::string week_str; + std::string time_of_day; + std::string address; + + if (!filter.get(NULL, SOCIAL_ADDRESS, &address)) { + _E("Invalid parameter"); + return ""; + } + + if (filter.get(NULL, STATS_DAY_OF_WEEK, &week_str)) + filter_cleaned.set(NULL, STATS_DAY_OF_WEEK, week_str); + + if (filter.get(NULL, STATS_TIME_OF_DAY, &time_of_day)) + filter_cleaned.set(NULL, STATS_TIME_OF_DAY, time_of_day); + + std::stringstream query; + + query << + "DELETE FROM " SOCIAL_TEMP_CONTACT_FREQ ";"; + + query << + "INSERT INTO " SOCIAL_TEMP_CONTACT_FREQ \ + " SELECT " SOCIAL_ADDRESS ", COUNT(*) AS " STATS_TOTAL_COUNT \ + " FROM " SOCIAL_TABLE_CONTACT_LOG \ + " WHERE " << create_where_clause(filter_cleaned) << + " GROUP BY " SOCIAL_ADDRESS ";"; + + query << + "INSERT OR IGNORE INTO " SOCIAL_TEMP_CONTACT_FREQ " (" SOCIAL_ADDRESS ")" \ + " VALUES ('" << address << "');"; + + query << + "SELECT S." SOCIAL_ADDRESS ", S." STATS_TOTAL_COUNT ", 1+COUNT(lesser." STATS_TOTAL_COUNT ") AS " STATS_RANK \ + " FROM " SOCIAL_TEMP_CONTACT_FREQ " AS S" \ + " LEFT JOIN " SOCIAL_TEMP_CONTACT_FREQ " AS lesser" \ + " ON S." STATS_TOTAL_COUNT " < lesser." STATS_TOTAL_COUNT \ + " WHERE S." SOCIAL_ADDRESS " = '" << address << "'"; + + + return query.str(); +} + +void ctx::social_db_handle::reply_trigger_item(int error, ctx::json &json_result) +{ + IF_FAIL_VOID_TAG(STR_EQ(req_subject.c_str(), SOCIAL_SUBJ_FREQUENCY), _E, "Invalid subject"); + + ctx::json results; + std::string val_str; + int val; + + json_result.get(NULL, SOCIAL_ADDRESS, &val_str); + results.set(NULL, SOCIAL_ADDRESS, val_str); + json_result.get(NULL, STATS_TOTAL_COUNT, &val); + results.set(NULL, STATS_TOTAL_COUNT, val); + json_result.get(NULL, STATS_RANK, &val); + results.set(NULL, STATS_RANK, val); + + context_manager::reply_to_read(req_subject.c_str(), req_filter, error, results); +} diff --git a/src/statistics/social/db_handle.h b/src/statistics/social/db_handle.h new file mode 100644 index 0000000..8254f41 --- /dev/null +++ b/src/statistics/social/db_handle.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_SOCIAL_DB_HANDLE_H__ +#define __CONTEXT_SOCIAL_DB_HANDLE_H__ + +#include +#include +#include + +namespace ctx { + class social_db_handle : public stats_db_handle_base { + public: + social_db_handle(); + ~social_db_handle(); + + int read(const char* subject, ctx::json filter); + + private: + std::string create_where_clause(ctx::json filter); + std::string create_sql_freq_address(ctx::json filter); + std::string create_sql_frequency(ctx::json filter); + void reply_trigger_item(int error, ctx::json &json_result); + }; +} + +#endif /* __CONTEXT_SOCIAL_DB_HANDLE_H__ */ diff --git a/src/statistics/social/log_aggregator.cpp b/src/statistics/social/log_aggregator.cpp new file mode 100644 index 0000000..4e80053 --- /dev/null +++ b/src/statistics/social/log_aggregator.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "social_stats_types.h" +#include "log_aggregator.h" + +ctx::contact_log_aggregator::contact_log_aggregator() + : timer_id(-1) +{ + create_table(); + timer_id = timer_manager::set_at(3, 0, timer_types::EVERYDAY, this, NULL); +} + +ctx::contact_log_aggregator::~contact_log_aggregator() +{ + timer_manager::remove(timer_id); +} + +void ctx::contact_log_aggregator::create_table() +{ + static bool done = false; + IF_FAIL_VOID(!done); + + db_manager::create_table(0, SOCIAL_TABLE_CONTACT_LOG, SOCIAL_TABLE_CONTACT_LOG_COLUMNS, NULL, NULL); + db_manager::execute(0, SOCIAL_TEMP_CONTACT_FREQ_SQL, NULL); + + done = true; +} + +bool ctx::contact_log_aggregator::on_timer_expired(int timer, void* user_data) +{ + aggregate_contact_log(); + return true; +} + +void ctx::contact_log_aggregator::aggregate_contact_log() +{ + db_manager::execute(0, + "SELECT IFNULL(MAX(" STATS_UNIV_TIME "),0) AS " STATS_LAST_TIME \ + ", (strftime('%s', 'now', 'localtime')) - (strftime('%s', 'now')) AS " TIME_DIFFERENCE \ + " FROM " SOCIAL_TABLE_CONTACT_LOG, this); +} + +void ctx::contact_log_aggregator::on_query_result_received(unsigned int query_id, int error, std::vector& records) +{ + IF_FAIL_VOID_TAG(!records.empty(), _E, "Invalid query result"); + + int last_time = 0; + records[0].get(NULL, STATS_LAST_TIME, &last_time); + records[0].get(NULL, TIME_DIFFERENCE, &time_diff); + + _D("Last Time: %d / Local - UTC: %d", last_time, time_diff); + + contacts_list_h list = NULL; + + get_updated_contact_log_list(last_time, &list); + IF_FAIL_VOID(list); + + remove_expired_log(); + insert_contact_log_list(list); + destroy_contact_log_list(list); +} + +void ctx::contact_log_aggregator::get_updated_contact_log_list(int last_time, contacts_list_h *list) +{ + contacts_filter_h filter = NULL; + contacts_query_h query = NULL; + + int err = contacts_connect(); + IF_FAIL_VOID_TAG(err == CONTACTS_ERROR_NONE, _E, "contacts_connect() failed"); + + err = contacts_filter_create(_contacts_phone_log._uri, &filter); + IF_FAIL_CATCH_TAG(err == CONTACTS_ERROR_NONE, _E, "contacts_filter_create() failed"); + + contacts_filter_add_int(filter, _contacts_phone_log.log_type, CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, CONTACTS_PLOG_TYPE_VOICE_INCOMMING); + contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_AND); + contacts_filter_add_int(filter, _contacts_phone_log.log_type, CONTACTS_MATCH_LESS_THAN_OR_EQUAL, CONTACTS_PLOG_TYPE_MMS_BLOCKED); + contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_AND); + contacts_filter_add_int(filter, _contacts_phone_log.log_time , CONTACTS_MATCH_GREATER_THAN, last_time); + contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_AND); + + err = contacts_query_create(_contacts_phone_log._uri, &query); + IF_FAIL_CATCH_TAG(err == CONTACTS_ERROR_NONE, _E, "contacts_query_create() failed"); + + contacts_query_set_filter(query, filter); + contacts_query_set_sort(query, _contacts_phone_log.log_time, true); + + err = contacts_db_get_records_with_query(query, 0, 0, list); + IF_FAIL_CATCH_TAG(err == CONTACTS_ERROR_NONE, _E, "contacts_db_get_records_with_query() failed"); + +CATCH: + if (filter) + contacts_filter_destroy(filter); + if (query) + contacts_query_destroy(query); +} + +void ctx::contact_log_aggregator::destroy_contact_log_list(contacts_list_h list) +{ + if (list) + contacts_list_destroy(list, true); + + contacts_disconnect(); +} + +void ctx::contact_log_aggregator::insert_contact_log_list(contacts_list_h list) +{ + IF_FAIL_VOID(contacts_list_first(list) == CONTACTS_ERROR_NONE); + + do { + contacts_record_h record = NULL; + contacts_list_get_current_record_p(list, &record); + if (record == NULL) break; + + ctx::json data; + + char* address = NULL; + int log_type; + int duration = 0; + int accesstime = 0; + + contacts_record_get_str_p(record, _contacts_phone_log.address, &address); + + if (!address) { + _W("Getting address failed"); + continue; + } + + contacts_record_get_int(record, _contacts_phone_log.log_type, &log_type); + contacts_record_get_int(record, _contacts_phone_log.extra_data1, &duration); + contacts_record_get_int(record, _contacts_phone_log.log_time, &accesstime); + + data.set(NULL, SOCIAL_ADDRESS, address); + data.set(NULL, SOCIAL_PHONE_LOG_TYPE, log_type); + data.set(NULL, STATS_DURATION, duration); + data.set(NULL, STATS_UNIV_TIME, accesstime); + data.set(NULL, STATS_LOCAL_TIME, accesstime + time_diff); + + db_manager::insert(0, SOCIAL_TABLE_CONTACT_LOG, data, NULL); + + } while(contacts_list_next(list) == CONTACTS_ERROR_NONE); +} + +void ctx::contact_log_aggregator::remove_expired_log() +{ + std::stringstream query; + query << "DELETE FROM " SOCIAL_TABLE_CONTACT_LOG " WHERE " \ + STATS_UNIV_TIME " < strftime('%s', 'now') - " << LOG_RETENTION_PERIOD; + db_manager::execute(0, query.str().c_str(), NULL); +} diff --git a/src/statistics/social/log_aggregator.h b/src/statistics/social/log_aggregator.h new file mode 100644 index 0000000..57c154f --- /dev/null +++ b/src/statistics/social/log_aggregator.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_SOCIAL_CONTACT_LOG_AGGREGATOR_H__ +#define __CONTEXT_SOCIAL_CONTACT_LOG_AGGREGATOR_H__ + +#include +#include +#include + +namespace ctx { + + class contact_log_aggregator : public db_listener_iface, public timer_listener_iface { + private: + int timer_id; + int time_diff; + void create_table(); + void get_updated_contact_log_list(int last_time, contacts_list_h *list); + void insert_contact_log_list(contacts_list_h list); + void destroy_contact_log_list(contacts_list_h list); + void remove_expired_log(); + + public: + contact_log_aggregator(); + ~contact_log_aggregator(); + + void aggregate_contact_log(); + + void on_creation_result_received(unsigned int query_id, int error) {} + void on_insertion_result_received(unsigned int query_id, int error, int64_t row_id) {} + void on_query_result_received(unsigned int query_id, int error, std::vector& records); + bool on_timer_expired(int timer_id, void* user_data); + + }; /* class phone_contact_log_aggregator */ + +} /* namespace ctx */ + +#endif diff --git a/src/statistics/social/social_stats_provider.cpp b/src/statistics/social/social_stats_provider.cpp new file mode 100644 index 0000000..92bb856 --- /dev/null +++ b/src/statistics/social/social_stats_provider.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "social_stats_provider.h" +#include "db_handle.h" +#include "log_aggregator.h" + +static ctx::contact_log_aggregator *aggregator = NULL; + +ctx::social_statistics_provider *ctx::social_statistics_provider::__instance = NULL; + +ctx::social_statistics_provider::social_statistics_provider() +{ +} + +ctx::social_statistics_provider::~social_statistics_provider() +{ + delete aggregator; +} + +ctx::context_provider_iface *ctx::social_statistics_provider::create(void *data) +{ + IF_FAIL_RETURN(!__instance, __instance); + + __instance = new(std::nothrow) social_statistics_provider(); + IF_FAIL_RETURN_TAG(__instance, NULL, _E, "Memory allocation failed"); + + _I(BLUE("Created")); + + if (!__instance->init()) { + destroy(data); + return NULL; + } + + return __instance; +} + +void ctx::social_statistics_provider::destroy(void *data) +{ + IF_FAIL_VOID(__instance); + delete __instance; + __instance = NULL; + _I(BLUE("Destroyed")); +} + +bool ctx::social_statistics_provider::is_supported(const char* subject) +{ + return true; +} + +void ctx::social_statistics_provider::submit_trigger_item() +{ + context_manager::register_trigger_item(SOCIAL_SUBJ_FREQUENCY, OPS_READ, + "{" TRIG_DEF_RANK "," TRIG_DEF_TOTAL_COUNT "}", + "{" + "\"Address\":{\"type\":\"string\"}," + TRIG_DEF_TIME_OF_DAY "," TRIG_DEF_DAY_OF_WEEK + "}"); +} + +bool ctx::social_statistics_provider::init() +{ + aggregator = new(std::nothrow) contact_log_aggregator(); + IF_FAIL_RETURN_TAG(aggregator, false, _E, "Memory allocation failed"); + return true; +} + +int ctx::social_statistics_provider::subscribe(const char* subject, ctx::json option, ctx::json* request_result) +{ + return ERR_NOT_SUPPORTED; +} + +int ctx::social_statistics_provider::unsubscribe(const char* subject, ctx::json option) +{ + return ERR_NOT_SUPPORTED; +} + +int ctx::social_statistics_provider::read(const char* subject, ctx::json option, ctx::json* request_result) +{ + ctx::social_db_handle *handle = new(std::nothrow) ctx::social_db_handle(); + IF_FAIL_RETURN_TAG(handle, ERR_OPERATION_FAILED, _E, "Memory allocation failed"); + + int err = handle->read(subject, option); + if (err != ERR_NONE) { + delete handle; + return err; + } + + return ERR_NONE; +} + +int ctx::social_statistics_provider::write(const char* subject, ctx::json data, ctx::json* request_result) +{ + return ERR_NOT_SUPPORTED; +} diff --git a/src/statistics/social/social_stats_provider.h b/src/statistics/social/social_stats_provider.h new file mode 100644 index 0000000..64ab059 --- /dev/null +++ b/src/statistics/social/social_stats_provider.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_SOCIAL_STATS_PROVIDER_H__ +#define __CONTEXT_SOCIAL_STATS_PROVIDER_H__ + +#include +#include "social_stats_types.h" + +namespace ctx { + + class social_statistics_provider : public context_provider_iface { + public: + static context_provider_iface *create(void *data); + static void destroy(void *data); + static bool is_supported(const char *subject); + static void submit_trigger_item(); + + int subscribe(const char* subject, ctx::json option, ctx::json* request_result); + int unsubscribe(const char* subject, ctx::json option); + int read(const char* subject, ctx::json option, ctx::json* request_result); + int write(const char* subject, ctx::json data, ctx::json* request_result); + + private: + static social_statistics_provider *__instance; + + social_statistics_provider(); + ~social_statistics_provider(); + bool init(); + + }; /* class social_statistics_provider */ + +} /* namespace ctx */ + +#endif /* __CONTEXT_SOCIAL_STATS_PROVIDER_H__ */ diff --git a/src/statistics/social/social_stats_types.h b/src/statistics/social/social_stats_types.h new file mode 100644 index 0000000..b627c67 --- /dev/null +++ b/src/statistics/social/social_stats_types.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_SOCIAL_STATS_TYPES_H__ +#define __CONTEXT_SOCIAL_STATS_TYPES_H__ + +#include + +#define SOCIAL_HISTORY_PRIV "callhistory.read" +#define SOCIAL_SUBJ_FREQ_ADDRESS "stats/contact/often" +#define SOCIAL_SUBJ_FREQUENCY "stats/contact/frequency" + +#define SOCIAL_TABLE_CONTACT_LOG "Log_Contact" +#define SOCIAL_TABLE_CONTACT_LOG_COLUMNS \ + "Address TEXT NOT NULL, PLogType INTEGER NOT NULL, " \ + "Duration INTEGER NOT NULL DEFAULT 0, " \ + "UTC TIMESTAMP DEFAULT (strftime('%s', 'now')), " \ + "LocalTime TIMESTAMP DEFAULT (strftime('%s', 'now', 'localtime'))" + +#define SOCIAL_TEMP_CONTACT_FREQ "Temp_ContactFreq" +#define SOCIAL_TEMP_CONTACT_FREQ_SQL \ + "CREATE TABLE IF NOT EXISTS " SOCIAL_TEMP_CONTACT_FREQ \ + " (Address TEXT NOT NULL UNIQUE, TotalCount INTEGER DEFAULT 0);" + +#define SOCIAL_COMMUNICATION_TYPE "CommunicationType" +#define SOCIAL_ADDRESS "Address" +#define SOCIAL_PHONE_LOG_TYPE "PLogType" +#define TIME_DIFFERENCE "TimeDIff" + +enum _social_comm_type_e { + SOCIAL_COMMUNICATION_TYPE_CALL = 1, + SOCIAL_COMMUNICATION_TYPE_MESSAGE, + SOCIAL_COMMUNICATION_TYPE_ALL +}; + +#endif diff --git a/src/statistics/statistics_context_provider.cpp b/src/statistics/statistics_context_provider.cpp new file mode 100644 index 0000000..62fea4d --- /dev/null +++ b/src/statistics/statistics_context_provider.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "app/app_stats_provider.h" + +#ifdef _MOBILE_ +#include "media/media_stats_provider.h" +#include "social/social_stats_provider.h" +#endif + +#ifdef _TV_ +#include "media/media_stats_provider.h" +#endif + +template +void register_provider(const char *subject, const char *privilege) +{ + if (!provider::is_supported(subject)) + return; + + ctx::context_provider_info provider_info(provider::create, provider::destroy, NULL, privilege); + ctx::context_manager::register_provider(subject, provider_info); +} + +EXTAPI bool ctx::init_statistics_context_provider() +{ + app_statistics_provider::create(NULL); + register_provider(APP_SUBJ_RECENTLY_USED, APP_HISTORY_PRIV); + register_provider(APP_SUBJ_FREQUENTLY_USED, APP_HISTORY_PRIV); + register_provider(APP_SUBJ_RARELY_USED, APP_HISTORY_PRIV); + register_provider(APP_SUBJ_PEAK_TIME, APP_HISTORY_PRIV); + register_provider(APP_SUBJ_COMMON_SETTING, APP_HISTORY_PRIV); + register_provider(APP_SUBJ_FREQUENCY, APP_HISTORY_PRIV); + app_statistics_provider::submit_trigger_item(); + +#ifdef _MOBILE_ + media_statistics_provider::create(NULL); + register_provider(MEDIA_SUBJ_PEAK_TIME_FOR_MUSIC, MEDIA_HISTORY_PRIV); + register_provider(MEDIA_SUBJ_PEAK_TIME_FOR_VIDEO, MEDIA_HISTORY_PRIV); + register_provider(MEDIA_SUBJ_COMMON_SETTING_FOR_MUSIC, MEDIA_HISTORY_PRIV); + register_provider(MEDIA_SUBJ_COMMON_SETTING_FOR_VIDEO, MEDIA_HISTORY_PRIV); + register_provider(MEDIA_SUBJ_MUSIC_FREQUENCY, MEDIA_HISTORY_PRIV); + register_provider(MEDIA_SUBJ_VIDEO_FREQUENCY, MEDIA_HISTORY_PRIV); + media_statistics_provider::submit_trigger_item(); + + social_statistics_provider::create(NULL); + register_provider(SOCIAL_SUBJ_FREQ_ADDRESS, SOCIAL_HISTORY_PRIV); + register_provider(SOCIAL_SUBJ_FREQUENCY, SOCIAL_HISTORY_PRIV); + social_statistics_provider::submit_trigger_item(); +#endif + +#ifdef _TV_ + media_statistics_provider::create(NULL); + register_provider(MEDIA_SUBJ_PEAK_TIME_FOR_MUSIC, MEDIA_HISTORY_PRIV); + register_provider(MEDIA_SUBJ_PEAK_TIME_FOR_VIDEO, MEDIA_HISTORY_PRIV); + register_provider(MEDIA_SUBJ_COMMON_SETTING_FOR_MUSIC, MEDIA_HISTORY_PRIV); + register_provider(MEDIA_SUBJ_COMMON_SETTING_FOR_VIDEO, MEDIA_HISTORY_PRIV); + register_provider(MEDIA_SUBJ_MUSIC_FREQUENCY, MEDIA_HISTORY_PRIV); + register_provider(MEDIA_SUBJ_VIDEO_FREQUENCY, MEDIA_HISTORY_PRIV); + media_statistics_provider::submit_trigger_item(); +#endif + + return true; +}