sav

Sorting Algorithms Visualized
Index Commits Files Refs README LICENSE
commit 8f431bb2d5c546f987271789dcb5585674951371
parent cd09f71836d10706ec13d6ca676c0f47d5df5aef
Author: Martin J. Klöckner <64109770+mjkloeckner@users.noreply.github.com>
Date:   Thu, 22 Dec 2022 19:22:11 -0300

Merge pull request #15 from mjkloeckner/tmp

commit old changes
Diffstat:
Marray.c | 6+++---
Mdrw.c | 78+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Mdrw.h | 21+++++++--------------
Mmain.c | 76++++++++++++++++++++++------------------------------------------------------
Msav.h | 1-
Msdl_extra.c | 8--------
Msdl_extra.h | 6------
Msort.c | 24+++++++++++++++++++++++-
Msort.h | 14++------------
Mstatus.h | 2+-
Atodo.md | 11+++++++++++
Mutil.h | 1+
12 files changed, 129 insertions(+), 119 deletions(-)
diff --git a/array.c b/array.c
@@ -20,7 +20,7 @@ status_t Arr_create(Arr **arr) {
         return ERROR_MEMORY_ALLOC;
 
     (*arr)->len = ARR_LEN;
-    (*arr)->shuffle = NULL;
+    (*arr)->shuffle = &arr_shuffle;
 
     return OK;
 }
