du4
This commit is contained in:
parent
9f313e864b
commit
6a047a3e64
BIN
a2/test_main
Executable file
BIN
a2/test_main
Executable file
Binary file not shown.
36
a2/test_main.c
Normal file
36
a2/test_main.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#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;
|
||||
}
|
||||
127
du1/gui.c
Normal file
127
du1/gui.c
Normal file
@ -0,0 +1,127 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// 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;
|
||||
}
|
||||
259
du2/gui.c
Normal file
259
du2/gui.c
Normal file
@ -0,0 +1,259 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <cairo.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
229
du2/gui_backup.c
Normal file
229
du2/gui_backup.c
Normal file
@ -0,0 +1,229 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <cairo.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
BIN
du2/program
Executable file
BIN
du2/program
Executable file
Binary file not shown.
BIN
du3/program
Executable file
BIN
du3/program
Executable file
Binary file not shown.
104
du4/snake.c
Normal file
104
du4/snake.c
Normal file
@ -0,0 +1,104 @@
|
||||
#include <stdlib.h>
|
||||
#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;
|
||||
}
|
||||
}
|
||||
112
du4/snake.h
Normal file
112
du4/snake.h
Normal file
@ -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
|
||||
Loading…
Reference in New Issue
Block a user