📄 cap.c
字号:
/* * Contact Availability Prediction plugin for Purple * * Copyright (C) 2006 Geoffrey Foster. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */#include "cap.h"static void generate_prediction(CapStatistics *statistics) { if(statistics->buddy) { if(statistics->prediction == NULL) statistics->prediction = g_malloc(sizeof(CapPrediction)); statistics->prediction->probability = generate_prediction_for(statistics->buddy); statistics->prediction->generated_at = time(NULL); }}static double generate_prediction_for(PurpleBuddy *buddy) { double prediction = 1.0f; gboolean generated = FALSE; gchar *buddy_name = buddy->name; const gchar *protocol_id = purple_account_get_protocol_id(buddy->account); const gchar *account_id = purple_account_get_username(buddy->account); const gchar *status_id = purple_status_get_id(get_status_for(buddy)); time_t t = time(NULL); struct tm *current_time = localtime(&t); int current_minute = current_time->tm_min + current_time->tm_hour * 60; int threshold = purple_prefs_get_int("/plugins/gtk/cap/threshold"); int min_minute = (current_minute - threshold) % 1440; int max_minute = (current_minute + threshold) % 1440; char *sql; sqlite3_stmt *stmt = NULL; const char *tail = NULL; int rc; sql = sqlite3_mprintf("select sum(success_count) as successes, sum(failed_count) as failures " "from cap_msg_count where " "buddy=%Q and account=%Q and protocol=%Q and minute_val>=%d and minute_val<=%d;", buddy_name, account_id, protocol_id, min_minute, max_minute); rc = sqlite3_prepare(_db, sql, -1, &stmt, &tail); if(rc == SQLITE_OK) { int successes = 0; int failures = 0; if(stmt != NULL) { if(sqlite3_step(stmt) == SQLITE_ROW) { successes = sqlite3_column_int(stmt, 0); failures = sqlite3_column_int(stmt, 1); if(failures + successes > 0) { prediction *= ((double)successes/((double)(successes+failures))); generated = TRUE; } } sqlite3_finalize(stmt); } } sqlite3_free(sql); sql = sqlite3_mprintf("select sum(success_count) as successes, sum(failed_count) as failures " "from cap_status_count where " "buddy=%Q and account=%Q and protocol=%Q and status=%Q;", buddy_name, account_id, protocol_id, status_id); rc = sqlite3_prepare(_db, sql, -1, &stmt, &tail); if(rc == SQLITE_OK) { int successes = 0; int failures = 0; if(stmt != NULL) { if(sqlite3_step(stmt) == SQLITE_ROW) { successes = sqlite3_column_int(stmt, 0); failures = sqlite3_column_int(stmt, 1); if(failures + successes > 0) { prediction *= ((double)successes/((double)(successes+failures))); generated = TRUE; } } sqlite3_finalize(stmt); } } sqlite3_free(sql); if(strcmp(purple_status_get_id(get_status_for(buddy)), "offline") == 0) { /* This is kind of stupid, change it. */ if(prediction == 1.0f) prediction = 0.0f; } if(generated) return prediction; else return -1;}static CapStatistics * get_stats_for(PurpleBuddy *buddy) { gchar *buddy_name; CapStatistics *stats; g_return_val_if_fail(buddy != NULL, NULL); buddy_name = g_strdup(buddy->name); stats = g_hash_table_lookup(_buddy_stats, buddy_name); if(!stats) { stats = g_malloc(sizeof(CapStatistics)); stats->last_message = -1; stats->last_message_status_id = NULL; stats->last_status_id = NULL; stats->prediction = NULL; g_hash_table_insert(_buddy_stats, buddy_name, stats); stats->buddy = buddy; stats->last_seen = -1; stats->last_status_id = ""; } else { g_free(buddy_name); } generate_prediction(stats); return stats;}static void destroy_stats(gpointer data) { CapStatistics *stats = data; g_free(stats->prediction); /* g_free(stats->hourly_usage); */ /* g_free(stats->daily_usage); */ if (stats->timeout_source_id != 0) g_source_remove(stats->timeout_source_id); g_free(stats);}static voidinsert_cap_msg_count_success(const char *buddy_name, const char *account, const char *protocol, int minute) { int rc; sqlite3_stmt *stmt; const char *tail; char *sql_select = sqlite3_mprintf("SELECT * FROM cap_msg_count WHERE " "buddy=%Q AND account=%Q AND protocol=%Q AND minute_val=%d;", buddy_name, account, protocol, minute); char *sql_ins_up = NULL; purple_debug_info("cap", "%s\n", sql_select); sqlite3_prepare(_db, sql_select, -1, &stmt, &tail); rc = sqlite3_step(stmt); if(rc == SQLITE_DONE) { sql_ins_up = sqlite3_mprintf("INSERT INTO cap_msg_count VALUES (%Q, %Q, %Q, %d, %d, %d);", buddy_name, account, protocol, minute, 1, 0); } else if(rc == SQLITE_ROW) { sql_ins_up = sqlite3_mprintf("UPDATE cap_msg_count SET success_count=success_count+1 WHERE " "buddy=%Q AND account=%Q AND protocol=%Q AND minute_val=%d;", buddy_name, account, protocol, minute); } else { purple_debug_info("cap", "%d\n", rc); sqlite3_finalize(stmt); sqlite3_free(sql_select); return; } sqlite3_finalize(stmt); sqlite3_free(sql_select); sqlite3_exec(_db, sql_ins_up, NULL, NULL, NULL); sqlite3_free(sql_ins_up);}static voidinsert_cap_status_count_success(const char *buddy_name, const char *account, const char *protocol, const char *status_id) { int rc; sqlite3_stmt *stmt; const char *tail; char *sql_select = sqlite3_mprintf("SELECT * FROM cap_status_count WHERE " "buddy=%Q AND account=%Q AND protocol=%Q AND status=%Q;", buddy_name, account, protocol, status_id); char *sql_ins_up = NULL; purple_debug_info("cap", "%s\n", sql_select); sqlite3_prepare(_db, sql_select, -1, &stmt, &tail); rc = sqlite3_step(stmt); if(rc == SQLITE_DONE) { sql_ins_up = sqlite3_mprintf("INSERT INTO cap_status_count VALUES (%Q, %Q, %Q, %Q, %d, %d);", buddy_name, account, protocol, status_id, 1, 0); } else if(rc == SQLITE_ROW) { sql_ins_up = sqlite3_mprintf("UPDATE cap_status_count SET success_count=success_count+1 WHERE " "buddy=%Q AND account=%Q AND protocol=%Q AND status=%Q;", buddy_name, account, protocol, status_id); } else { purple_debug_info("cap", "%d\n", rc); sqlite3_finalize(stmt); sqlite3_free(sql_select); return; } sqlite3_finalize(stmt); sqlite3_free(sql_select); sqlite3_exec(_db, sql_ins_up, NULL, NULL, NULL); sqlite3_free(sql_ins_up);}static voidinsert_cap_msg_count_failed(const char *buddy_name, const char *account, const char *protocol, int minute) { int rc; sqlite3_stmt *stmt; const char *tail; char *sql_select = sqlite3_mprintf("SELECT * FROM cap_msg_count WHERE " "buddy=%Q AND account=%Q AND protocol=%Q AND minute_val=%d;", buddy_name, account, protocol, minute); char *sql_ins_up = NULL; purple_debug_info("cap", "%s\n", sql_select); sqlite3_prepare(_db, sql_select, -1, &stmt, &tail); rc = sqlite3_step(stmt); if(rc == SQLITE_DONE) { sql_ins_up = sqlite3_mprintf("INSERT INTO cap_msg_count VALUES (%Q, %Q, %Q, %d, %d, %d);", buddy_name, account, protocol, minute, 0, 1); } else if(rc == SQLITE_ROW) { sql_ins_up = sqlite3_mprintf("UPDATE cap_msg_count SET failed_count=failed_count+1 WHERE " "buddy=%Q AND account=%Q AND protocol=%Q AND minute_val=%d;", buddy_name, account, protocol, minute); } else { purple_debug_info("cap", "%d\n", rc); sqlite3_finalize(stmt); sqlite3_free(sql_select); return; } sqlite3_finalize(stmt); sqlite3_free(sql_select); sqlite3_exec(_db, sql_ins_up, NULL, NULL, NULL); sqlite3_free(sql_ins_up);}static voidinsert_cap_status_count_failed(const char *buddy_name, const char *account, const char *protocol, const char *status_id) { int rc; sqlite3_stmt *stmt; const char *tail; char *sql_select = sqlite3_mprintf("SELECT * FROM cap_status_count WHERE " "buddy=%Q AND account=%Q AND protocol=%Q AND status=%Q;", buddy_name, account, protocol, status_id); char *sql_ins_up = NULL; purple_debug_info("cap", "%s\n", sql_select); sqlite3_prepare(_db, sql_select, -1, &stmt, &tail); rc = sqlite3_step(stmt); if(rc == SQLITE_DONE) { sql_ins_up = sqlite3_mprintf("INSERT INTO cap_status_count VALUES (%Q, %Q, %Q, %Q, %d, %d);", buddy_name, account, protocol, status_id, 0, 1); } else if(rc == SQLITE_ROW) { sql_ins_up = sqlite3_mprintf("UPDATE cap_status_count SET failed_count=failed_count+1 WHERE " "buddy=%Q AND account=%Q AND protocol=%Q AND status=%Q;", buddy_name, account, protocol, status_id); } else { purple_debug_info("cap", "%d\n", rc); sqlite3_finalize(stmt); sqlite3_free(sql_select); return; } sqlite3_finalize(stmt); sqlite3_free(sql_select); sqlite3_exec(_db, sql_ins_up, NULL, NULL, NULL); sqlite3_free(sql_ins_up);}static void insert_cap_success(CapStatistics *stats) { gchar *buddy_name = stats->buddy->name; const gchar *protocol_id = purple_account_get_protocol_id(stats->buddy->account); const gchar *account_id = purple_account_get_username(stats->buddy->account); const gchar *status_id = (stats->last_message_status_id) ? stats->last_message_status_id : purple_status_get_id(get_status_for(stats->buddy)); struct tm *current_time; int minute; if(stats->last_message == -1) { time_t now = time(NULL); current_time = localtime(&now); } else { current_time = localtime(&stats->last_message); } minute = current_time->tm_min + current_time->tm_hour * 60; insert_cap_msg_count_success(buddy_name, account_id, protocol_id, minute); insert_cap_status_count_success(buddy_name, account_id, protocol_id, status_id); stats->last_message = -1; stats->last_message_status_id = NULL;}static void insert_cap_failure(CapStatistics *stats) { gchar *buddy_name = stats->buddy->name; const gchar *protocol_id = purple_account_get_protocol_id(stats->buddy->account); const gchar *account_id = purple_account_get_username(stats->buddy->account); const gchar *status_id = (stats->last_message_status_id) ? stats->last_message_status_id :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -