<commit_before>#include <pebble.h>

#define PERSIST_WORK_INTERVAL 10
#define PERSIST_REST_INTERVAL 20
#define PERSIST_WARNING_VIBRATION 30

#define DEFAULT_WORK_INTERVAL 1500
#define DEFAULT_REST_INTERVAL 120
#define DEFAULT_WARNING_VIBRATION false

#define NUM_MENU_SECTIONS 1
#define NUM_MENU_ITEMS 3

#define MAX_WORK_INTERVAL 3600
#define WORK_INTERVAL_INCREMENT 300

#define MAX_REST_INTERVAL 600
#define REST_INTERVAL_INCREMENT 60

#define WARNING_VIBRATION_TIME 9

#define COUNTDOWN_STR_LENGTH 6

static int WORK_INTERVAL;
static int STARTING_WORK_INTERVAL;

static int REST_INTERVAL;
static int STARTING_REST_INTERVAL;

static int WARNING_VIBRATION;

static Window *s_main_window;
static Window *s_menu_window;

static TextLayer *s_clock_layer;
static TextLayer *s_countdown_layer;

static SimpleMenuLayer *s_simple_menu_layer;
static SimpleMenuSection s_menu_sections[NUM_MENU_SECTIONS];
static SimpleMenuItem s_menu_items[NUM_MENU_ITEMS];

static bool s_in_rest_mode = false;
static bool s_countdown_paused = true;

static int s_countdown_seconds;

static void init_settings() {
   WORK_INTERVAL = (
       persist_exists(PERSIST_WORK_INTERVAL) ?
           persist_read_int(PERSIST_WORK_INTERVAL) :
           DEFAULT_WORK_INTERVAL
   );
   REST_INTERVAL = (
       persist_exists(PERSIST_REST_INTERVAL) ?
           persist_read_int(PERSIST_REST_INTERVAL) :
           DEFAULT_REST_INTERVAL
   );
   WARNING_VIBRATION = (
       persist_exists(PERSIST_WARNING_VIBRATION) ?
           persist_read_int(PERSIST_WARNING_VIBRATION) :
           DEFAULT_WARNING_VIBRATION
   );
}

static char* format_countdown_time(int countdown_time, char* str) {
    int seconds = countdown_time % 60;
    int minutes = countdown_time / 60;

    snprintf(str, sizeof("00:00"), "%01d:%02d", minutes, seconds);

    return str;
}

static void update_work_interval(int index, void *context) {
    static char countdown_str[COUNTDOWN_STR_LENGTH];

    if (WORK_INTERVAL == MAX_WORK_INTERVAL) {
        WORK_INTERVAL = WORK_INTERVAL_INCREMENT;
    } else {
        WORK_INTERVAL += WORK_INTERVAL_INCREMENT;
    }

    s_menu_items[0].subtitle = format_countdown_time(
        WORK_INTERVAL,
        countdown_str
    );

    layer_mark_dirty(simple_menu_layer_get_layer(s_simple_menu_layer));
}

static void update_rest_interval(int index, void *context) {
    static char countdown_str[COUNTDOWN_STR_LENGTH];

    if (REST_INTERVAL == MAX_REST_INTERVAL) {
        REST_INTERVAL = REST_INTERVAL_INCREMENT;
    } else {
        REST_INTERVAL += REST_INTERVAL_INCREMENT;
    }

    s_menu_items[1].subtitle = format_countdown_time(
        REST_INTERVAL,
        countdown_str
    );

    layer_mark_dirty(simple_menu_layer_get_layer(s_simple_menu_layer));
}

static void update_warning_vibration(int index, void *context) {
    WARNING_VIBRATION = !WARNING_VIBRATION;

    s_menu_items[2].subtitle = WARNING_VIBRATION ? "On" : "Off";

    layer_mark_dirty(simple_menu_layer_get_layer(s_simple_menu_layer));
}

static void build_menu() {
    static char work_countdown_str[COUNTDOWN_STR_LENGTH];
    static char rest_countdown_str[COUNTDOWN_STR_LENGTH];

    s_menu_items[0] = (SimpleMenuItem) {
        .title = "Work Interval",
        .subtitle = format_countdown_time(WORK_INTERVAL, work_countdown_str),
        .callback = update_work_interval
    };
    s_menu_items[1] = (SimpleMenuItem) {
        .title = "Rest Interval",
        .subtitle = format_countdown_time(REST_INTERVAL, rest_countdown_str),
        .callback = update_rest_interval
    };
    s_menu_items[2] = (SimpleMenuItem) {
        .title = "Warning Vibe",
        .subtitle = WARNING_VIBRATION ? "On" : "Off",
        .callback = update_warning_vibration
    };
    s_menu_sections[0] = (SimpleMenuSection) {
        .title = "Settings",
        .num_items = NUM_MENU_ITEMS,
        .items = s_menu_items
    };
}

