chore: remove legacy libtikker static library and simplify Makefile build targets

This commit is contained in:
2025-12-05 16:08:50 +00:00
parent 18cd67566d
commit 57e32c5769
32 changed files with 986 additions and 2416 deletions
-36
View File
@@ -1,36 +0,0 @@
CC ?= gcc
CFLAGS ?= -Wall -Wextra -pedantic -std=c11 -O2
CFLAGS += -I. -I./include -I../third_party -fPIC
LIB_DIR ?= ../../build/lib
SRC_DIR := src
OBJ_DIR := .obj
LIB_TARGET := $(LIB_DIR)/libtikker.a
SOURCES := $(wildcard $(SRC_DIR)/*.c)
OBJECTS := $(SOURCES:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
.PHONY: all clean
all: $(LIB_TARGET)
$(OBJ_DIR):
@mkdir -p $(OBJ_DIR)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
@echo "Compiling $<..."
@$(CC) $(CFLAGS) -c $< -o $@
$(LIB_TARGET): $(OBJECTS) | $(LIB_DIR)
@mkdir -p $(LIB_DIR)
@echo "Creating static library $(LIB_TARGET)..."
@ar rcs $@ $(OBJECTS)
@echo "✓ libtikker.a created"
$(LIB_DIR):
@mkdir -p $(LIB_DIR)
clean:
@rm -rf $(OBJ_DIR)
@rm -f $(LIB_TARGET)
@echo "✓ libtikker cleaned"
-72
View File
@@ -1,72 +0,0 @@
#ifndef TIKKER_AGGREGATOR_H
#define TIKKER_AGGREGATOR_H
#include <stdint.h>
#include <sqlite3.h>
#include <tikker.h>
typedef struct {
char date[11];
uint64_t total;
} tikker_daily_entry_t;
typedef struct {
char date[11];
uint32_t hour;
uint64_t presses;
} tikker_hourly_entry_t;
typedef struct {
char week[8];
uint64_t total;
} tikker_weekly_entry_t;
typedef enum {
TIKKER_WEEKDAY_SUNDAY = 0,
TIKKER_WEEKDAY_MONDAY = 1,
TIKKER_WEEKDAY_TUESDAY = 2,
TIKKER_WEEKDAY_WEDNESDAY = 3,
TIKKER_WEEKDAY_THURSDAY = 4,
TIKKER_WEEKDAY_FRIDAY = 5,
TIKKER_WEEKDAY_SATURDAY = 6
} tikker_weekday_t;
int tikker_aggregate_daily(sqlite3 *db,
tikker_daily_entry_t **entries,
int *count);
int tikker_aggregate_hourly(sqlite3 *db,
const char *date,
tikker_hourly_entry_t **entries,
int *count);
int tikker_aggregate_weekly(sqlite3 *db,
tikker_weekly_entry_t **entries,
int *count);
int tikker_aggregate_weekday(sqlite3 *db,
tikker_weekday_stat_t **entries,
int *count);
int tikker_get_peak_hour(sqlite3 *db,
const char *date,
uint32_t *hour,
uint64_t *presses);
int tikker_get_peak_day(sqlite3 *db,
char *date,
uint64_t *presses);
int tikker_get_daily_average(sqlite3 *db,
uint64_t *avg_presses,
int *num_days);
uint64_t tikker_calculate_total_presses(sqlite3 *db);
uint64_t tikker_calculate_total_releases(sqlite3 *db);
uint64_t tikker_calculate_total_repeats(sqlite3 *db);
void tikker_free_daily_entries(tikker_daily_entry_t *entries, int count);
void tikker_free_hourly_entries(tikker_hourly_entry_t *entries, int count);
void tikker_free_weekly_entries(tikker_weekly_entry_t *entries, int count);
#endif
-37
View File
@@ -1,37 +0,0 @@
#ifndef TIKKER_CONFIG_H
#define TIKKER_CONFIG_H
#define TIKKER_VERSION "2.0.0-enterprise"
#define TIKKER_VERSION_MAJOR 2
#define TIKKER_VERSION_MINOR 0
#define TIKKER_VERSION_PATCH 0
#define TIKKER_DEFAULT_DB_PATH "tikker.db"
#define TIKKER_DEFAULT_LOGS_DIR "logs_plain"
#define TIKKER_DEFAULT_CACHE_DIR "tikker_cache"
#define TIKKER_DEFAULT_TAGS_DB "tags.db"
#define TIKKER_DEFAULT_LOGS_DB "logs.db"
#define TIKKER_TEXT_BUFFER_INITIAL 4096
#define TIKKER_TEXT_BUFFER_MAX (1024 * 1024 * 100)
#define TIKKER_MAX_KEYCODE 256
#define TIKKER_MAX_KEY_NAME 32
#define TIKKER_MAX_DATE_STR 11
#define TIKKER_MAX_PATH 4096
#define TIKKER_WORD_MIN_LENGTH 2
#define TIKKER_WORD_MAX_LENGTH 255
#define TIKKER_TOP_WORDS_DEFAULT 10
#define TIKKER_TOP_KEYS_DEFAULT 10
#define TIKKER_SHIFT_KEYCODE_LSHIFT 42
#define TIKKER_SHIFT_KEYCODE_RSHIFT 54
#define TIKKER_KEY_SPACE 57
#define TIKKER_ENABLE_PROFILING 0
#define TIKKER_ENABLE_DEBUG 0
#endif
-27
View File
@@ -1,27 +0,0 @@
#ifndef TIKKER_DATABASE_H
#define TIKKER_DATABASE_H
#include <stddef.h>
#include <sqlite3.h>
typedef struct {
const char *db_path;
sqlite3 *conn;
int flags;
} tikker_db_t;
tikker_db_t* tikker_db_open(const char *path);
void tikker_db_close(tikker_db_t *db);
int tikker_db_init_schema(tikker_db_t *db);
int tikker_db_execute(tikker_db_t *db, const char *sql);
int tikker_db_query(tikker_db_t *db, const char *sql,
int (*callback)(void*, int, char**, char**),
void *arg);
int tikker_db_begin_transaction(tikker_db_t *db);
int tikker_db_commit_transaction(tikker_db_t *db);
int tikker_db_rollback_transaction(tikker_db_t *db);
int tikker_db_vacuum(tikker_db_t *db);
int tikker_db_pragma(tikker_db_t *db, const char *pragma, char *result, size_t result_size);
int tikker_db_integrity_check(tikker_db_t *db);
#endif
-33
View File
@@ -1,33 +0,0 @@
#ifndef TIKKER_DECODER_H
#define TIKKER_DECODER_H
#include <stddef.h>
#include <stdint.h>
#define TIKKER_KEY_SPACE 57
#define TIKKER_KEY_ENTER 28
#define TIKKER_KEY_TAB 15
#define TIKKER_KEY_BACKSPACE 14
#define TIKKER_KEY_LSHIFT 42
#define TIKKER_KEY_RSHIFT 54
typedef struct {
char *data;
size_t capacity;
size_t length;
} tikker_text_buffer_t;
tikker_text_buffer_t* tikker_text_buffer_create(size_t initial_capacity);
void tikker_text_buffer_free(tikker_text_buffer_t *buf);
int tikker_text_buffer_append(tikker_text_buffer_t *buf, const char *data, size_t len);
int tikker_text_buffer_append_char(tikker_text_buffer_t *buf, char c);
void tikker_text_buffer_pop(tikker_text_buffer_t *buf);
int tikker_keycode_to_char(uint32_t keycode, int shift_active, char *out_char);
const char* tikker_keycode_to_name(uint32_t keycode);
int tikker_decode_file(const char *input_path, const char *output_path);
int tikker_decode_buffer(const char *input, size_t input_len,
tikker_text_buffer_t *output);
#endif
-57
View File
@@ -1,57 +0,0 @@
#ifndef TIKKER_INDEXER_H
#define TIKKER_INDEXER_H
#include <stdint.h>
#include <sqlite3.h>
typedef struct {
const char *word;
uint64_t count;
int rank;
} tikker_word_entry_t;
typedef struct {
sqlite3 *db;
int word_count;
uint64_t total_words;
} tikker_word_index_t;
tikker_word_index_t* tikker_word_index_open(const char *db_path);
void tikker_word_index_close(tikker_word_index_t *index);
int tikker_word_index_reset(tikker_word_index_t *index);
int tikker_index_text_file(const char *file_path,
const char *db_path);
int tikker_index_directory(const char *dir_path,
const char *db_path);
int tikker_word_index_add(tikker_word_index_t *index,
const char *word,
uint64_t count);
int tikker_word_index_commit(tikker_word_index_t *index);
int tikker_word_get_frequency(const char *db_path,
const char *word,
uint64_t *count);
int tikker_word_get_rank(const char *db_path,
const char *word,
int *rank,
uint64_t *count);
int tikker_word_get_top(const char *db_path,
int limit,
tikker_word_entry_t **entries,
int *count);
int tikker_word_get_total_count(const char *db_path,
uint64_t *total);
int tikker_word_get_unique_count(const char *db_path,
int *count);
void tikker_word_entries_free(tikker_word_entry_t *entries, int count);
#endif
-19
View File
@@ -1,19 +0,0 @@
#ifndef TIKKER_REPORT_H
#define TIKKER_REPORT_H
#include <stddef.h>
#include <sqlite3.h>
typedef struct {
char *title;
char *data;
size_t data_size;
} tikker_report_t;
int tikker_merge_text_files(const char *input_dir,
const char *pattern,
const char *output_path);
void tikker_report_free(tikker_report_t *report);
#endif
-138
View File
@@ -1,138 +0,0 @@
#ifndef TIKKER_H
#define TIKKER_H
#include <stdint.h>
#include <time.h>
#include <sqlite3.h>
#include <stddef.h>
#define TIKKER_SUCCESS 0
#define TIKKER_ERROR_DB -1
#define TIKKER_ERROR_MEMORY -2
#define TIKKER_ERROR_IO -3
#define TIKKER_ERROR_INVALID -4
#define TIKKER_ERROR_NOT_FOUND -5
typedef struct {
sqlite3 *db;
const char *db_path;
uint32_t flags;
} tikker_context_t;
typedef struct {
const char *word;
uint64_t count;
float percentage;
} tikker_word_stat_t;
typedef struct {
uint32_t keycode;
const char *key_name;
uint64_t count;
} tikker_key_stat_t;
typedef struct {
char date[11];
uint64_t total_presses;
uint64_t total_releases;
uint64_t total_repeats;
} tikker_daily_stat_t;
typedef struct {
uint32_t hour;
uint64_t presses;
} tikker_hourly_stat_t;
typedef struct {
char weekday[10];
uint64_t presses;
} tikker_weekday_stat_t;
typedef struct {
double decode_time;
double index_time;
double aggregate_time;
uint64_t records_processed;
} tikker_perf_metrics_t;
tikker_context_t* tikker_open(const char *db_path);
void tikker_close(tikker_context_t *ctx);
int tikker_init_schema(tikker_context_t *ctx);
int tikker_get_version(char *buffer, size_t size);
int tikker_get_daily_stats(tikker_context_t *ctx,
tikker_daily_stat_t **stats,
int *count);
int tikker_get_hourly_stats(tikker_context_t *ctx,
const char *date,
tikker_hourly_stat_t **stats,
int *count);
int tikker_get_weekday_stats(tikker_context_t *ctx,
tikker_weekday_stat_t **stats,
int *count);
int tikker_get_top_words(tikker_context_t *ctx,
int limit,
tikker_word_stat_t **words,
int *count);
int tikker_get_top_keys(tikker_context_t *ctx,
int limit,
tikker_key_stat_t **keys,
int *count);
int tikker_get_date_range(tikker_context_t *ctx,
char *min_date,
char *max_date);
int tikker_get_event_counts(tikker_context_t *ctx,
uint64_t *pressed,
uint64_t *released,
uint64_t *repeated);
int tikker_decode_keylog(const char *input_file,
const char *output_file);
int tikker_decode_keylog_buffer(const char *input,
size_t input_len,
char **output,
size_t *output_len);
int tikker_index_text_file(const char *file_path,
const char *db_path);
int tikker_index_directory(const char *dir_path,
const char *db_path);
int tikker_get_word_frequency(const char *db_path,
const char *word,
uint64_t *count);
int tikker_get_top_words_from_db(const char *db_path,
int limit,
tikker_word_stat_t **words,
int *count);
int tikker_generate_html_report(tikker_context_t *ctx,
const char *output_file,
const char *graph_dir);
int tikker_generate_json_report(tikker_context_t *ctx,
char **json_output);
int tikker_merge_text_files(const char *input_dir,
const char *pattern,
const char *output_path);
int tikker_get_metrics(tikker_perf_metrics_t *metrics);
void tikker_free_words(tikker_word_stat_t *words, int count);
void tikker_free_keys(tikker_key_stat_t *keys, int count);
void tikker_free_daily_stats(tikker_daily_stat_t *stats, int count);
void tikker_free_hourly_stats(tikker_hourly_stat_t *stats, int count);
void tikker_free_weekday_stats(tikker_weekday_stat_t *stats, int count);
void tikker_free_json(char *json);
#endif
-60
View File
@@ -1,60 +0,0 @@
#ifndef TIKKER_TYPES_H
#define TIKKER_TYPES_H
#include <stdint.h>
#include <stddef.h>
#include <time.h>
typedef enum {
TIKKER_LOG_DEBUG = 0,
TIKKER_LOG_INFO = 1,
TIKKER_LOG_WARN = 2,
TIKKER_LOG_ERROR = 3,
TIKKER_LOG_FATAL = 4
} tikker_log_level_t;
typedef enum {
TIKKER_EVENT_PRESSED = 0,
TIKKER_EVENT_RELEASED = 1,
TIKKER_EVENT_REPEATED = 2
} tikker_event_type_t;
typedef struct {
uint64_t id;
uint32_t keycode;
tikker_event_type_t event;
const char *name;
time_t timestamp;
char character;
} tikker_kevent_t;
typedef struct {
const char *name;
const char *symbol;
uint32_t code;
} tikker_key_mapping_t;
typedef struct {
int year;
int month;
int day;
int hour;
int minute;
int second;
int weekday;
} tikker_datetime_t;
typedef struct {
char *buffer;
size_t capacity;
size_t length;
} tikker_string_t;
tikker_string_t* tikker_string_create(size_t capacity);
void tikker_string_free(tikker_string_t *str);
int tikker_string_append(tikker_string_t *str, const char *data);
int tikker_string_append_char(tikker_string_t *str, char c);
void tikker_string_clear(tikker_string_t *str);
char* tikker_string_cstr(tikker_string_t *str);
#endif
-92
View File
@@ -1,92 +0,0 @@
#include <aggregator.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <sqlite3.h>
int tikker_aggregate_daily(sqlite3 *db,
tikker_daily_entry_t **entries,
int *count) {
if (!db || !entries || !count) return -1;
*entries = NULL;
*count = 0;
return 0;
}
int tikker_aggregate_hourly(sqlite3 *db,
const char *date,
tikker_hourly_entry_t **entries,
int *count) {
if (!db || !date || !entries || !count) return -1;
*entries = NULL;
*count = 0;
return 0;
}
int tikker_aggregate_weekly(sqlite3 *db,
tikker_weekly_entry_t **entries,
int *count) {
if (!db || !entries || !count) return -1;
*entries = NULL;
*count = 0;
return 0;
}
int tikker_aggregate_weekday(sqlite3 *db,
tikker_weekday_stat_t **entries,
int *count) {
if (!db || !entries || !count) return -1;
*entries = NULL;
*count = 0;
return 0;
}
int tikker_get_peak_hour(sqlite3 *db,
const char *date,
uint32_t *hour,
uint64_t *presses) {
if (!db || !date || !hour || !presses) return -1;
return 0;
}
int tikker_get_peak_day(sqlite3 *db,
char *date,
uint64_t *presses) {
if (!db || !date || !presses) return -1;
return 0;
}
int tikker_get_daily_average(sqlite3 *db,
uint64_t *avg_presses,
int *num_days) {
if (!db || !avg_presses || !num_days) return -1;
return 0;
}
uint64_t tikker_calculate_total_presses(sqlite3 *db) {
if (!db) return 0;
return 0;
}
uint64_t tikker_calculate_total_releases(sqlite3 *db) {
if (!db) return 0;
return 0;
}
uint64_t tikker_calculate_total_repeats(sqlite3 *db) {
if (!db) return 0;
return 0;
}
void tikker_free_daily_entries(tikker_daily_entry_t *entries, int count) {
if (entries) free(entries);
}
void tikker_free_hourly_entries(tikker_hourly_entry_t *entries, int count) {
if (entries) free(entries);
}
void tikker_free_weekly_entries(tikker_weekly_entry_t *entries, int count) {
if (entries) free(entries);
}
-89
View File
@@ -1,89 +0,0 @@
#include <database.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
tikker_db_t* tikker_db_open(const char *path) {
if (!path) return NULL;
tikker_db_t *db = malloc(sizeof(tikker_db_t));
if (!db) return NULL;
db->db_path = path;
db->flags = 0;
int ret = sqlite3_open(path, &db->conn);
if (ret != SQLITE_OK) { free(db); return NULL; }
return db;
}
void tikker_db_close(tikker_db_t *db) {
if (!db) return;
if (db->conn) sqlite3_close(db->conn);
free(db);
}
int tikker_db_init_schema(tikker_db_t *db) {
if (!db || !db->conn) return -1;
return 0;
}
int tikker_db_execute(tikker_db_t *db, const char *sql) {
if (!db || !db->conn || !sql) return -1;
char *errmsg = NULL;
int ret = sqlite3_exec(db->conn, sql, NULL, NULL, &errmsg);
if (errmsg) sqlite3_free(errmsg);
return ret == SQLITE_OK ? 0 : -1;
}
int tikker_db_query(tikker_db_t *db, const char *sql,
int (*callback)(void*, int, char**, char**),
void *arg) {
if (!db || !db->conn || !sql) return -1;
char *errmsg = NULL;
int ret = sqlite3_exec(db->conn, sql, callback, arg, &errmsg);
if (errmsg) sqlite3_free(errmsg);
return ret == SQLITE_OK ? 0 : -1;
}
int tikker_db_begin_transaction(tikker_db_t *db) {
if (!db || !db->conn) return -1;
return tikker_db_execute(db, "BEGIN TRANSACTION;");
}
int tikker_db_commit_transaction(tikker_db_t *db) {
if (!db || !db->conn) return -1;
return tikker_db_execute(db, "COMMIT;");
}
int tikker_db_rollback_transaction(tikker_db_t *db) {
if (!db || !db->conn) return -1;
return tikker_db_execute(db, "ROLLBACK;");
}
int tikker_db_vacuum(tikker_db_t *db) {
if (!db || !db->conn) return -1;
return tikker_db_execute(db, "VACUUM;");
}
int tikker_db_pragma(tikker_db_t *db, const char *pragma, char *result, size_t result_size) {
if (!db || !db->conn || !pragma || !result) return -1;
char sql[512];
snprintf(sql, sizeof(sql), "PRAGMA %s", pragma);
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db->conn, sql, -1, &stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(stmt) == SQLITE_ROW) {
const unsigned char *text = sqlite3_column_text(stmt, 0);
if (text) {
snprintf(result, result_size, "%s", (const char *)text);
}
}
sqlite3_finalize(stmt);
return 0;
}
return -1;
}
int tikker_db_integrity_check(tikker_db_t *db) {
if (!db || !db->conn) return -1;
return tikker_db_execute(db, "PRAGMA integrity_check;");
}
-201
View File
@@ -1,201 +0,0 @@
#include <decoder.h>
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static const char *keycode_names[] = {
"NONE", "ESC", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=",
"BACKSPACE", "TAB", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
"[", "]", "ENTER", "L_CTRL", "A", "S", "D", "F", "G", "H", "J", "K",
"L", ";", "'", "`", "L_SHIFT", "\\", "Z", "X", "C", "V", "B", "N", "M",
",", ".", "/", "R_SHIFT", "*", "L_ALT", "SPACE", "CAPSLOCK"
};
tikker_text_buffer_t* tikker_text_buffer_create(size_t initial_capacity) {
tikker_text_buffer_t *buf = malloc(sizeof(tikker_text_buffer_t));
if (!buf) return NULL;
buf->capacity = initial_capacity ? initial_capacity : 4096;
buf->data = malloc(buf->capacity);
if (!buf->data) { free(buf); return NULL; }
buf->length = 0;
return buf;
}
void tikker_text_buffer_free(tikker_text_buffer_t *buf) {
if (!buf) return;
if (buf->data) free(buf->data);
free(buf);
}
int tikker_text_buffer_append(tikker_text_buffer_t *buf, const char *data, size_t len) {
if (!buf || !data) return -1;
if (buf->length + len >= buf->capacity) {
size_t new_capacity = buf->capacity * 2;
while (new_capacity < buf->length + len + 1) new_capacity *= 2;
char *new_data = realloc(buf->data, new_capacity);
if (!new_data) return -1;
buf->data = new_data;
buf->capacity = new_capacity;
}
memcpy(buf->data + buf->length, data, len);
buf->length += len;
buf->data[buf->length] = '\0';
return 0;
}
int tikker_text_buffer_append_char(tikker_text_buffer_t *buf, char c) {
return tikker_text_buffer_append(buf, &c, 1);
}
void tikker_text_buffer_pop(tikker_text_buffer_t *buf) {
if (!buf || buf->length == 0) return;
buf->length--;
buf->data[buf->length] = '\0';
}
int tikker_keycode_to_char(uint32_t keycode, int shift_active, char *out_char) {
if (!out_char) return -1;
if (keycode >= 2 && keycode <= 11) {
char base = '0' + (keycode - 2);
if (shift_active) {
const char *shifted[] = {"!", "@", "#", "$", "%", "^", "&", "*", "(", ")"};
*out_char = shifted[keycode - 2][0];
} else {
*out_char = base;
}
return 0;
}
if (keycode >= 16 && keycode <= 25) {
*out_char = 'a' + (keycode - 16);
if (shift_active) *out_char = (*out_char) - 32;
return 0;
}
if (keycode == TIKKER_KEY_SPACE) { *out_char = ' '; return 0; }
*out_char = '?';
return 1;
}
const char* tikker_keycode_to_name(uint32_t keycode) {
if (keycode < sizeof(keycode_names) / sizeof(keycode_names[0])) return keycode_names[keycode];
return "UNKNOWN";
}
static const char* shift_number_map[] = {
"!", "@", "#", "$", "%", "^", "&", "*", "(", ")"
};
int tikker_decode_buffer(const char *input, size_t input_len,
tikker_text_buffer_t *output) {
if (!input || !output) return -1;
int shift_active = 0;
size_t i = 0;
while (i < input_len) {
if (input[i] == '[') {
size_t j = i + 1;
while (j < input_len && input[j] != ']') j++;
if (j >= input_len) return -1;
size_t token_len = j - i - 1;
char token[256];
if (token_len >= sizeof(token)) return -1;
memcpy(token, input + i + 1, token_len);
token[token_len] = '\0';
if (strcmp(token, "LEFT_SHIFT") == 0 || strcmp(token, "R_SHIFT") == 0) {
shift_active = 1;
} else if (strcmp(token, "BACKSPACE") == 0) {
tikker_text_buffer_pop(output);
} else if (strcmp(token, "TAB") == 0) {
tikker_text_buffer_append_char(output, '\t');
} else if (strcmp(token, "ENTER") == 0) {
tikker_text_buffer_append_char(output, '\n');
} else if (strcmp(token, "UP") == 0 || strcmp(token, "DOWN") == 0 ||
strcmp(token, "LEFT") == 0 || strcmp(token, "RIGHT") == 0) {
} else if (token_len == 1) {
char c = token[0];
if (shift_active) {
if (c >= 'a' && c <= 'z') {
c = c - 32;
} else if (c >= '0' && c <= '9') {
c = shift_number_map[c - '0'][0];
}
shift_active = 0;
} else {
if (c >= 'A' && c <= 'Z') {
c = c + 32;
}
}
tikker_text_buffer_append_char(output, c);
}
i = j + 1;
} else if (input[i] == ' ' || input[i] == '\t' || input[i] == '\n') {
i++;
} else {
i++;
}
}
return 0;
}
int tikker_decode_file(const char *input_path, const char *output_path) {
if (!input_path || !output_path) return -1;
FILE *input_file = fopen(input_path, "r");
if (!input_file) return -1;
fseek(input_file, 0, SEEK_END);
long file_size = ftell(input_file);
fseek(input_file, 0, SEEK_SET);
if (file_size <= 0) {
fclose(input_file);
return -1;
}
char *buffer = malloc(file_size);
if (!buffer) {
fclose(input_file);
return -1;
}
size_t read_bytes = fread(buffer, 1, file_size, input_file);
fclose(input_file);
if (read_bytes != (size_t)file_size) {
free(buffer);
return -1;
}
tikker_text_buffer_t *output_buf = tikker_text_buffer_create(file_size);
if (!output_buf) {
free(buffer);
return -1;
}
int ret = tikker_decode_buffer(buffer, file_size, output_buf);
free(buffer);
if (ret != 0) {
tikker_text_buffer_free(output_buf);
return -1;
}
FILE *output_file = fopen(output_path, "w");
if (!output_file) {
tikker_text_buffer_free(output_buf);
return -1;
}
fwrite(output_buf->data, 1, output_buf->length, output_file);
fclose(output_file);
tikker_text_buffer_free(output_buf);
return 0;
}
-329
View File
@@ -1,329 +0,0 @@
#define _DEFAULT_SOURCE
#include <indexer.h>
#include <database.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <dirent.h>
tikker_word_index_t* tikker_word_index_open(const char *db_path) {
if (!db_path) return NULL;
tikker_word_index_t *index = malloc(sizeof(tikker_word_index_t));
if (!index) return NULL;
int ret = sqlite3_open(db_path, &index->db);
if (ret != SQLITE_OK) { free(index); return NULL; }
index->word_count = 0;
index->total_words = 0;
return index;
}
void tikker_word_index_close(tikker_word_index_t *index) {
if (!index) return;
if (index->db) sqlite3_close(index->db);
free(index);
}
static int is_valid_word_char(char c) {
return isalnum(c) || c == '_';
}
int tikker_word_index_reset(tikker_word_index_t *index) {
if (!index || !index->db) return -1;
sqlite3_exec(index->db, "DROP TABLE IF EXISTS words", NULL, NULL, NULL);
const char *sql = "CREATE TABLE IF NOT EXISTS words ("
"word TEXT NOT NULL PRIMARY KEY,"
"count INTEGER NOT NULL)";
char *errmsg = NULL;
int ret = sqlite3_exec(index->db, sql, NULL, NULL, &errmsg);
if (errmsg) sqlite3_free(errmsg);
if (ret == SQLITE_OK) {
index->word_count = 0;
index->total_words = 0;
return 0;
}
return -1;
}
int tikker_index_text_file(const char *file_path, const char *db_path) {
if (!file_path || !db_path) return -1;
FILE *f = fopen(file_path, "r");
if (!f) return -1;
tikker_word_index_t *index = tikker_word_index_open(db_path);
if (!index) {
fclose(f);
return -1;
}
char word[256];
int word_len = 0;
int c;
while ((c = fgetc(f)) != EOF) {
if (is_valid_word_char(c)) {
if (word_len < (int)sizeof(word) - 1) {
word[word_len++] = tolower(c);
}
} else {
if (word_len > 0) {
word[word_len] = '\0';
tikker_word_index_add(index, word, 1);
word_len = 0;
}
}
}
if (word_len > 0) {
word[word_len] = '\0';
tikker_word_index_add(index, word, 1);
}
fclose(f);
tikker_word_index_commit(index);
tikker_word_index_close(index);
return 0;
}
int tikker_index_directory(const char *dir_path, const char *db_path) {
if (!dir_path || !db_path) return -1;
DIR *dir = opendir(dir_path);
if (!dir) return -1;
tikker_word_index_t *index = tikker_word_index_open(db_path);
if (!index) {
closedir(dir);
return -1;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_REG && strstr(entry->d_name, ".txt")) {
char file_path[1024];
snprintf(file_path, sizeof(file_path), "%s/%s", dir_path, entry->d_name);
FILE *f = fopen(file_path, "r");
if (f) {
char word[256];
int word_len = 0;
int c;
while ((c = fgetc(f)) != EOF) {
if (is_valid_word_char(c)) {
if (word_len < (int)sizeof(word) - 1) {
word[word_len++] = tolower(c);
}
} else {
if (word_len >= 2) {
word[word_len] = '\0';
tikker_word_index_add(index, word, 1);
}
word_len = 0;
}
}
if (word_len >= 2) {
word[word_len] = '\0';
tikker_word_index_add(index, word, 1);
}
fclose(f);
}
}
}
closedir(dir);
tikker_word_index_commit(index);
tikker_word_index_close(index);
return 0;
}
int tikker_word_index_add(tikker_word_index_t *index, const char *word, uint64_t count) {
if (!index || !index->db || !word) return -1;
sqlite3_stmt *stmt;
const char *sql = "INSERT OR IGNORE INTO words (word, count) VALUES (?, 0); "
"UPDATE words SET count = count + ? WHERE word = ?";
if (sqlite3_prepare_v2(index->db, sql, -1, &stmt, NULL) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, word, -1, SQLITE_STATIC);
sqlite3_bind_int64(stmt, 2, count);
sqlite3_bind_text(stmt, 3, word, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) == SQLITE_DONE) {
index->word_count++;
index->total_words += count;
}
sqlite3_finalize(stmt);
return 0;
}
return -1;
}
int tikker_word_index_commit(tikker_word_index_t *index) {
if (!index || !index->db) return -1;
char *errmsg = NULL;
int ret = sqlite3_exec(index->db, "COMMIT", NULL, NULL, &errmsg);
if (errmsg) sqlite3_free(errmsg);
return ret == SQLITE_OK ? 0 : -1;
}
int tikker_word_get_frequency(const char *db_path, const char *word, uint64_t *count) {
if (!db_path || !word || !count) return -1;
sqlite3 *db;
if (sqlite3_open(db_path, &db) != SQLITE_OK) return -1;
sqlite3_stmt *stmt;
const char *sql = "SELECT count FROM words WHERE word = ?";
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, word, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) == SQLITE_ROW) {
*count = sqlite3_column_int64(stmt, 0);
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}
sqlite3_finalize(stmt);
}
*count = 0;
sqlite3_close(db);
return -1;
}
int tikker_word_get_rank(const char *db_path, const char *word, int *rank, uint64_t *count) {
if (!db_path || !word || !rank || !count) return -1;
sqlite3 *db;
if (sqlite3_open(db_path, &db) != SQLITE_OK) return -1;
sqlite3_stmt *stmt;
const char *sql = "SELECT COUNT(*) + 1 FROM words WHERE count > (SELECT count FROM words WHERE word = ?)";
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, word, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) == SQLITE_ROW) {
*rank = sqlite3_column_int(stmt, 0);
sqlite3_finalize(stmt);
tikker_word_get_frequency(db_path, word, count);
sqlite3_close(db);
return 0;
}
sqlite3_finalize(stmt);
}
sqlite3_close(db);
return -1;
}
int tikker_word_get_top(const char *db_path, int limit, tikker_word_entry_t **entries, int *count) {
if (!db_path || limit <= 0 || !entries || !count) return -1;
sqlite3 *db;
if (sqlite3_open(db_path, &db) != SQLITE_OK) return -1;
sqlite3_stmt *stmt;
const char *sql = "SELECT word, count FROM words ORDER BY count DESC LIMIT ?";
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
sqlite3_close(db);
return -1;
}
sqlite3_bind_int(stmt, 1, limit);
int result_count = 0;
tikker_word_entry_t *result = malloc(limit * sizeof(tikker_word_entry_t));
if (!result) {
sqlite3_finalize(stmt);
sqlite3_close(db);
return -1;
}
while (sqlite3_step(stmt) == SQLITE_ROW && result_count < limit) {
const char *word_str = (const char *)sqlite3_column_text(stmt, 0);
uint64_t word_count = sqlite3_column_int64(stmt, 1);
result[result_count].word = strdup(word_str);
result[result_count].count = word_count;
result[result_count].rank = result_count + 1;
result_count++;
}
sqlite3_finalize(stmt);
sqlite3_close(db);
*entries = result;
*count = result_count;
return 0;
}
int tikker_word_get_total_count(const char *db_path, uint64_t *total) {
if (!db_path || !total) return -1;
sqlite3 *db;
if (sqlite3_open(db_path, &db) != SQLITE_OK) return -1;
sqlite3_stmt *stmt;
const char *sql = "SELECT SUM(count) FROM words";
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(stmt) == SQLITE_ROW) {
*total = sqlite3_column_int64(stmt, 0);
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}
sqlite3_finalize(stmt);
}
*total = 0;
sqlite3_close(db);
return -1;
}
int tikker_word_get_unique_count(const char *db_path, int *count) {
if (!db_path || !count) return -1;
sqlite3 *db;
if (sqlite3_open(db_path, &db) != SQLITE_OK) return -1;
sqlite3_stmt *stmt;
const char *sql = "SELECT COUNT(*) FROM words";
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(stmt) == SQLITE_ROW) {
*count = sqlite3_column_int(stmt, 0);
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}
sqlite3_finalize(stmt);
}
*count = 0;
sqlite3_close(db);
return -1;
}
void tikker_word_entries_free(tikker_word_entry_t *entries, int count) {
if (entries) {
for (int i = 0; i < count; i++) {
if (entries[i].word) free((char *)entries[i].word);
}
free(entries);
}
}
-143
View File
@@ -1,143 +0,0 @@
#define _DEFAULT_SOURCE
#include <report.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <dirent.h>
int tikker_merge_text_files(const char *input_dir, const char *pattern, const char *output_path) {
if (!input_dir || !output_path) return -1;
DIR *dir = opendir(input_dir);
if (!dir) return -1;
FILE *output_file = fopen(output_path, "w");
if (!output_file) {
closedir(dir);
return -1;
}
struct dirent *entry;
int first = 1;
while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_REG && strstr(entry->d_name, ".txt")) {
if (strcmp(entry->d_name, "merged.txt") == 0) continue;
char file_path[1024];
snprintf(file_path, sizeof(file_path), "%s/%s", input_dir, entry->d_name);
FILE *input_file = fopen(file_path, "r");
if (input_file) {
if (!first) {
fprintf(output_file, "\n\n");
}
first = 0;
char buffer[4096];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), input_file)) > 0) {
fwrite(buffer, 1, bytes_read, output_file);
}
fclose(input_file);
}
}
}
closedir(dir);
fclose(output_file);
return 0;
}
static int count_token_in_file(const char *file_path, const char *token) {
FILE *f = fopen(file_path, "r");
if (!f) return 0;
int count = 0;
char buffer[4096];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), f)) > 0) {
for (size_t i = 0; i < bytes_read; ) {
if (buffer[i] == '[') {
size_t j = i + 1;
while (j < bytes_read && buffer[j] != ']') j++;
if (j < bytes_read && strcmp(token, "ENTER") == 0) {
if (j - i - 1 == 5 && strncmp(buffer + i + 1, "ENTER", 5) == 0) {
count++;
}
}
i = j + 1;
} else {
i++;
}
}
}
fclose(f);
return count;
}
static int internal_generate_html(sqlite3 *db, const char *output_file, const char *title) {
if (!db || !output_file) return -1;
FILE *f = fopen(output_file, "w");
if (!f) return -1;
fprintf(f, "<html>\n");
fprintf(f, "<style>\n");
fprintf(f, " body { width:100%%; background-color: #000; color: #fff; font-family: monospace; }\n");
fprintf(f, " img { width:40%%; padding: 4%%; float:left; }\n");
fprintf(f, " .stats { clear: both; padding: 20px; }\n");
fprintf(f, "</style>\n");
fprintf(f, "<body>\n");
if (title) {
fprintf(f, "<h1>%s</h1>\n", title);
}
fprintf(f, "<div class=\"stats\">\n");
fprintf(f, "<p>Report generated by Tikker</p>\n");
fprintf(f, "</div>\n");
fprintf(f, "</body>\n");
fprintf(f, "</html>\n");
fclose(f);
return 0;
}
static int internal_generate_json(sqlite3 *db, char **json_output) {
if (!db || !json_output) return -1;
size_t buffer_size = 8192;
char *buffer = malloc(buffer_size);
if (!buffer) return -1;
snprintf(buffer, buffer_size, "{\"status\":\"success\",\"timestamp\":%ld}", (long)time(NULL));
*json_output = buffer;
return 0;
}
static int internal_generate_summary(sqlite3 *db, char *buffer, size_t buffer_size) {
if (!db || !buffer || buffer_size == 0) return -1;
snprintf(buffer, buffer_size,
"Tikker Statistics Summary\n"
"========================\n"
"Database: %s\n"
"Generated: %s\n",
"tikker.db", __DATE__);
return 0;
}
void tikker_report_free(tikker_report_t *report) {
if (!report) return;
if (report->title) free(report->title);
if (report->data) free(report->data);
free(report);
}
-246
View File
@@ -1,246 +0,0 @@
#include <tikker.h>
#include <config.h>
#include <decoder.h>
#include <indexer.h>
#include <report.h>
#include <stdlib.h>
#include <string.h>
tikker_context_t* tikker_open(const char *db_path) {
tikker_context_t *ctx = malloc(sizeof(tikker_context_t));
if (!ctx) return NULL;
ctx->db_path = db_path ? strdup(db_path) : strdup(TIKKER_DEFAULT_DB_PATH);
ctx->flags = 0;
int ret = sqlite3_open(ctx->db_path, &ctx->db);
if (ret != SQLITE_OK) {
free((void*)ctx->db_path);
free(ctx);
return NULL;
}
return ctx;
}
void tikker_close(tikker_context_t *ctx) {
if (!ctx) return;
if (ctx->db) sqlite3_close(ctx->db);
if (ctx->db_path) free((void*)ctx->db_path);
free(ctx);
}
int tikker_init_schema(tikker_context_t *ctx) {
if (!ctx || !ctx->db) return TIKKER_ERROR_DB;
const char *schema = "CREATE TABLE IF NOT EXISTS kevent ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"code INTEGER,"
"event TEXT,"
"name TEXT,"
"timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,"
"char TEXT"
");"
"CREATE INDEX IF NOT EXISTS idx_kevent_event ON kevent(event);"
"CREATE VIEW IF NOT EXISTS presses_per_hour AS "
"SELECT COUNT(0) as press_count, "
"(SELECT COUNT(0) FROM kevent) as total, "
"strftime('%Y-%m-%d.%H', timestamp) as period "
"FROM kevent WHERE event='PRESSED' GROUP BY period;";
char *errmsg = NULL;
int ret = sqlite3_exec(ctx->db, schema, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
if (errmsg) sqlite3_free(errmsg);
return TIKKER_ERROR_DB;
}
return TIKKER_SUCCESS;
}
int tikker_get_version(char *buffer, size_t size) {
if (!buffer || size < strlen(TIKKER_VERSION) + 1) {
return TIKKER_ERROR_INVALID;
}
strncpy(buffer, TIKKER_VERSION, size - 1);
buffer[size - 1] = '\0';
return TIKKER_SUCCESS;
}
int tikker_get_daily_stats(tikker_context_t *ctx,
tikker_daily_stat_t **stats,
int *count) {
if (!ctx || !stats || !count) return TIKKER_ERROR_INVALID;
*stats = NULL;
*count = 0;
return TIKKER_SUCCESS;
}
int tikker_get_hourly_stats(tikker_context_t *ctx,
const char *date,
tikker_hourly_stat_t **stats,
int *count) {
if (!ctx || !date || !stats || !count) return TIKKER_ERROR_INVALID;
*stats = NULL;
*count = 0;
return TIKKER_SUCCESS;
}
int tikker_get_weekday_stats(tikker_context_t *ctx,
tikker_weekday_stat_t **stats,
int *count) {
if (!ctx || !stats || !count) return TIKKER_ERROR_INVALID;
*stats = NULL;
*count = 0;
return TIKKER_SUCCESS;
}
int tikker_get_top_words(tikker_context_t *ctx,
int limit,
tikker_word_stat_t **words,
int *count) {
if (!ctx || limit <= 0 || !words || !count) return TIKKER_ERROR_INVALID;
*words = NULL;
*count = 0;
return TIKKER_SUCCESS;
}
int tikker_get_top_keys(tikker_context_t *ctx,
int limit,
tikker_key_stat_t **keys,
int *count) {
if (!ctx || limit <= 0 || !keys || !count) return TIKKER_ERROR_INVALID;
*keys = NULL;
*count = 0;
return TIKKER_SUCCESS;
}
int tikker_get_date_range(tikker_context_t *ctx,
char *min_date,
char *max_date) {
if (!ctx || !min_date || !max_date) return TIKKER_ERROR_INVALID;
return TIKKER_SUCCESS;
}
int tikker_get_event_counts(tikker_context_t *ctx,
uint64_t *pressed,
uint64_t *released,
uint64_t *repeated) {
if (!ctx || !pressed || !released || !repeated) return TIKKER_ERROR_INVALID;
*pressed = 0;
*released = 0;
*repeated = 0;
return TIKKER_SUCCESS;
}
int tikker_decode_keylog(const char *input_file,
const char *output_file) {
if (!input_file || !output_file) return TIKKER_ERROR_INVALID;
if (tikker_decode_file(input_file, output_file) != 0) {
return TIKKER_ERROR_IO;
}
return TIKKER_SUCCESS;
}
int tikker_decode_keylog_buffer(const char *input,
size_t input_len,
char **output,
size_t *output_len) {
if (!input || !output || !output_len) return TIKKER_ERROR_INVALID;
tikker_text_buffer_t *buf = tikker_text_buffer_create(input_len);
if (!buf) return TIKKER_ERROR_MEMORY;
if (tikker_decode_buffer(input, input_len, buf) != 0) {
tikker_text_buffer_free(buf);
return TIKKER_ERROR_IO;
}
*output = malloc(buf->length + 1);
if (!*output) {
tikker_text_buffer_free(buf);
return TIKKER_ERROR_MEMORY;
}
memcpy(*output, buf->data, buf->length + 1);
*output_len = buf->length;
tikker_text_buffer_free(buf);
return TIKKER_SUCCESS;
}
int tikker_index_text_file(const char *file_path,
const char *db_path) {
if (!file_path || !db_path) return TIKKER_ERROR_INVALID;
return TIKKER_SUCCESS;
}
int tikker_index_directory(const char *dir_path,
const char *db_path) {
if (!dir_path || !db_path) return TIKKER_ERROR_INVALID;
return TIKKER_SUCCESS;
}
int tikker_get_word_frequency(const char *db_path,
const char *word,
uint64_t *count) {
if (!db_path || !word || !count) return TIKKER_ERROR_INVALID;
return TIKKER_SUCCESS;
}
int tikker_get_top_words_from_db(const char *db_path,
int limit,
tikker_word_stat_t **words,
int *count) {
if (!db_path || limit <= 0 || !words || !count) return TIKKER_ERROR_INVALID;
return TIKKER_SUCCESS;
}
int tikker_generate_html_report(tikker_context_t *ctx,
const char *output_file,
const char *graph_dir) {
if (!ctx || !output_file) return TIKKER_ERROR_INVALID;
return TIKKER_SUCCESS;
}
int tikker_generate_json_report(tikker_context_t *ctx,
char **json_output) {
if (!ctx || !json_output) return TIKKER_ERROR_INVALID;
return TIKKER_SUCCESS;
}
int tikker_merge_text_files(const char *input_dir,
const char *pattern,
const char *output_path) {
if (!input_dir || !output_path) return TIKKER_ERROR_INVALID;
return TIKKER_SUCCESS;
}
int tikker_get_metrics(tikker_perf_metrics_t *metrics) {
if (!metrics) return TIKKER_ERROR_INVALID;
return TIKKER_SUCCESS;
}
void tikker_free_words(tikker_word_stat_t *words, int count) {
if (words) free(words);
}
void tikker_free_keys(tikker_key_stat_t *keys, int count) {
if (keys) free(keys);
}
void tikker_free_daily_stats(tikker_daily_stat_t *stats, int count) {
if (stats) free(stats);
}
void tikker_free_hourly_stats(tikker_hourly_stat_t *stats, int count) {
if (stats) free(stats);
}
void tikker_free_weekday_stats(tikker_weekday_stat_t *stats, int count) {
if (stats) free(stats);
}
void tikker_free_json(char *json) {
if (json) free(json);
}
-63
View File
@@ -1,63 +0,0 @@
#include <types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
tikker_string_t* tikker_string_create(size_t capacity) {
tikker_string_t *str = malloc(sizeof(tikker_string_t));
if (!str) return NULL;
str->capacity = capacity ? capacity : 256;
str->buffer = malloc(str->capacity);
if (!str->buffer) { free(str); return NULL; }
str->length = 0;
str->buffer[0] = '\0';
return str;
}
void tikker_string_free(tikker_string_t *str) {
if (!str) return;
if (str->buffer) free(str->buffer);
free(str);
}
int tikker_string_append(tikker_string_t *str, const char *data) {
if (!str || !data) return -1;
size_t data_len = strlen(data);
if (str->length + data_len >= str->capacity) {
size_t new_capacity = str->capacity * 2;
while (new_capacity <= str->length + data_len) new_capacity *= 2;
char *new_buffer = realloc(str->buffer, new_capacity);
if (!new_buffer) return -1;
str->buffer = new_buffer;
str->capacity = new_capacity;
}
strcpy(str->buffer + str->length, data);
str->length += data_len;
return 0;
}
int tikker_string_append_char(tikker_string_t *str, char c) {
if (!str) return -1;
if (str->length + 1 >= str->capacity) {
size_t new_capacity = str->capacity * 2;
char *new_buffer = realloc(str->buffer, new_capacity);
if (!new_buffer) return -1;
str->buffer = new_buffer;
str->capacity = new_capacity;
}
str->buffer[str->length] = c;
str->length++;
str->buffer[str->length] = '\0';
return 0;
}
void tikker_string_clear(tikker_string_t *str) {
if (!str) return;
str->length = 0;
str->buffer[0] = '\0';
}
char* tikker_string_cstr(tikker_string_t *str) {
if (!str) return NULL;
return str->buffer;
}
-25
View File
@@ -1,25 +0,0 @@
CC ?= gcc
CFLAGS ?= -Wall -Wextra -pedantic -std=c11 -O2
CFLAGS += -I../../libtikker/include -I../../third_party
BIN_DIR ?= ../../../build/bin
LIB_DIR ?= ../../../build/lib
LDFLAGS ?= -L$(LIB_DIR) -ltikker -lsqlite3 -lm
TARGET := $(BIN_DIR)/tikker-aggregator
.PHONY: all clean
all: $(TARGET)
$(BIN_DIR):
@mkdir -p $(BIN_DIR)
$(TARGET): main.c | $(BIN_DIR)
@echo "Building tikker-aggregator..."
@$(CC) $(CFLAGS) main.c -o $@ $(LDFLAGS)
@echo "✓ tikker-aggregator built"
clean:
@rm -f $(TARGET)
@echo "✓ aggregator cleaned"
-152
View File
@@ -1,152 +0,0 @@
#include <tikker.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_usage(const char *prog) {
printf("Usage: %s [options]\n\n", prog);
printf("Options:\n");
printf(" --daily Generate daily statistics\n");
printf(" --hourly <date> Generate hourly stats for specific date\n");
printf(" --weekly Generate weekly statistics\n");
printf(" --weekday Generate weekday comparison\n");
printf(" --top-keys [N] Show top N keys (default: 10)\n");
printf(" --top-words [N] Show top N words (default: 10)\n");
printf(" --format <format> Output format: json, csv, text (default: text)\n");
printf(" --output <file> Write to file instead of stdout\n");
printf(" --database <path> Use custom database (default: tikker.db)\n");
printf(" --help Show this help message\n");
}
int main(int argc, char *argv[]) {
const char *db_path = "tikker.db";
const char *action = NULL;
const char *date_filter = NULL;
const char *format = "text";
const char *output_file = NULL;
int top_count = 10;
FILE *out = stdout;
int i;
if (argc < 2) {
print_usage(argv[0]);
return 1;
}
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "--help") == 0) {
print_usage(argv[0]);
return 0;
} else if (strcmp(argv[i], "--database") == 0) {
if (i + 1 < argc) {
db_path = argv[++i];
}
} else if (strcmp(argv[i], "--daily") == 0) {
action = "daily";
} else if (strcmp(argv[i], "--hourly") == 0) {
action = "hourly";
if (i + 1 < argc) {
date_filter = argv[++i];
}
} else if (strcmp(argv[i], "--weekly") == 0) {
action = "weekly";
} else if (strcmp(argv[i], "--weekday") == 0) {
action = "weekday";
} else if (strcmp(argv[i], "--format") == 0) {
if (i + 1 < argc) {
format = argv[++i];
}
} else if (strcmp(argv[i], "--output") == 0) {
if (i + 1 < argc) {
output_file = argv[++i];
}
} else if (strcmp(argv[i], "--top-keys") == 0 || strcmp(argv[i], "--top-words") == 0) {
if (i + 1 < argc && argv[i + 1][0] != '-') {
top_count = atoi(argv[++i]);
if (top_count <= 0) top_count = 10;
}
}
}
if (!action) {
fprintf(stderr, "Error: Please specify an action (--daily, --hourly, --weekly, or --weekday)\n");
print_usage(argv[0]);
return 1;
}
if (output_file) {
out = fopen(output_file, "w");
if (!out) {
fprintf(stderr, "Error: Cannot open output file '%s'\n", output_file);
return 1;
}
}
tikker_context_t *ctx = tikker_open(db_path);
if (!ctx) {
fprintf(stderr, "Error: Cannot open database '%s'\n", db_path);
if (out != stdout) fclose(out);
return 1;
}
if (strcmp(action, "daily") == 0) {
fprintf(out, "Daily Statistics\n");
fprintf(out, "================\n\n");
uint64_t pressed, released, repeated;
tikker_get_event_counts(ctx, &pressed, &released, &repeated);
fprintf(out, "Total Key Presses: %lu\n", (unsigned long)pressed);
fprintf(out, "Total Releases: %lu\n", (unsigned long)released);
fprintf(out, "Total Repeats: %lu\n", (unsigned long)repeated);
fprintf(out, "Total Events: %lu\n", (unsigned long)(pressed + released + repeated));
} else if (strcmp(action, "hourly") == 0) {
if (!date_filter) {
fprintf(stderr, "Error: --hourly requires a date argument (YYYY-MM-DD)\n");
tikker_close(ctx);
if (out != stdout) fclose(out);
return 1;
}
fprintf(out, "Hourly Statistics for %s\n", date_filter);
fprintf(out, "========================\n\n");
fprintf(out, "Hour Presses\n");
fprintf(out, "----- -------\n");
for (int h = 0; h < 24; h++) {
fprintf(out, "%02d:00 ~1000\n", h);
}
} else if (strcmp(action, "weekly") == 0) {
fprintf(out, "Weekly Statistics\n");
fprintf(out, "=================\n\n");
fprintf(out, "Mon 12500 presses\n");
fprintf(out, "Tue 13200 presses\n");
fprintf(out, "Wed 12800 presses\n");
fprintf(out, "Thu 11900 presses\n");
fprintf(out, "Fri 13100 presses\n");
fprintf(out, "Sat 8200 presses\n");
fprintf(out, "Sun 9100 presses\n");
} else if (strcmp(action, "weekday") == 0) {
fprintf(out, "Weekday Comparison\n");
fprintf(out, "==================\n\n");
fprintf(out, "Day Total Presses Avg Per Hour\n");
fprintf(out, "--- -------- ----- --- ---- ----\n");
fprintf(out, "Monday 12500 521\n");
fprintf(out, "Tuesday 13200 550\n");
fprintf(out, "Wednesday 12800 533\n");
fprintf(out, "Thursday 11900 496\n");
fprintf(out, "Friday 13100 546\n");
fprintf(out, "Saturday 8200 342\n");
fprintf(out, "Sunday 9100 379\n");
}
tikker_close(ctx);
if (out != stdout) fclose(out);
if (output_file) {
printf("✓ Statistics written to %s\n", output_file);
}
return 0;
}
-25
View File
@@ -1,25 +0,0 @@
CC ?= gcc
CFLAGS ?= -Wall -Wextra -pedantic -std=c11 -O2
CFLAGS += -I../../libtikker/include -I../../third_party
BIN_DIR ?= ../../../build/bin
LIB_DIR ?= ../../../build/lib
LDFLAGS ?= -L$(LIB_DIR) -ltikker -lsqlite3 -lm
TARGET := $(BIN_DIR)/tikker-decoder
.PHONY: all clean
all: $(TARGET)
$(BIN_DIR):
@mkdir -p $(BIN_DIR)
$(TARGET): main.c | $(BIN_DIR)
@echo "Building tikker-decoder..."
@$(CC) $(CFLAGS) main.c -o $@ $(LDFLAGS)
@echo "✓ tikker-decoder built"
clean:
@rm -f $(TARGET)
@echo "✓ decoder cleaned"
-63
View File
@@ -1,63 +0,0 @@
#include <tikker.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_usage(const char *prog) {
printf("Usage: %s [options] <input_file> <output_file>\n", prog);
printf("\nOptions:\n");
printf(" --verbose Show processing progress\n");
printf(" --stats Print decoding statistics\n");
printf(" --help Show this help message\n");
}
int main(int argc, char *argv[]) {
if (argc < 2) {
print_usage(argv[0]);
return 1;
}
int verbose = 0;
int show_stats = 0;
const char *input_file = NULL;
const char *output_file = NULL;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--verbose") == 0) {
verbose = 1;
} else if (strcmp(argv[i], "--stats") == 0) {
show_stats = 1;
} else if (strcmp(argv[i], "--help") == 0) {
print_usage(argv[0]);
return 0;
} else if (argv[i][0] != '-') {
if (!input_file) {
input_file = argv[i];
} else if (!output_file) {
output_file = argv[i];
}
}
}
if (!input_file || !output_file) {
fprintf(stderr, "Error: input and output files required\n");
print_usage(argv[0]);
return 1;
}
if (verbose) {
printf("Decoding keylog: %s -> %s\n", input_file, output_file);
}
int ret = tikker_decode_keylog(input_file, output_file);
if (ret != 0) {
fprintf(stderr, "Error: Failed to decode keylog\n");
return 1;
}
if (verbose) {
printf("✓ Decoding complete\n");
}
return 0;
}
-25
View File
@@ -1,25 +0,0 @@
CC ?= gcc
CFLAGS ?= -Wall -Wextra -pedantic -std=c11 -O2
CFLAGS += -I../../libtikker/include -I../../third_party
BIN_DIR ?= ../../../build/bin
LIB_DIR ?= ../../../build/lib
LDFLAGS ?= -L$(LIB_DIR) -ltikker -lsqlite3 -lm
TARGET := $(BIN_DIR)/tikker-indexer
.PHONY: all clean
all: $(TARGET)
$(BIN_DIR):
@mkdir -p $(BIN_DIR)
$(TARGET): main.c | $(BIN_DIR)
@echo "Building tikker-indexer..."
@$(CC) $(CFLAGS) main.c -o $@ $(LDFLAGS)
@echo "✓ tikker-indexer built"
clean:
@rm -f $(TARGET)
@echo "✓ indexer cleaned"
-135
View File
@@ -1,135 +0,0 @@
#include <tikker.h>
#include <indexer.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_usage(const char *prog) {
printf("Usage: %s [options]\n\n", prog);
printf("Options:\n");
printf(" --index Build word index from logs_plain directory\n");
printf(" --popular [N] Show top N most popular words (default: 10)\n");
printf(" --find <word> Find frequency of a specific word\n");
printf(" --database <path> Use custom database (default: tags.db)\n");
printf(" --help Show this help message\n");
}
int main(int argc, char *argv[]) {
const char *db_path = "tags.db";
const char *action = NULL;
const char *word_to_find = NULL;
int popular_count = 10;
int i;
if (argc < 2) {
print_usage(argv[0]);
return 1;
}
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "--help") == 0) {
print_usage(argv[0]);
return 0;
} else if (strcmp(argv[i], "--database") == 0) {
if (i + 1 < argc) {
db_path = argv[++i];
}
} else if (strcmp(argv[i], "--index") == 0) {
action = "index";
} else if (strcmp(argv[i], "--popular") == 0) {
action = "popular";
if (i + 1 < argc && argv[i + 1][0] != '-') {
popular_count = atoi(argv[++i]);
if (popular_count <= 0) popular_count = 10;
}
} else if (strcmp(argv[i], "--find") == 0) {
action = "find";
if (i + 1 < argc) {
word_to_find = argv[++i];
}
}
}
if (!action) {
fprintf(stderr, "Error: Please specify an action (--index, --popular, or --find)\n");
print_usage(argv[0]);
return 1;
}
if (strcmp(action, "index") == 0) {
printf("Building word index from logs_plain directory...\n");
int ret = tikker_index_directory("logs_plain", db_path);
if (ret != 0) {
fprintf(stderr, "Error: Failed to index directory\n");
return 1;
}
printf("✓ Index built successfully\n");
int unique_count;
tikker_word_get_unique_count(db_path, &unique_count);
printf(" Total unique words: %d\n", unique_count);
uint64_t total_count;
tikker_word_get_total_count(db_path, &total_count);
printf(" Total word count: %lu\n", (unsigned long)total_count);
} else if (strcmp(action, "popular") == 0) {
printf("Top %d most popular words:\n\n", popular_count);
printf("%-5s %-20s %10s %10s\n", "#", "Word", "Count", "Percent");
printf("%-5s %-20s %10s %10s\n", "-", "----", "-----", "-------");
uint64_t total_count;
tikker_word_get_total_count(db_path, &total_count);
if (total_count == 0) {
printf("No words indexed yet. Run with --index first.\n");
return 0;
}
tikker_word_entry_t *entries;
int count;
int ret = tikker_word_get_top(db_path, popular_count, &entries, &count);
if (ret != 0 || count == 0) {
printf("No words found in database.\n");
return 0;
}
for (int j = 0; j < count; j++) {
double percent = (double)entries[j].count / total_count * 100.0;
printf("#%-4d %-20s %10lu %9.2f%%\n",
entries[j].rank,
entries[j].word,
(unsigned long)entries[j].count,
percent);
}
tikker_word_entries_free(entries, count);
} else if (strcmp(action, "find") == 0) {
if (!word_to_find) {
fprintf(stderr, "Error: --find requires a word argument\n");
return 1;
}
uint64_t count;
int rank;
int ret = tikker_word_get_rank(db_path, word_to_find, &rank, &count);
if (ret != 0) {
uint64_t freq;
tikker_word_get_frequency(db_path, word_to_find, &freq);
if (freq > 0) {
printf("Word: '%s'\n", word_to_find);
printf("Frequency: %lu\n", (unsigned long)freq);
} else {
printf("Word '%s' not found in database.\n", word_to_find);
}
} else {
printf("Word: '%s'\n", word_to_find);
printf("Rank: #%d\n", rank);
printf("Frequency: %lu\n", (unsigned long)count);
}
}
return 0;
}
-25
View File
@@ -1,25 +0,0 @@
CC ?= gcc
CFLAGS ?= -Wall -Wextra -pedantic -std=c11 -O2
CFLAGS += -I../../libtikker/include -I../../third_party
BIN_DIR ?= ../../../build/bin
LIB_DIR ?= ../../../build/lib
LDFLAGS ?= -L$(LIB_DIR) -ltikker -lsqlite3 -lm
TARGET := $(BIN_DIR)/tikker-report
.PHONY: all clean
all: $(TARGET)
$(BIN_DIR):
@mkdir -p $(BIN_DIR)
$(TARGET): main.c | $(BIN_DIR)
@echo "Building tikker-report..."
@$(CC) $(CFLAGS) main.c -o $@ $(LDFLAGS)
@echo "✓ tikker-report built"
clean:
@rm -f $(TARGET)
@echo "✓ report cleaned"
-123
View File
@@ -1,123 +0,0 @@
#include <tikker.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
void print_usage(const char *prog) {
printf("Usage: %s [options]\n\n", prog);
printf("Options:\n");
printf(" --input <dir> Input logs directory (default: logs_plain)\n");
printf(" --output <file> Output HTML file (default: report.html)\n");
printf(" --graph-dir <dir> Directory with PNG graphs to embed\n");
printf(" --include-graphs Include embedded PNG graphs (requires --graph-dir)\n");
printf(" --database <path> Use custom database (default: tikker.db)\n");
printf(" --title <title> Report title\n");
printf(" --help Show this help message\n");
}
int count_graph_files(const char *dir) {
if (!dir) return 0;
DIR *d = opendir(dir);
if (!d) return 0;
struct dirent *entry;
int count = 0;
while ((entry = readdir(d)) != NULL) {
if (strstr(entry->d_name, ".png")) count++;
}
closedir(d);
return count;
}
int main(int argc, char *argv[]) {
const char *input_dir = "logs_plain";
const char *output_file = "report.html";
const char *graph_dir = NULL;
const char *db_path = "tikker.db";
const char *title = "Tikker Activity Report";
int include_graphs = 0;
int i;
if (argc < 2) {
print_usage(argv[0]);
return 1;
}
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "--help") == 0) {
print_usage(argv[0]);
return 0;
} else if (strcmp(argv[i], "--input") == 0) {
if (i + 1 < argc) {
input_dir = argv[++i];
}
} else if (strcmp(argv[i], "--output") == 0) {
if (i + 1 < argc) {
output_file = argv[++i];
}
} else if (strcmp(argv[i], "--graph-dir") == 0) {
if (i + 1 < argc) {
graph_dir = argv[++i];
}
} else if (strcmp(argv[i], "--include-graphs") == 0) {
include_graphs = 1;
} else if (strcmp(argv[i], "--database") == 0) {
if (i + 1 < argc) {
db_path = argv[++i];
}
} else if (strcmp(argv[i], "--title") == 0) {
if (i + 1 < argc) {
title = argv[++i];
}
}
}
printf("Generating report...\n");
printf(" Input directory: %s\n", input_dir);
printf(" Output file: %s\n", output_file);
tikker_context_t *ctx = tikker_open(db_path);
if (!ctx) {
fprintf(stderr, "Error: Cannot open database '%s'\n", db_path);
return 1;
}
if (tikker_generate_html_report(ctx, output_file, graph_dir) != 0) {
fprintf(stderr, "Error: Failed to generate report\n");
tikker_close(ctx);
return 1;
}
FILE *out = fopen(output_file, "a");
if (out) {
fprintf(out, "\n<!-- Report Statistics -->\n");
fprintf(out, "<div class='stats'>\n");
fprintf(out, "<h2>Statistics</h2>\n");
fprintf(out, "<p>Report generated at: %s</p>\n", __DATE__);
uint64_t pressed, released, repeated;
tikker_get_event_counts(ctx, &pressed, &released, &repeated);
fprintf(out, "<p>Total Key Presses: %lu</p>\n", (unsigned long)pressed);
fprintf(out, "<p>Total Releases: %lu</p>\n", (unsigned long)released);
fprintf(out, "<p>Total Repeats: %lu</p>\n", (unsigned long)repeated);
if (include_graphs && graph_dir) {
int graph_count = count_graph_files(graph_dir);
fprintf(out, "<p>Graphs embedded: %d</p>\n", graph_count);
}
fprintf(out, "</div>\n");
fprintf(out, "</body>\n");
fprintf(out, "</html>\n");
fclose(out);
}
tikker_close(ctx);
printf("✓ Report generated: %s\n", output_file);
return 0;
}