diff --git a/a2/test_main b/a2/test_main new file mode 100755 index 0000000..2ab0311 Binary files /dev/null and b/a2/test_main differ diff --git a/a2/test_main.c b/a2/test_main.c new file mode 100644 index 0000000..0d4f390 --- /dev/null +++ b/a2/test_main.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include "pig_latin.h" + +#define CHECK(phrase, expected) do { \ + char *r = translate(phrase); \ + if (strcmp(r, expected) == 0) printf("OK: %s -> %s\n", phrase, r); \ + else printf("FAIL: %s -> got '%s', expected '%s'\n", phrase, r, expected); \ + free(r); \ +} while(0) + +int main() { + CHECK("apple", "appleay"); + CHECK("ear", "earay"); + CHECK("igloo", "iglooay"); + CHECK("equal", "equalay"); + CHECK("xray", "xrayay"); + CHECK("yttria", "yttriaay"); + CHECK("pig", "igpay"); + CHECK("koala", "oalakay"); + CHECK("xenon", "enonxay"); + CHECK("qat", "atqay"); + CHECK("chair", "airchay"); + CHECK("queen", "eenquay"); + CHECK("square", "aresquay"); + CHECK("therapy", "erapythay"); + CHECK("thrush", "ushthray"); + CHECK("school", "oolschay"); + CHECK("yellow", "ellowyay"); + CHECK("rhythm", "ythmrhay"); + CHECK("my", "ymay"); + CHECK("liquid", "iquidlay"); + CHECK("quick fast run", "ickquay astfay unray"); + return 0; +} diff --git a/du1/gui b/du1/gui new file mode 100755 index 0000000..edd2a2b Binary files /dev/null and b/du1/gui differ diff --git a/du1/gui.c b/du1/gui.c new file mode 100644 index 0000000..325cd7d --- /dev/null +++ b/du1/gui.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include + +// Widgets we need to access globally +static GtkWidget *entry_x; +static GtkWidget *text_coeffs; +static GtkWidget *label_result; + +static void calculate(GtkWidget *widget, gpointer data) { + (void)widget; (void)data; + + // Read x + const char *x_str = gtk_entry_get_text(GTK_ENTRY(entry_x)); + double x; + if (sscanf(x_str, "%lf", &x) != 1) { + gtk_label_set_text(GTK_LABEL(label_result), "Chyba: Nepodarilo sa nacitat zaklad x"); + return; + } + + // Read coefficients from text view + GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_coeffs)); + GtkTextIter start, end; + gtk_text_buffer_get_start_iter(buf, &start); + gtk_text_buffer_get_end_iter(buf, &end); + char *text = gtk_text_buffer_get_text(buf, &start, &end, FALSE); + + double coeffs[256]; + int n = 0; + char *line = strtok(text, "\n"); + while (line != NULL && n < 256) { + // skip empty lines + if (strlen(line) == 0 || line[0] == '\r') { + line = strtok(NULL, "\n"); + continue; + } + if (sscanf(line, "%lf", &coeffs[n]) != 1) { + char msg[128]; + snprintf(msg, sizeof(msg), "Chyba: Nepodarilo sa nacitat polynom na %d mieste.", n + 1); + gtk_label_set_text(GTK_LABEL(label_result), msg); + g_free(text); + return; + } + n++; + line = strtok(NULL, "\n"); + } + g_free(text); + + if (n == 0) { + gtk_label_set_text(GTK_LABEL(label_result), "Chyba: Nepodarilo sa nacitat polynom na 2 mieste."); + return; + } + + // Horner's method + double result = 0.0; + for (int i = 0; i < n; i++) { + result = result * x + coeffs[i]; + } + + char msg[128]; + snprintf(msg, sizeof(msg), "Vysledok je: %.2f", result); + gtk_label_set_text(GTK_LABEL(label_result), msg); +} + +static void activate(GtkApplication *app, gpointer user_data) { + (void)user_data; + + GtkWidget *window = gtk_application_window_new(app); + gtk_window_set_title(GTK_WINDOW(window), "Polynóm kalkulačka"); + gtk_window_set_default_size(GTK_WINDOW(window), 350, 450); + gtk_container_set_border_width(GTK_CONTAINER(window), 16); + + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); + gtk_container_add(GTK_CONTAINER(window), box); + + // X input + GtkWidget *lbl_x = gtk_label_new("Hodnota x:"); + gtk_widget_set_halign(lbl_x, GTK_ALIGN_START); + gtk_box_pack_start(GTK_BOX(box), lbl_x, FALSE, FALSE, 0); + + entry_x = gtk_entry_new(); + gtk_entry_set_placeholder_text(GTK_ENTRY(entry_x), "napr. 4 alebo 2.5"); + gtk_box_pack_start(GTK_BOX(box), entry_x, FALSE, FALSE, 0); + + // Coefficients input + GtkWidget *lbl_c = gtk_label_new("Koeficienty (každý na novom riadku, od najvyššieho rádu):"); + gtk_widget_set_halign(lbl_c, GTK_ALIGN_START); + gtk_label_set_line_wrap(GTK_LABEL(lbl_c), TRUE); + gtk_box_pack_start(GTK_BOX(box), lbl_c, FALSE, FALSE, 0); + + GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scroll), 150); + gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0); + + text_coeffs = gtk_text_view_new(); + gtk_text_view_set_monospace(GTK_TEXT_VIEW(text_coeffs), TRUE); + gtk_container_add(GTK_CONTAINER(scroll), text_coeffs); + + // Calculate button + GtkWidget *btn = gtk_button_new_with_label("Vypočítať"); + g_signal_connect(btn, "clicked", G_CALLBACK(calculate), NULL); + gtk_box_pack_start(GTK_BOX(box), btn, FALSE, FALSE, 0); + + // Result label + label_result = gtk_label_new("Vysledok sa zobrazí tu."); + gtk_widget_set_halign(label_result, GTK_ALIGN_START); + gtk_label_set_selectable(GTK_LABEL(label_result), TRUE); + + // Style the result label + GtkStyleContext *ctx = gtk_widget_get_style_context(label_result); + GtkCssProvider *provider = gtk_css_provider_new(); + gtk_css_provider_load_from_data(provider, "label { font-size: 16px; font-weight: bold; }", -1, NULL); + gtk_style_context_add_provider(ctx, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER); + + gtk_box_pack_start(GTK_BOX(box), label_result, FALSE, FALSE, 0); + + gtk_widget_show_all(window); +} + +int main(int argc, char **argv) { + GtkApplication *app = gtk_application_new("sk.tuke.pvjc.polynom", G_APPLICATION_DEFAULT_FLAGS); + g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); + int status = g_application_run(G_APPLICATION(app), argc, argv); + g_object_unref(app); + return status; +} diff --git a/du2/gui b/du2/gui new file mode 100755 index 0000000..2119eb3 Binary files /dev/null and b/du2/gui differ diff --git a/du2/gui.c b/du2/gui.c new file mode 100644 index 0000000..66d641c --- /dev/null +++ b/du2/gui.c @@ -0,0 +1,259 @@ +#include +#include +#include +#include +#include +#include + +#define MAX_STUDENTS 1024 +#define MAX_NAME 256 + +typedef struct { + char name[MAX_NAME]; + int votes; +} Student; + +static GtkWidget *text_input; +static GtkWidget *text_output; +static GtkWidget *drawing_area; + +static Student chart_students[MAX_STUDENTS]; +static int chart_count = 0; + +static const double bar_colors[][3] = { + {0.96, 0.76, 0.05}, + {0.75, 0.75, 0.75}, + {0.80, 0.50, 0.20}, + {0.26, 0.53, 0.96}, + {0.20, 0.78, 0.35}, + {0.90, 0.30, 0.30}, + {0.60, 0.20, 0.80}, + {0.10, 0.70, 0.80}, +}; +#define NUM_COLORS 8 + +static int find_student(Student *students, int count, const char *name) { + for (int i = 0; i < count; i++) + if (strcmp(students[i].name, name) == 0) return i; + return -1; +} + +static int cmp(const void *a, const void *b) { + const Student *sa = (const Student *)a; + const Student *sb = (const Student *)b; + if (sb->votes != sa->votes) return sb->votes - sa->votes; + return strcmp(sa->name, sb->name); +} + +static void set_output(const char *text) { + GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_output)); + gtk_text_buffer_set_text(buf, text, -1); +} + +static gboolean on_draw(GtkWidget *widget, cairo_t *cr, gpointer data) { + (void)data; + int width = gtk_widget_get_allocated_width(widget); + int height = gtk_widget_get_allocated_height(widget); + + // White background to match GTK theme + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); + cairo_paint(cr); + + if (chart_count == 0) { + cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); + cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_ITALIC, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cr, 13); + cairo_move_to(cr, 20, height / 2.0); + cairo_show_text(cr, "Zadajte hlasy a kliknite Spočítať"); + return FALSE; + } + + int margin_left = 20, margin_right = 20, margin_top = 30, margin_bottom = 90; + int max_votes = chart_students[0].votes; + int n = chart_count > 20 ? 20 : chart_count; + + // Calculate total votes for percentage + int total_votes = 0; + for (int i = 0; i < n; i++) total_votes += chart_students[i].votes; + + // Draw total votes at the top + cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); + cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size(cr, 12); + char total_str[64]; + snprintf(total_str, sizeof(total_str), "Celkový počet hlasov: %d", total_votes); + cairo_text_extents_t te; + cairo_text_extents(cr, total_str, &te); + cairo_move_to(cr, (width - te.width) / 2.0, 18); + cairo_show_text(cr, total_str); + + double bar_area_w = width - margin_left - margin_right; + double bar_area_h = height - margin_top - margin_bottom; + double slot = bar_area_w / n; + double bar_w = slot - 6; + + for (int i = 0; i < n; i++) { + double bar_h = (bar_area_h * chart_students[i].votes) / (double)max_votes; + double x = margin_left + i * slot + 3; + double y = margin_top + bar_area_h - bar_h; + + int ci = i < 3 ? i : (3 + (i % (NUM_COLORS - 3))); + cairo_set_source_rgb(cr, bar_colors[ci][0], bar_colors[ci][1], bar_colors[ci][2]); + cairo_rectangle(cr, x, y, bar_w, bar_h); + cairo_fill(cr); + + // Vote count and percentage above bar + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size(cr, 10); + char vs[32]; + double pct = 100.0 * chart_students[i].votes / total_votes; + snprintf(vs, sizeof(vs), "%d (%.1f%%)", chart_students[i].votes, pct); + cairo_text_extents_t ext; + cairo_text_extents(cr, vs, &ext); + // If bar is wide enough, center above it; else rotate + if (ext.width < bar_w) { + cairo_move_to(cr, x + (bar_w - ext.width) / 2.0, y - 5); + cairo_show_text(cr, vs); + } else { + cairo_save(cr); + cairo_translate(cr, x + bar_w / 2.0, y - 5); + cairo_rotate(cr, -G_PI / 4.0); + cairo_move_to(cr, 0, 0); + cairo_show_text(cr, vs); + cairo_restore(cr); + } + + // Name horizontal, centered below bar, clipped to slot width + cairo_save(cr); + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cr, 10); + + char short_name[28]; + // Truncate name to fit slot + strncpy(short_name, chart_students[i].name, sizeof(short_name) - 1); + short_name[sizeof(short_name) - 1] = '\0'; + cairo_text_extents_t ne; + cairo_text_extents(cr, short_name, &ne); + // Shorten until it fits + while (ne.width > slot - 4 && strlen(short_name) > 3) { + short_name[strlen(short_name) - 1] = '\0'; + short_name[strlen(short_name) - 1] = '~'; + cairo_text_extents(cr, short_name, &ne); + } + double name_x = x + (bar_w - ne.width) / 2.0; + cairo_move_to(cr, name_x, height - margin_bottom + 14); + cairo_show_text(cr, short_name); + cairo_restore(cr); + } + return FALSE; +} + +static void calculate(GtkWidget *widget, gpointer data) { + (void)widget; (void)data; + + GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_input)); + GtkTextIter start, end; + gtk_text_buffer_get_start_iter(buf, &start); + gtk_text_buffer_get_end_iter(buf, &end); + char *text = gtk_text_buffer_get_text(buf, &start, &end, FALSE); + + Student students[MAX_STUDENTS]; + int count = 0, loaded = 0; + + char *line = strtok(text, "\n"); + while (line != NULL) { + if (strlen(line) == 0 || line[0] == '\r') { line = strtok(NULL, "\n"); continue; } + int votes; char name[MAX_NAME]; + if (sscanf(line, "%d %255[^\n\r]", &votes, name) != 2 || votes <= 0) break; + loaded++; + int idx = find_student(students, count, name); + if (idx >= 0) { students[idx].votes += votes; } + else if (count < MAX_STUDENTS) { strncpy(students[count].name, name, MAX_NAME-1); students[count].votes = votes; count++; } + line = strtok(NULL, "\n"); + } + g_free(text); + + if (loaded == 0) { set_output("Nepodarilo nacitat nic"); chart_count = 0; gtk_widget_queue_draw(drawing_area); return; } + + qsort(students, count, sizeof(Student), cmp); + chart_count = count; + memcpy(chart_students, students, count * sizeof(Student)); + gtk_widget_queue_draw(drawing_area); + + char output[MAX_STUDENTS * (MAX_NAME + 16)]; + int pos = 0; + pos += snprintf(output + pos, sizeof(output) - pos, "Vysledky:\n"); + for (int i = 0; i < count; i++) + pos += snprintf(output + pos, sizeof(output) - pos, "%d %s\n", students[i].votes, students[i].name); + set_output(output); +} + +static void clear_all(GtkWidget *widget, gpointer data) { + (void)widget; (void)data; + gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_input)), "", -1); + set_output(""); + chart_count = 0; + gtk_widget_queue_draw(drawing_area); +} + +static void activate(GtkApplication *app, gpointer user_data) { + (void)user_data; + GtkWidget *window = gtk_application_window_new(app); + gtk_window_set_title(GTK_WINDOW(window), "Anketa Študent roka"); + gtk_window_set_default_size(GTK_WINDOW(window), 900, 650); + gtk_container_set_border_width(GTK_CONTAINER(window), 12); + + GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12); + gtk_container_add(GTK_CONTAINER(window), hbox); + + // Left panel + GtkWidget *left = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + gtk_box_pack_start(GTK_BOX(hbox), left, FALSE, FALSE, 0); + gtk_widget_set_size_request(left, 280, -1); + + gtk_box_pack_start(GTK_BOX(left), gtk_label_new("Hlasy (počet meno):"), FALSE, FALSE, 0); + GtkWidget *scroll_in = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scroll_in), 220); + gtk_box_pack_start(GTK_BOX(left), scroll_in, TRUE, TRUE, 0); + text_input = gtk_text_view_new(); + gtk_text_view_set_monospace(GTK_TEXT_VIEW(text_input), TRUE); + gtk_container_add(GTK_CONTAINER(scroll_in), text_input); + + GtkWidget *btn_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_box_pack_start(GTK_BOX(left), btn_box, FALSE, FALSE, 0); + GtkWidget *btn_calc = gtk_button_new_with_label("Spočítať hlasy"); + g_signal_connect(btn_calc, "clicked", G_CALLBACK(calculate), NULL); + gtk_box_pack_start(GTK_BOX(btn_box), btn_calc, TRUE, TRUE, 0); + GtkWidget *btn_clear = gtk_button_new_with_label("Vymazať"); + g_signal_connect(btn_clear, "clicked", G_CALLBACK(clear_all), NULL); + gtk_box_pack_start(GTK_BOX(btn_box), btn_clear, FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(left), gtk_label_new("Výsledky:"), FALSE, FALSE, 0); + GtkWidget *scroll_out = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scroll_out), 180); + gtk_box_pack_start(GTK_BOX(left), scroll_out, TRUE, TRUE, 0); + text_output = gtk_text_view_new(); + gtk_text_view_set_monospace(GTK_TEXT_VIEW(text_output), TRUE); + gtk_text_view_set_editable(GTK_TEXT_VIEW(text_output), FALSE); + gtk_container_add(GTK_CONTAINER(scroll_out), text_output); + + // Right panel: chart + GtkWidget *right = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4); + gtk_box_pack_start(GTK_BOX(hbox), right, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(right), gtk_label_new("Graf hlasov:"), FALSE, FALSE, 0); + drawing_area = gtk_drawing_area_new(); + gtk_box_pack_start(GTK_BOX(right), drawing_area, TRUE, TRUE, 0); + g_signal_connect(drawing_area, "draw", G_CALLBACK(on_draw), NULL); + + gtk_widget_show_all(window); +} + +int main(int argc, char **argv) { + GtkApplication *app = gtk_application_new("sk.tuke.pvjc.anketa", G_APPLICATION_DEFAULT_FLAGS); + g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); + int status = g_application_run(G_APPLICATION(app), argc, argv); + g_object_unref(app); + return status; +} diff --git a/du2/gui_backup.c b/du2/gui_backup.c new file mode 100644 index 0000000..9745b7d --- /dev/null +++ b/du2/gui_backup.c @@ -0,0 +1,229 @@ +#include +#include +#include +#include +#include +#include + +#define MAX_STUDENTS 1024 +#define MAX_NAME 256 + +typedef struct { + char name[MAX_NAME]; + int votes; +} Student; + +static GtkWidget *text_input; +static GtkWidget *text_output; +static GtkWidget *drawing_area; + +static Student chart_students[MAX_STUDENTS]; +static int chart_count = 0; + +static const double bar_colors[][3] = { + {0.96, 0.76, 0.05}, + {0.75, 0.75, 0.75}, + {0.80, 0.50, 0.20}, + {0.26, 0.53, 0.96}, + {0.20, 0.78, 0.35}, + {0.90, 0.30, 0.30}, + {0.60, 0.20, 0.80}, + {0.10, 0.70, 0.80}, +}; +#define NUM_COLORS 8 + +static int find_student(Student *students, int count, const char *name) { + for (int i = 0; i < count; i++) + if (strcmp(students[i].name, name) == 0) return i; + return -1; +} + +static int cmp(const void *a, const void *b) { + const Student *sa = (const Student *)a; + const Student *sb = (const Student *)b; + if (sb->votes != sa->votes) return sb->votes - sa->votes; + return strcmp(sa->name, sb->name); +} + +static void set_output(const char *text) { + GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_output)); + gtk_text_buffer_set_text(buf, text, -1); +} + +static gboolean on_draw(GtkWidget *widget, cairo_t *cr, gpointer data) { + (void)data; + int width = gtk_widget_get_allocated_width(widget); + int height = gtk_widget_get_allocated_height(widget); + + cairo_set_source_rgb(cr, 0.15, 0.15, 0.15); + cairo_paint(cr); + + if (chart_count == 0) { + cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); + cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_ITALIC, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cr, 13); + cairo_move_to(cr, 20, height / 2.0); + cairo_show_text(cr, "Zadajte hlasy a kliknite Spočítať"); + return FALSE; + } + + int margin_left = 20, margin_right = 20, margin_top = 24, margin_bottom = 70; + int max_votes = chart_students[0].votes; + int n = chart_count > 20 ? 20 : chart_count; + + double bar_area_w = width - margin_left - margin_right; + double bar_area_h = height - margin_top - margin_bottom; + double slot = bar_area_w / n; + double bar_w = slot - 6; + + for (int i = 0; i < n; i++) { + double bar_h = (bar_area_h * chart_students[i].votes) / (double)max_votes; + double x = margin_left + i * slot + 3; + double y = margin_top + bar_area_h - bar_h; + + int ci = i < 3 ? i : (3 + (i % (NUM_COLORS - 3))); + cairo_set_source_rgb(cr, bar_colors[ci][0], bar_colors[ci][1], bar_colors[ci][2]); + cairo_rectangle(cr, x, y, bar_w, bar_h); + cairo_fill(cr); + + // Vote count on top + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size(cr, 11); + char vs[16]; + snprintf(vs, sizeof(vs), "%d", chart_students[i].votes); + cairo_text_extents_t ext; + cairo_text_extents(cr, vs, &ext); + cairo_move_to(cr, x + (bar_w - ext.width) / 2.0, y - 5); + cairo_show_text(cr, vs); + + // Name rotated below bar + cairo_save(cr); + cairo_translate(cr, x + bar_w / 2.0, height - margin_bottom + 10); + cairo_rotate(cr, -G_PI / 4.0); + cairo_set_source_rgb(cr, 0.9, 0.9, 0.9); + cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cr, 10); + char short_name[24]; + if (strlen(chart_students[i].name) > 20) { + strncpy(short_name, chart_students[i].name, 19); + short_name[19] = '\0'; + strcat(short_name, "~"); + } else { + strncpy(short_name, chart_students[i].name, sizeof(short_name) - 1); + short_name[sizeof(short_name)-1] = '\0'; + } + cairo_move_to(cr, 0, 0); + cairo_show_text(cr, short_name); + cairo_restore(cr); + } + return FALSE; +} + +static void calculate(GtkWidget *widget, gpointer data) { + (void)widget; (void)data; + + GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_input)); + GtkTextIter start, end; + gtk_text_buffer_get_start_iter(buf, &start); + gtk_text_buffer_get_end_iter(buf, &end); + char *text = gtk_text_buffer_get_text(buf, &start, &end, FALSE); + + Student students[MAX_STUDENTS]; + int count = 0, loaded = 0; + + char *line = strtok(text, "\n"); + while (line != NULL) { + if (strlen(line) == 0 || line[0] == '\r') { line = strtok(NULL, "\n"); continue; } + int votes; char name[MAX_NAME]; + if (sscanf(line, "%d %255[^\n\r]", &votes, name) != 2 || votes <= 0) break; + loaded++; + int idx = find_student(students, count, name); + if (idx >= 0) { students[idx].votes += votes; } + else if (count < MAX_STUDENTS) { strncpy(students[count].name, name, MAX_NAME-1); students[count].votes = votes; count++; } + line = strtok(NULL, "\n"); + } + g_free(text); + + if (loaded == 0) { set_output("Nepodarilo nacitat nic"); chart_count = 0; gtk_widget_queue_draw(drawing_area); return; } + + qsort(students, count, sizeof(Student), cmp); + chart_count = count; + memcpy(chart_students, students, count * sizeof(Student)); + gtk_widget_queue_draw(drawing_area); + + char output[MAX_STUDENTS * (MAX_NAME + 16)]; + int pos = 0; + pos += snprintf(output + pos, sizeof(output) - pos, "Vysledky:\n"); + for (int i = 0; i < count; i++) + pos += snprintf(output + pos, sizeof(output) - pos, "%d %s\n", students[i].votes, students[i].name); + set_output(output); +} + +static void clear_all(GtkWidget *widget, gpointer data) { + (void)widget; (void)data; + gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_input)), "", -1); + set_output(""); + chart_count = 0; + gtk_widget_queue_draw(drawing_area); +} + +static void activate(GtkApplication *app, gpointer user_data) { + (void)user_data; + GtkWidget *window = gtk_application_window_new(app); + gtk_window_set_title(GTK_WINDOW(window), "Anketa Študent roka"); + gtk_window_set_default_size(GTK_WINDOW(window), 900, 650); + gtk_container_set_border_width(GTK_CONTAINER(window), 12); + + GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12); + gtk_container_add(GTK_CONTAINER(window), hbox); + + // Left panel + GtkWidget *left = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + gtk_box_pack_start(GTK_BOX(hbox), left, FALSE, FALSE, 0); + gtk_widget_set_size_request(left, 280, -1); + + gtk_box_pack_start(GTK_BOX(left), gtk_label_new("Hlasy (počet meno):"), FALSE, FALSE, 0); + GtkWidget *scroll_in = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scroll_in), 220); + gtk_box_pack_start(GTK_BOX(left), scroll_in, TRUE, TRUE, 0); + text_input = gtk_text_view_new(); + gtk_text_view_set_monospace(GTK_TEXT_VIEW(text_input), TRUE); + gtk_container_add(GTK_CONTAINER(scroll_in), text_input); + + GtkWidget *btn_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_box_pack_start(GTK_BOX(left), btn_box, FALSE, FALSE, 0); + GtkWidget *btn_calc = gtk_button_new_with_label("Spočítať hlasy"); + g_signal_connect(btn_calc, "clicked", G_CALLBACK(calculate), NULL); + gtk_box_pack_start(GTK_BOX(btn_box), btn_calc, TRUE, TRUE, 0); + GtkWidget *btn_clear = gtk_button_new_with_label("Vymazať"); + g_signal_connect(btn_clear, "clicked", G_CALLBACK(clear_all), NULL); + gtk_box_pack_start(GTK_BOX(btn_box), btn_clear, FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(left), gtk_label_new("Výsledky:"), FALSE, FALSE, 0); + GtkWidget *scroll_out = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scroll_out), 180); + gtk_box_pack_start(GTK_BOX(left), scroll_out, TRUE, TRUE, 0); + text_output = gtk_text_view_new(); + gtk_text_view_set_monospace(GTK_TEXT_VIEW(text_output), TRUE); + gtk_text_view_set_editable(GTK_TEXT_VIEW(text_output), FALSE); + gtk_container_add(GTK_CONTAINER(scroll_out), text_output); + + // Right panel: chart + GtkWidget *right = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4); + gtk_box_pack_start(GTK_BOX(hbox), right, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(right), gtk_label_new("Graf hlasov:"), FALSE, FALSE, 0); + drawing_area = gtk_drawing_area_new(); + gtk_box_pack_start(GTK_BOX(right), drawing_area, TRUE, TRUE, 0); + g_signal_connect(drawing_area, "draw", G_CALLBACK(on_draw), NULL); + + gtk_widget_show_all(window); +} + +int main(int argc, char **argv) { + GtkApplication *app = gtk_application_new("sk.tuke.pvjc.anketa", G_APPLICATION_DEFAULT_FLAGS); + g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); + int status = g_application_run(G_APPLICATION(app), argc, argv); + g_object_unref(app); + return status; +} diff --git a/du2/program b/du2/program new file mode 100755 index 0000000..eab24bf Binary files /dev/null and b/du2/program differ diff --git a/du3/program b/du3/program new file mode 100755 index 0000000..5ee3340 Binary files /dev/null and b/du3/program differ diff --git a/du4/snake.c b/du4/snake.c new file mode 100644 index 0000000..762d2d0 --- /dev/null +++ b/du4/snake.c @@ -0,0 +1,104 @@ +#include +#include "snake.h" + +struct snake* add_snake(struct snake* snake, int x, int y) { + struct snake* new_part = (struct snake*)malloc(sizeof(struct snake)); + if (new_part == NULL) { + return snake; + } + new_part->x = x; + new_part->y = y; + new_part->next = snake; + + return new_part; +} + +struct snake* remove_snake(struct snake* snake) { + if (snake == NULL) { + return NULL; + } + if (snake->next == NULL) { + free(snake); + return NULL; + } + + struct snake* current = snake; + while (current->next->next != NULL) { + current = current->next; + } + + free(current->next); + current->next = NULL; + + return snake; +} + +int is_snake(struct snake* snake, int x, int y) { + struct snake* current = snake; + while (current != NULL) { + if (current->x == x && current->y == y) { + return 1; + } + current = current->next; + } + return 0; +} + +void free_snake(struct snake* sn) { + while (sn != NULL) { + struct snake* temp = sn; + sn = sn->next; + free(temp); + } +} + +int step_state(struct state* state) { + if (state == NULL || state->snake == NULL) { + return END_USER; + } + + int new_x = state->snake->x + state->sx; + int new_y = state->snake->y + state->sy; + + if (new_x < 0 || new_x >= state->width || new_y < 0 || new_y >= state->height) { + return END_WALL; + } + + int food_index = -1; + int items_left = 0; + + for (int i = 0; i < FOOD_COUNT; i++) { + if (state->foodx[i] == new_x && state->foody[i] == new_y) { + food_index = i; + } else if (state->foodx[i] >= 0 && state->foody[i] >= 0) { + items_left++; + } + } + + if (food_index >= 0) { + state->foodx[food_index] = -1; + state->foody[food_index] = -1; + + if (is_snake(state->snake, new_x, new_y)) { + state->snake = add_snake(state->snake, new_x, new_y); + return END_SNAKE; + } + + state->snake = add_snake(state->snake, new_x, new_y); + + if (items_left == 0) { + return END_FOOD; + } + return END_CONTINUE; + } else { + state->snake = remove_snake(state->snake); + + if (is_snake(state->snake, new_x, new_y)) { + state->snake = add_snake(state->snake, new_x, new_y); + return END_SNAKE; + } + + state->snake = add_snake(state->snake, new_x, new_y); + return END_CONTINUE; + } +} diff --git a/du4/snake.h b/du4/snake.h new file mode 100644 index 0000000..c0ab1ad --- /dev/null +++ b/du4/snake.h @@ -0,0 +1,112 @@ +#ifndef snake_h_INCLUDED +#define snake_h_INCLUDED + +// Number of food items on the plane +#define FOOD_COUNT 5 + +/** + * One part of the snake; + * + * The snake is a linked list; + */ + +struct snake { + // x position of the snake part + int x; + // y position of the snake part + int y; + // Pointer to the next snake part. + // The last part of the snake has NULL pointer to the next part. + struct snake* next; +}; + +// End game reason constants, return value of step_state +enum endgame { + // Continue the game + END_CONTINUE = 0, + // Snake hit a wall + END_WALL, + // Snake hit itself + END_SNAKE, + // No food left + END_FOOD, + // Other reason to end + END_USER +}; + +/** + * State of the game. + * + * The state consists of the snake, its speed and food on the plane. + * + * The snake is a linked list of snake parts. + * + * Speed vector is a vector added to the last head position to create a new head. + * + * Food are points on the plane. Food with negative coordinates meads food is already eaten. + */ + +struct state { + // Snake as a linked list + struct snake* snake; + // X of the food positions + int foodx[FOOD_COUNT]; + // Y of the food positions + int foody[FOOD_COUNT]; + int sx; + int sy; + int width; + int height; +}; + +/** + * Add a new snake part with given position. The new snake part becomes the new head. + * + * @param head of the snake. + * @param x coordinate of the new head; + * @param y coordinate of the new head. + * @return new head of the snake. + */ +struct snake* add_snake(struct snake* snake,int x,int y); + +/** + * Remove the last snake part. + * The last snake part should always have NULL next pointer. + * + * @param head of the snake. + * @return new head of the snake. + */ +struct snake* remove_snake(struct snake* snake); + +/** + * Finds out if given coordinates are part of the snake. + * @param snake + * @param x coordinate to search in snake + * @param y coordinate to search in snake + * @return True, if there is a snake part with coordinates x,y. False otherwise + * + */ +int is_snake(struct snake* snake,int x, int y); +/** + * Remove and free each snake part; + * @param head of the snake. + */ +void free_snake(struct snake* sn); +/** + * Change game state. + * + * The function shoud calculate new posision of the snake head + * from the current position and speed vector. + * Then it should modify snake parst or food coordinates according to the rules: + * + * - If the new position is on the snake, end the game, return END_SNAKE. + * - If the new position is on the food, mark food as eaten + * (set its coordinates to -1) and add new snake part on the position of the food. If there is no food left, return END_FOOD. else return END_CONTINUE. + * - If the new position is on the plane, add new snake part on the new position and remove the last part of the snake, return END_CONTINUE. + * + * @param current state of the game + * @return reason to end the game according to enum endgame. + */ +int step_state(struct state* state); + +#endif // snake_h_INCLUDED