static void set_colors() {
    if (s_in_rest_mode) {
        window_set_background_color(s_main_window, GColorWhite);

        text_layer_set_background_color(s_clock_layer, GColorWhite);
        text_layer_set_text_color(s_clock_layer, GColorBlack);

        text_layer_set_background_color(s_countdown_layer, GColorWhite);
        text_layer_set_text_color(s_countdown_layer, GColorBlack);
    } else {
        window_set_background_color(s_main_window, GColorBlack);

        text_layer_set_background_color(s_clock_layer, GColorBlack);
        text_layer_set_text_color(s_clock_layer, GColorWhite);

        text_layer_set_background_color(s_countdown_layer, GColorBlack);
        text_layer_set_text_color(s_countdown_layer, GColorWhite);
    }
}

static void update_clock_time() {
    time_t temp = time(NULL);

    struct tm *tick_time = localtime(&temp);

    static char buffer[] = "00:00";

    if (clock_is_24h_style() == true) {
        strftime(buffer, sizeof("00:00"), "%H:%M", tick_time);
    } else {
        strftime(buffer, sizeof("00:00"), "%I:%M", tick_time);
    }

    text_layer_set_text(s_clock_layer, buffer);
}

static void update_countdown_time() {
    static char countdown_str[COUNTDOWN_STR_LENGTH];

    if (!s_countdown_paused) {
        text_layer_set_text(
            s_countdown_layer,
            format_countdown_time(s_countdown_seconds, countdown_str)
        );
        --s_countdown_seconds;
    }

    if (s_countdown_seconds == WARNING_VIBRATION_TIME) {
        vibes_double_pulse();
    }
}

