18
18
// Thanks to Synapse Developers for this class
22
namespace Slingshot.Backend {
24
public class RelevancyService : Object {
26
private Zeitgeist.Log zg_log;
27
private Zeitgeist.DataSourceRegistry zg_dsr;
28
private Gee.HashMap<string, int> app_popularity;
29
private bool has_datahub_gio_module = false;
31
private const float MULTIPLIER = 65535.0f;
33
public signal void update_complete ();
35
public RelevancyService () {
37
zg_log = new Zeitgeist.Log ();
38
app_popularity = new Gee.HashMap<string, int> ();
40
refresh_popularity ();
41
check_data_sources.begin ();
43
Timeout.add_seconds (60*30, refresh_popularity);
47
private async void check_data_sources () {
49
zg_dsr = new Zeitgeist.DataSourceRegistry ();
20
public class Slingshot.Backend.RelevancyService : Object {
22
private Zeitgeist.Log zg_log;
23
private Zeitgeist.DataSourceRegistry zg_dsr;
24
private Gee.HashMap<string, int> app_popularity;
25
private bool has_datahub_gio_module = false;
27
private const float MULTIPLIER = 65535.0f;
29
public signal void update_complete ();
31
public RelevancyService () {
33
zg_log = new Zeitgeist.Log ();
34
app_popularity = new Gee.HashMap<string, int> ();
36
refresh_popularity ();
37
check_data_sources.begin ();
39
Timeout.add_seconds (60*30, refresh_popularity);
43
private async void check_data_sources () {
45
zg_dsr = new Zeitgeist.DataSourceRegistry ();
50
47
var ptr_arr = yield zg_dsr.get_data_sources (null);
52
for (uint i=0; i < ptr_arr.len; i++) {
49
for (uint i=0; i < ptr_arr.length; i++) {
54
51
unowned Zeitgeist.DataSource ds;
55
ds = (Zeitgeist.DataSource) ptr_arr.index (i);
56
if (ds.get_unique_id () == "com.zeitgeist-project,datahub,gio-launch-listener"
57
&& ds.is_enabled ()) {
52
ds = (Zeitgeist.DataSource) ptr_arr.get (i);
53
if (ds.unique_id == "com.zeitgeist-project,datahub,gio-launch-listener"
54
&& ds.enabled == true) {
59
56
has_datahub_gio_module = true;
65
public bool refresh_popularity () {
65
public bool refresh_popularity () {
67
load_application_relevancies.begin ();
71
private void reload_relevancies () {
73
Idle.add_full (Priority.LOW, () => {
67
74
load_application_relevancies.begin ();
71
private void reload_relevancies () {
73
Idle.add_full (Priority.LOW, () => {
74
load_application_relevancies.begin ();
79
private async void load_application_relevancies () {
81
Idle.add (load_application_relevancies.callback, Priority.HIGH);
84
int64 end = Zeitgeist.Timestamp.now ();
85
int64 start = end - Zeitgeist.Timestamp.WEEK * 4;
86
Zeitgeist.TimeRange tr = new Zeitgeist.TimeRange (start, end);
88
var event = new Zeitgeist.Event ();
89
event.set_interpretation ("!" + ZG_LEAVE_EVENT);
90
var subject = new Zeitgeist.Subject ();
91
subject.set_interpretation (NFO_SOFTWARE);
92
subject.set_uri ("application://*");
93
event.add_subject (subject);
95
var ptr_arr = new PtrArray ();
98
Zeitgeist.ResultSet rs;
102
rs = yield zg_log.find_events (tr, (owned) ptr_arr,
103
Zeitgeist.StorageState.ANY,
105
Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS,
108
app_popularity.clear ();
109
uint size = rs.size ();
112
// Zeitgeist (0.6) doesn't have any stats API, so let's approximate
114
foreach (Zeitgeist.Event e in rs) {
116
if (e.num_subjects () <= 0) continue;
117
Zeitgeist.Subject s = e.get_subject (0);
119
float power = index / (size * 2) + 0.5f; // linearly <0.5, 1.0>
120
float relevancy = 1.0f / Math.powf (index + 1, power);
121
app_popularity[s.get_uri ()] = (int)(relevancy * MULTIPLIER);
125
} catch (Error err) {
126
warning ("%s", err.message);
131
public float get_app_popularity (string desktop_id) {
133
var id = "application://" + desktop_id;
135
if (app_popularity.has_key(id)) {
136
return app_popularity[id] / MULTIPLIER;
142
public void app_launched (App app) {
144
string app_uri = null;
145
if (app.desktop_id != null) {
146
app_uri = "application://" + app.desktop_id;
149
push_app_launch (app_uri, app.name);
152
reload_relevancies ();
155
private void push_app_launch (string app_uri, string? display_name) {
157
message ("Pushing launch event: %s [%s]", app_uri, display_name);
158
var event = new Zeitgeist.Event ();
159
var subject = new Zeitgeist.Subject ();
161
event.set_actor ("application://synapse.desktop");
162
event.set_interpretation (Zeitgeist.ZG_ACCESS_EVENT);
163
event.set_manifestation (Zeitgeist.ZG_USER_ACTIVITY);
164
event.add_subject (subject);
166
subject.set_uri (app_uri);
167
subject.set_interpretation (Zeitgeist.NFO_SOFTWARE);
168
subject.set_manifestation (Zeitgeist.NFO_SOFTWARE_ITEM);
169
subject.set_mimetype ("application/x-desktop");
170
subject.set_text (display_name);
172
zg_log.insert_events_no_reply (event, null);
79
private async void load_application_relevancies () {
81
Idle.add (load_application_relevancies.callback, Priority.HIGH);
84
int64 end = Zeitgeist.Timestamp.from_now ();
85
int64 start = end - Zeitgeist.Timestamp.WEEK * 4;
86
Zeitgeist.TimeRange tr = new Zeitgeist.TimeRange (start, end);
88
var event = new Zeitgeist.Event ();
89
event.interpretation = "!" + Zeitgeist.ZG.LEAVE_EVENT;
90
var subject = new Zeitgeist.Subject ();
91
subject.interpretation = Zeitgeist.NFO.SOFTWARE;
92
subject.uri = "application://*";
93
event.add_subject (subject);
95
var ptr_arr = new GLib.GenericArray<Zeitgeist.Event> ();
98
Zeitgeist.ResultSet rs;
102
rs = yield zg_log.find_events (tr, (owned) ptr_arr,
103
Zeitgeist.StorageState.ANY,
105
Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS,
108
app_popularity.clear ();
109
uint size = rs.size ();
112
// Zeitgeist (0.6) doesn't have any stats API, so let's approximate
114
foreach (Zeitgeist.Event e in rs) {
116
if (e.num_subjects () <= 0) continue;
117
Zeitgeist.Subject s = e.get_subject (0);
119
float power = index / (size * 2) + 0.5f; // linearly <0.5, 1.0>
120
float relevancy = 1.0f / Math.powf (index + 1, power);
121
app_popularity[s.uri] = (int)(relevancy * MULTIPLIER);
125
} catch (Error err) {
126
warning ("%s", err.message);
131
public float get_app_popularity (string desktop_id) {
133
var id = "application://" + desktop_id;
135
if (app_popularity.has_key(id)) {
136
return app_popularity[id] / MULTIPLIER;
142
public void app_launched (App app) {
144
string app_uri = null;
145
if (app.desktop_id != null) {
146
app_uri = "application://" + app.desktop_id;
149
push_app_launch (app_uri, app.name);
152
reload_relevancies ();
155
private void push_app_launch (string app_uri, string? display_name) {
157
message ("Pushing launch event: %s [%s]", app_uri, display_name);
158
var event = new Zeitgeist.Event ();
159
var subject = new Zeitgeist.Subject ();
161
event.actor = "application://synapse.desktop";
162
event.interpretation = Zeitgeist.ZG.ACCESS_EVENT;
163
event.manifestation = Zeitgeist.ZG.USER_ACTIVITY;
164
event.add_subject (subject);
166
subject.uri = app_uri;
167
subject.interpretation = Zeitgeist.NFO.SOFTWARE;
168
subject.manifestation = Zeitgeist.NFO.SOFTWARE_ITEM;
169
subject.mimetype = "application/x-desktop";
170
subject.text = display_name;
171
var ptr_arr = new GLib.GenericArray<Zeitgeist.Event> ();
175
zg_log.insert_events_no_reply (ptr_arr);
177
critical (e.message);
b'\\ No newline at end of file'