@@ -50,7 +50,7 @@ void arr_reversed(Arr *arr) {
 
     per_element = (ARR_MAX / arr->len);
     for(i = 0; i < arr->len; i++)
-        arr->v[i] = (arr->len * per_element) - (i * per_element);
+        arr->v[i] = arr->bk[i] = (arr->len * per_element) - (i * per_element);
 }
 
 void arr_in_order(Arr *arr) {
@@ -60,7 +60,7 @@ void arr_in_order(Arr *arr) {
     per_element = (ARR_MAX / arr->len);
 
     for(i = 0; i < arr->len; i++)
-        arr->v[i] = (i * per_element);
+        arr->v[i] = arr->bk[i] = (i * per_element);
 }
 
 void arr_shuffle(Arr *arr) {
diff --git a/drw.c b/drw.c
@@ -3,6 +3,26 @@
 static status_t drw_status_bar_fetch_text(Drw *, SAV *);
 static void drw_text(Drw *drw, const char *text, int x, int y);
 
+static char* const sort_status_str[STATUS_MAX] = {
+    "READY",
+    "SORTING",
+    "PAUSED",
+    "SORTED",
+    "STOPPED"
+};
+
+static char* const algo_sel_str[ALGORITHMS_COUNT + 1] = {
+    /* "bubble sort]", */
+    "bubble sort]",
+    "insertion sort]",
+    "merge sort]",
+    "quick sort]",
+    "shell sort]",
+    "selection sort]",
+    "heap sort]",
+    "sort not set]"
+};
+
 void drw_element_color(Drw *drw, int x, int y, int h, unsigned int col) {
     SDL_Rect rect;
 
@@ -55,7 +75,7 @@ static status_t drw_status_bar_fetch_text(Drw *drw, SAV *sav) {
                     sav->arr->len, sav->cmps, sav->swps);
         else if(sav->sort_status == SORTED)
             snprintf(drw->bar_text, drw->bar_text_len - 2,
-                    "  %-8s  [%s] [%-15s  L:%ld C:%ld S:%ld, done in %lds, extra storage: %ldB",
+                    "  %-8s  [%s] [%-15s  L:%ld C:%ld S:%ld, done in %lds, extra storage used: %ldbytes",
                     sort_status_str[sav->sort_status],
                     shuffle_t_str[sav->arr->shuffle_sel], algo_sel_str[sav->sort_algo],
                     sav->arr->len, sav->cmps, sav->swps, (sav->tf - sav->ti), sav->B_used);
@@ -73,15 +93,20 @@ static status_t drw_status_bar_fetch_text(Drw *drw, SAV *sav) {
 static void drw_text(Drw *drw, const char *text, int x, int y) {
     SDL_Surface *text_surface;
     SDL_Texture *text_texture;
+    static SDL_Color text_color;
+
+    text_color.r = (char)(FONT_COLOR >> 16) & 0xFF;
+    text_color.g = (char)(FONT_COLOR >> 8) & 0xFF;
+    text_color.b = (char)(FONT_COLOR) & 0xFF;
 
     /* TODO: UNICODE support? */
     /* drw->text_surface = TTF_RenderText_Blended(drw->font, text, drw->text_color); */
     /* drw->text_surface = TTF_RenderUNICODE_Blended(drw->font, text, drw->text_color); */
-    text_surface = TTF_RenderUTF8_Blended(drw->font, text, drw->text_color);
+    text_surface = TTF_RenderUTF8_Blended(drw->font, text, text_color);
     text_texture = SDL_CreateTextureFromSurface(drw->rend, text_surface);
 
     drw->bar_text_rect.x = 10 + x;
-    drw->bar_text_rect.y = drw->h - drw->font_size - 5;
+    drw->bar_text_rect.y = drw->h - FONT_SIZE - 5;
     drw->bar_text_rect.w = text_surface->w;
     drw->bar_text_rect.h = text_surface->h;
 
@@ -93,11 +118,10 @@ static void drw_text(Drw *drw, const char *text, int x, int y) {
 status_t drw_status_bar(Drw *drw, SAV *sav) {
     status_t st;
     SDL_Rect rect;
-    int bar_border = 2;
 
-    rect.x = bar_border; /* top left + x */
-    rect.y = drw->h - bar_border; /* top left + y, (y < 0) */
-    rect.w = drw->w - (2 * bar_border); /* fixed width */
+    rect.x = BAR_BORDER; /* top left + x */
+    rect.y = drw->h - BAR_BORDER; /* top left + y, (y < 0) */
+    rect.w = drw->w - (2 * BAR_BORDER); /* fixed width */
     rect.h = -BAR_HEIGHT;
 
     /* TODO: Make a variable to store statusbar background color */
@@ -106,13 +130,26 @@ status_t drw_status_bar(Drw *drw, SAV *sav) {
 
     if((st = drw_status_bar_fetch_text(drw, sav)) != OK) return st;
 
-    drw_text(drw, drw->bar_text, 0, drw->h - drw->font_size - 5);
+    drw_text(drw, drw->bar_text, 0, drw->h - FONT_SIZE - 5);
     memset(drw->bar_text, 0, sizeof(char) * drw->bar_text_len);
 
     return OK;
 }
 
-status_t Drw_create(Drw **drw) {
+status_t drw_update_frame(Drw *drw, SAV *sav) {
+    if(!drw || !sav) return ERROR_NULL_POINTER;
+
+    SDL_SetRenderDrawColor(drw->rend, 29, 28, 28, 0);
+    SDL_RenderClear(drw->rend);
+
+    drw_array_graph(drw, sav);
+    drw_status_bar(drw, sav);
+    SDL_RenderPresent(drw->rend);
+
+    return OK;
+}
+
+status_t drw_create(Drw **drw) {
     TTF_Font *font = NULL;
     status_t st;
 
@@ -128,21 +165,24 @@ status_t Drw_create(Drw **drw) {
     if(font == NULL)
         return ERROR_TTF_OPENING_FONT;
 
+    int min_w, min_h;
+
+    /* compute the window minimum size */
+    min_w = ((ARR_LEN * RECT_WIDTH) + (2 * X_BORDER));
+    min_h = ((ARR_MAX) + (2 * Y_BORDER) + TOP_BORDER);
+
+    SDL_SetWindowMinimumSize((*drw)->win, min_w, min_h);
+    /* SDL_SetWindowMaximumSize(*win, min_w, min_h); */
+
     (*drw)->font = font;
-    (*drw)->font_size = FONT_SIZE;
-    (*drw)->bar_border = 2;
     (*drw)->x_border = X_BORDER;
     (*drw)->y_border = Y_BORDER;
 
-    (*drw)->text_color.r = (char)(FONT_COLOR >> 16) & 0xFF;
-    (*drw)->text_color.g = (char)(FONT_COLOR >> 8) & 0xFF;
-    (*drw)->text_color.b = (char)(FONT_COLOR) & 0xFF;
-
     SDL_GetWindowSize((*drw)->win, &((*drw)->w), &((*drw)->h));
 
-    (*drw)->bar_rect.x = (*drw)->bar_border; /* top left + x */
-    (*drw)->bar_rect.y = (*drw)->h - (*drw)->bar_border; /* top left + y, (y < 0) */
-    (*drw)->bar_rect.w = (*drw)->w - (2 * (*drw)->bar_border); /* fixed width */
+    (*drw)->bar_rect.x = BAR_BORDER; /* top left + x */
+    (*drw)->bar_rect.y = (*drw)->h - BAR_BORDER; /* top left + y, (y < 0) */
+    (*drw)->bar_rect.w = (*drw)->w - (2 * BAR_BORDER); /* fixed width */
     (*drw)->bar_rect.h = -BAR_HEIGHT;
 
     /* sometimes SDL_GetWindowSize() fails */
@@ -168,7 +208,7 @@ status_t Drw_create(Drw **drw) {
     return OK;
 }
 
-void Drw_destroy(Drw *drw) {
+void drw_destroy(Drw *drw) {
     if(drw == NULL) return;
 
     TTF_CloseFont(drw->font);
diff --git a/drw.h b/drw.h
@@ -9,7 +9,7 @@
 #include "sdl_extra.h"
 #include "sort.h"
 
-#define SEL_COLOR    0x00FF0000 // RGBA (A not used rn)
+#define SEL_COLOR    0x00FF0000 /* RGBA (A not used rn) */
 #define CMP_COLOR    0x00FFFF00
 #define NORM_COLOR    0xFF000000
 
@@ -18,39 +18,32 @@
 #define FONT_COLOR    0xBBBBBB
 
 #define BAR_HEIGHT    15
+#define BAR_BORDER    2
 
 #define WIN_MIN_W    800
 #define WIN_MIN_H    600
 
 #define X_BORDER    40
 #define Y_BORDER    40
-#define TOP_BORDER    50
+#define TOP_BORDER    150
 #define RECT_WIDTH    5
 
 typedef struct {
     SDL_Renderer *rend;
     SDL_Window *win;
-    SDL_Color text_color;
     SDL_Rect bar_rect, bar_text_rect;
     TTF_Font *font;
-    int w, h, font_size, bar_text_len, bar_border;
+    int w, h, bar_text_len;
     size_t x_border, y_border;
     char *bar_text;
 } Drw;
 
-static char * const sort_status_str[STATUS_MAX] = {
-    "READY",
-    "SORTING",
-    "PAUSED",
-    "SORTED",
-    "STOPPED"
-};
-
-status_t Drw_create(Drw **drw);
-void Drw_destroy(Drw *drw);
+status_t drw_create(Drw **drw);
+void drw_destroy(Drw *drw);
 
 void drw_element(SDL_Renderer *rend, int x, int y, int h);
 void drw_element_color(Drw *drw, int x, int y, int h, unsigned int col);
+status_t drw_update_frame(Drw *, SAV *);
 
 void drw_array_graph(Drw *drw, SAV *sav);
 status_t drw_status_bar(Drw *drw, SAV *sav);
diff --git a/main.c b/main.c
@@ -3,63 +3,36 @@
 #include "sort.h"
 #include "util.h"
 #include "sdl_extra.h"
-#include "array.h"
 
 #include <stdio.h>
 #include <pthread.h>
-#include <assert.h>
 
 #define SHOW_FPS false
 #define WELCOME_MSG_TIME 3
 
 void check_events(Drw *, SAV *);
 
-/* pthread_create compliant start routine */
-void *routine_wrapper(void *);
-
-static void (*sort_handler[])(SAV *) = {
-    /* &bubble_sort, */
-    &bubble_sort_improved,
-    &insertion_sort,
-    &merge_sort_wrapper,
-    &quick_sort_wrapper,
-    &shell_sort,
-    &selection_sort,
-    &heap_sort
-};
-
-void *routine_wrapper(void *arg) {
-    SAV *sav = (SAV *)arg;
-
-    assert((sav->sort_algo != ALGORITHMS_COUNT) && "Default sorting algorithm not set");
-
-    sort_handler[sav->sort_algo](sav);
-
-    return NULL;
-}
-
+/* TODO: fix Drw and SAV names and methods? */
+/* TODO: add sav methods */
 /* TODO: Support command line arguments */
 /* TODO: Support sound */
 /* TODO: More sorting algorithms */
-/* TODO: add sav methods */
 
 int main (void)
 {
     SAV *sav = NULL;
     Drw *drw = NULL;
     time_t tic, toc;
-    unsigned int ti, tf, dt;
-    short time_per_frame;
-
+    unsigned int ti, tf, dt, time_per_frame;
     pthread_t p1 = 0;
     status_t st;
 
     if((st = SAV_create(&sav)) != OK) goto end;
-    if((st = Drw_create(&drw)) != OK) goto end;
+    if((st = drw_create(&drw)) != OK) goto end;
 
     tic = time(NULL);
     time_per_frame = 16; /* miliseconds */
-    arr_shuffle(sav->arr);
+    sav->arr->shuffle(sav->arr);
 
 #if SHOW_FPS
     short fps = 0;
@@ -71,17 +44,8 @@ int main (void)
         if(!ti) ti = SDL_GetTicks();
         else dt = tf - ti; /* how many ms for a frame */
 
-        /* printf("DT: %d | TI: %d | TF: %d\n", dt, ti, tf); */
-
         check_events(drw, sav);
-
-        SDL_SetRenderDrawColor(drw->rend, 29, 28, 28, 0);
-        SDL_RenderClear(drw->rend);
-
-        drw_array_graph(drw, sav);
-        drw_status_bar(drw, sav);
-
-        SDL_RenderPresent(drw->rend);
+        drw_update_frame(drw, sav);
 
         if((sav->status == START) || (sav->status == WELCOME)) {
             /* Print welcome message during the first WELCOME_MSG_TIME seconds */
@@ -92,7 +56,7 @@ int main (void)
                 sav->status = RUN;
 
                 /* start sorting thread */
-                pthread_create(&p1, NULL, &routine_wrapper, (void *)sav);
+                pthread_create(&p1, NULL, &start_sorting, (void *)sav);
             }
         }
 
@@ -102,7 +66,7 @@ int main (void)
             pthread_join(p1, NULL);
 
             sort_reset_stats(sav);
-            arr_shuffle(sav->arr);
+            sav->arr->shuffle(sav->arr);
 
             sav->status = START;
             sav->sort_status = PAUSE;
@@ -113,9 +77,9 @@ int main (void)
             sav->sel = sav->cmp = ARR_LEN + 1;
         }
 
-        /* if less than `time_per_frame`, delay */
-        if(dt <= time_per_frame)
-            SDL_Delay(time_per_frame - dt);
+        /* if less than `time_per_frame`, delay */
+        if(dt <= time_per_frame)
+            SDL_Delay(time_per_frame - dt);
 
 #if SHOW_FPS
         if(dt > time_per_frame)
@@ -124,8 +88,8 @@ int main (void)
         printf("FPS is: %i\n", fps);
 #endif
 
-        ti = tf;
-        tf = SDL_GetTicks();
+        ti = tf;
+        tf = SDL_GetTicks();
     }
 
 end:
@@ -133,10 +97,9 @@ end:
     if(p1 != 0) pthread_join(p1, NULL);
 
     SAV_destroy(sav);
-    Drw_destroy(drw);
 
-    if(st != OK) printf("%s\n", status_string[st]);
-    return st;
+    drw_destroy(drw);
+    return 0;
 }
 
 void check_events(Drw *drw, SAV *sav)
@@ -179,10 +142,15 @@ void check_events(Drw *drw, SAV *sav)
                 break;
             case SDL_SCANCODE_S:
                 arr_shuffle_next(sav->arr);
-                if(sav->sort_status == PAUSE) {
-                    if(sav->status == RUN) sav->status = RESTART;
+                if(sav->sort_status == PAUSE || sav->sort_status == SORTED) {
+                    if(sav->status == RUN)
+                        sav->status = RESTART;
                     else arr_shuffle(sav->arr);
                 }
+                else if (sav->sort_status == RUN) {
+                    sav->status = RESTART;
+                    arr_shuffle(sav->arr);
+                }
                 break;
             default: break;
             }
diff --git a/sav.h b/sav.h
@@ -29,7 +29,6 @@ typedef struct {
     status_t status, prev_status, sort_status;
     sort_t sort_algo;
     size_t sort_delay;
-    bool quit;
 } SAV;
 
 status_t SAV_create(SAV **sav);
diff --git a/sdl_extra.c b/sdl_extra.c
@@ -1,8 +1,6 @@
 #include "sdl_extra.h"
 
 status_t SDL_setup(SDL_Window **win, SDL_Renderer **rend) {
-    int min_w, min_h;
-
     if (SDL_Init(SDL_INIT_VIDEO) != 0)
         return ERROR_SDL_INIT;
 
@@ -23,12 +21,6 @@ status_t SDL_setup(SDL_Window **win, SDL_Renderer **rend) {
     if(TTF_Init() == -1)
         return ERROR_SDL_FONT_INIT;
 
-    /* compute the window minimum size */
-    min_w = ((ARR_LEN * RECT_WIDTH) + (2 * X_BORDER));
-    min_h = ((ARR_MAX) + (2 * Y_BORDER) + TOP_BORDER);
-
-    SDL_SetWindowMinimumSize(*win, min_w, min_h);
-    /* SDL_SetWindowMaximumSize(*win, min_w, min_h); */
     return OK;
 }
 
diff --git a/sdl_extra.h b/sdl_extra.h
@@ -1,17 +1,11 @@
 #ifndef __SDL_EXTRA_H__
 #define __SDL_EXTRA_H__
 
-#include "array.h"
 #include "status.h"
 
 #include <SDL2/SDL.h>
 #include <SDL2/SDL_ttf.h>
 
-#define X_BORDER    40
-#define Y_BORDER    40
-#define TOP_BORDER    50
-#define RECT_WIDTH    5
-
 #define WIN_TITLE "SAV: Sorting Algorithms Visualized"
 
 status_t SDL_setup(SDL_Window **win, SDL_Renderer **rend);
diff --git a/sort.c b/sort.c
@@ -5,6 +5,28 @@
 
 #include "sort.h"
 
+static void (*sort_handler[])(SAV *) = {
+    /* &bubble_sort, */
+    &bubble_sort_improved,
+    &insertion_sort,
+    &merge_sort_wrapper,
+    &quick_sort_wrapper,
+    &shell_sort,
+    &selection_sort,
+    &heap_sort
+};
+
+/* pthread_create compliant start routine */
+void *start_sorting(void *arg) {
+    SAV *sav = (SAV *)arg;
+
+    assert((sav->sort_algo != ALGORITHMS_COUNT) && "Default sorting algorithm not set");
+
+    sort_handler[sav->sort_algo](sav);
+
+    return NULL;
+}
+
 void set_sort_speed(SAV *sav, size_t new_value) {
     if(sav == NULL) return;
 
@@ -33,7 +55,7 @@ status_t sort_pause(const SAV *sav) {
 
 void insertion_sort(SAV *sav) {
     int key;
-    int i, j;
+    size_t i, j;
 
     if(sav == NULL) return;
     if(sort_pause(sav) == STOP) return;
diff --git a/sort.h b/sort.h
@@ -2,20 +2,10 @@
 #define __SORT_H__
 
 #include "sav.h"
-
-static char * const algo_sel_str[ALGORITHMS_COUNT + 1] = {
-    /* "bubble sort]", */
-    "bubble sort]",
-    "insertion sort]",
-    "merge sort]",
-    "quick sort]",
-    "shell sort]",
-    "selection sort]",
-    "heap sort]",
-    "sort not set]"
-};
+#include "assert.h"
 
 void set_sort_speed(SAV *sav, size_t new_value);
+void *start_sorting(void *arg);
 
 void bubble_sort(SAV *);
 void bubble_sort_improved(SAV *);
diff --git a/status.h b/status.h
@@ -20,7 +20,7 @@ typedef enum {
     STATUS_MAX
 } status_t;
 
-static char * const status_string[STATUS_MAX] = {
+static char* const status_string[STATUS_MAX] = {
     "OK",
     "RUN",
     "PAUSE",
diff --git a/todo.md b/todo.md
@@ -0,0 +1,11 @@
+# SAV - To Do
+
+1. README: Update dependencies list
+    - Add font
+    - Add SDL\_ttf
+
+2. Fix Drw and SAV names and methods?
+3. Add sav methods
+4. Support command line arguments
+5. Support sound
+6. More sorting algorithms
diff --git a/util.h b/util.h
@@ -9,6 +9,7 @@
     ((color) >> (8 * 1)) & 0xFF, \
     ((color) >> (8 * 0)) & 0xFF
 
+
 void end(const char *msg);
 void swap(int *a, int *b);