static void update_rest_mode(bool force) {
    if (s_countdown_seconds == 0 || force == true) {
        if (s_in_rest_mode == false) {
            s_countdown_seconds = REST_INTERVAL;<commit_msg>Fix double buzz in rest mode bug.<commit_after>#include <pebble.h>

#define PERSIST_WORK_INTERVAL 10
#define PERSIST_REST_INTERVAL 20
#define PERSIST_WARNING_VIBRATION 30

#define DEFAULT_WORK_INTERVAL 1500
#define DEFAULT_REST_INTERVAL 120
#define DEFAULT_WARNING_VIBRATION false

#define NUM_MENU_SECTIONS 1
#define NUM_MENU_ITEMS 3

#define MAX_WORK_INTERVAL 3600
#define WORK_INTERVAL_INCREMENT 300

#define MAX_REST_INTERVAL 600
#define REST_INTERVAL_INCREMENT 60

#define WARNING_VIBRATION_TIME 9

#define COUNTDOWN_STR_LENGTH 6

static int WORK_INTERVAL;
static int STARTING_WORK_INTERVAL;

static int REST_INTERVAL;
static int STARTING_REST_INTERVAL;

static int WARNING_VIBRATION;

static Window *s_main_window;
static Window *s_menu_window;

static TextLayer *s_clock_layer;
static TextLayer *s_countdown_layer;

static SimpleMenuLayer *s_simple_menu_layer;
static SimpleMenuSection s_menu_sections[NUM_MENU_SECTIONS];
static SimpleMenuItem s_menu_items[NUM_MENU_ITEMS];

static bool s_in_rest_mode = false;
static bool s_countdown_paused = true;

static int s_countdown_seconds;

static void init_settings() {
   WORK_INTERVAL = (
       persist_exists(PERSIST_WORK_INTERVAL) ?
           persist_read_int(PERSIST_WORK_INTERVAL) :
           DEFAULT_WORK_INTERVAL
   );
   REST_INTERVAL = (
       persist_exists(PERSIST_REST_INTERVAL) ?
           persist_read_int(PERSIST_REST_INTERVAL) :
           DEFAULT_REST_INTERVAL
   );
   WARNING_VIBRATION = (
       persist_exists(PERSIST_WARNING_VIBRATION) ?
           persist_read_int(PERSIST_WARNING_VIBRATION) :
           DEFAULT_WARNING_VIBRATION
   );
}

static char* format_countdown_time(int countdown_time, char* str) {
    int seconds = countdown_time % 60;
    int minutes = countdown_time / 60;

    snprintf(str, sizeof("00:00"), "%01d:%02d", minutes, seconds);

    return str;
}

static void update_work_interval(int index, void *context) {
    static char countdown_str[COUNTDOWN_STR_LENGTH];

    if (WORK_INTERVAL == MAX_WORK_INTERVAL) {
        WORK_INTERVAL = WORK_INTERVAL_INCREMENT;
    } else {
        WORK_INTERVAL += WORK_INTERVAL_INCREMENT;
    }

    s_menu_items[0].subtitle = format_countdown_time(
        WORK_INTERVAL,
        countdown_str
    );

    layer_mark_dirty(simple_menu_layer_get_layer(s_simple_menu_layer));
}

static void update_rest_interval(int index, void *context) {
    static char countdown_str[COUNTDOWN_STR_LENGTH];

    if (REST_INTERVAL == MAX_REST_INTERVAL) {
        REST_INTERVAL = REST_INTERVAL_INCREMENT;
    } else {
        REST_INTERVAL += REST_INTERVAL_INCREMENT;
    }

    s_menu_items[1].subtitle = format_countdown_time(
        REST_INTERVAL,
        countdown_str
    );

    layer_mark_dirty(simple_menu_layer_get_layer(s_simple_menu_layer));
}

static void update_warning_vibration(int index, void *context) {
    WARNING_VIBRATION = !WARNING_VIBRATION;

    s_menu_items[2].subtitle = WARNING_VIBRATION ? "On" : "Off";

    layer_mark_dirty(simple_menu_layer_get_layer(s_simple_menu_layer));
}

static void build_menu() {
    static char work_countdown_str[COUNTDOWN_STR_LENGTH];
    static char rest_countdown_str[COUNTDOWN_STR_LENGTH];

    s_menu_items[0] = (SimpleMenuItem) {
        .title = "Work Interval",
        .subtitle = format_countdown_time(WORK_INTERVAL, work_countdown_str),
        .callback = update_work_interval
    };
    s_menu_items[1] = (SimpleMenuItem) {
        .title = "Rest Interval",
        .subtitle = format_countdown_time(REST_INTERVAL, rest_countdown_str),
        .callback = update_rest_interval
    };
    s_menu_items[2] = (SimpleMenuItem) {
        .title = "Warning Vibe",
        .subtitle = WARNING_VIBRATION ? "On" : "Off",
        .callback = update_warning_vibration
    };
    s_menu_sections[0] = (SimpleMenuSection) {
        .title = "Settings",
        .num_items = NUM_MENU_ITEMS,
        .items = s_menu_items
    };
}

static void set_colors() {
    if (s_in_rest_mode) {
        window_set_background_color(s_main_window, GColorWhite);

        text_layer_set_background_color(s_clock_layer, GColorWhite);
        text_layer_set_text_color(s_clock_layer, GColorBlack);

        text_layer_set_background_color(s_countdown_layer, GColorWhite);
        text_layer_set_text_color(s_countdown_layer, GColorBlack);
    } else {
        window_set_background_color(s_main_window, GColorBlack);

        text_layer_set_background_color(s_clock_layer, GColorBlack);
        text_layer_set_text_color(s_clock_layer, GColorWhite);

        text_layer_set_background_color(s_countdown_layer, GColorBlack);
        text_layer_set_text_color(s_countdown_layer, GColorWhite);
    }
}

static void update_clock_time() {
    time_t temp = time(NULL);

    struct tm *tick_time = localtime(&temp);

    static char buffer[] = "00:00";

    if (clock_is_24h_style() == true) {
        strftime(buffer, sizeof("00:00"), "%H:%M", tick_time);
    } else {
        strftime(buffer, sizeof("00:00"), "%I:%M", tick_time);
    }

    text_layer_set_text(s_clock_layer, buffer);
}

static void update_countdown_time() {
    static char countdown_str[COUNTDOWN_STR_LENGTH];

    if (!s_countdown_paused) {
        text_layer_set_text(
            s_countdown_layer,
            format_countdown_time(s_countdown_seconds, countdown_str)
        );
        --s_countdown_seconds;
    }

    if (s_countdown_seconds == WARNING_VIBRATION_TIME && !s_in_rest_mode) {
        vibes_double_pulse();
    }
}

static void update_rest_mode(bool force) {
    if (s_countdown_seconds == 0 || force == true) {
        if (s_in_rest_mode == false) {
            s_countdown_seconds = REST_INTERVAL;
{'fraction_non_alphanumeric': 0.08353328001421843, 'fraction_numerical': 0.011197014129565449, 'mean_word_length': 4.0062277580071175, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4069688', 'n_tokens_mistral': 4056, 'n_tokens_neox': 3832, 'n_words': 640}