klavaro  3.13
About: Klavaro is a touch typing tutor program.
  Fossies Dox: klavaro-3.13.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

plot.c
Go to the documentation of this file.
1 /**************************************************************************/
2 /* Klavaro - a flexible touch typing tutor */
3 /* Copyright (C) 2005-2021 Felipe Emmanuel Ferreira de Castro */
4 /* */
5 /* This file is part of Klavaro, which is a free software: you can */
6 /* redistribute it and/or modify it under the terms of the GNU General */
7 /* Public License as published by the Free Software Foundation, either */
8 /* version 3 of the License, or (at your option) any later version. */
9 /* */
10 /* Klavaro is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
13 /* GNU General Public License for more details (in the file COPYING). */
14 /* You should have received a copy of the GNU General Public License */
15 /* along with Klavaro. If not, see <https://www.gnu.org/licenses/> */
16 /**************************************************************************/
17 
18 /*
19  * Charts management
20  */
21 #include <math.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <locale.h>
25 #include <glib.h>
26 #include <glib/gstdio.h>
27 #include <gdk/gdk.h>
28 #include <gtk/gtk.h>
29 #include <gtkdatabox.h>
30 #include <gtkdatabox_grid.h>
31 #include <gtkdatabox_lines.h>
32 #include <gtkdatabox_points.h>
33 #include <gtkdatabox_bars.h>
34 
35 #include "auxiliar.h"
36 #include "main.h"
37 #include "callbacks.h"
38 #include "tutor.h"
39 #include "basic.h"
40 #include "accuracy.h"
41 #include "keyboard.h"
42 #include "translation.h"
43 #include "plot.h"
44 
45 static struct
46 {
47  GtkWidget *databox;
48  GtkWidget *gtkgrid;
49 
50  struct
51  {
52  gfloat x[DATA_POINTS+1];
53  gfloat y[DATA_POINTS+1];
54  } data;
55  GtkDataboxGraph *point_kernel;
56  GtkDataboxGraph *point_frame;
57  GtkDataboxGraph *line_kernel;
58  GtkDataboxGraph *line_frame;
59  GtkDataboxGraph *line_outter;
60 
61  struct
62  {
63  gfloat x[1];
64  gfloat y[1];
65  } mark;
66  GtkDataboxGraph *point_marker;
67 
68  struct
69  {
70  gfloat x[2];
71  gfloat y[2];
72  } goal;
73  GtkDataboxGraph *line_goal;
74  GtkDataboxGraph *grid;
75  GtkWidget * label_y[MAX_Y_LABELS];
76 
77  struct
78  {
79  gfloat x[2];
80  gfloat y[2];
81  } lim;
82  GtkDataboxGraph *limits;
83 } plot;
84 
85 gfloat accur[DATA_POINTS+1];
86 gfloat velo[DATA_POINTS+1];
87 gfloat fluid[DATA_POINTS+1];
88 gfloat score[DATA_POINTS+1];
89 gchar date[DATA_POINTS+1][20];
90 gchar hour[DATA_POINTS+1][20];
92 gchar lesson[DATA_POINTS+1][299];
93 gchar language[DATA_POINTS+1][80+1];
94 glong n_points;
95 gint plot_type; /* used to communicate the plotting type, for updating the cursor marker, etc */
96 
97 gint lesson_n;
98 
99 /*******************************************************************************
100  * Interface functions
101  */
102 GtkWidget *
104 {
105  return plot.databox;
106 }
107 
108 /*******************************************************************************
109  * Private functions
110  */
111 
112 static void
114 {
115  gint i;
116  gchar *tcolor;
117  GdkRGBA color;
118  GdkRGBA color_black;
119  GtkDatabox *box;
120 
121  box = GTK_DATABOX (plot.databox);
123  if (n_points < 1)
124  return;
126  for (i = 0; i < DATA_POINTS; i++)
127  {
128  if (i < n_points)
129  plot.data.y[i] = accur_wrong_get (i);
130  else
131  plot.data.y[i] = 0;
132  }
133 
134  /* Format the chart
135  */
136  plot.mark.x[0] = -7;
137  plot.mark.y[0] = -7;
138  plot.lim.x[0] = 0;
139  plot.lim.x[1] = DATA_POINTS + 2;
140  plot.lim.y[0] = 0;
141  plot.lim.y[1] = 1.05 * accur_wrong_get (0);
142  if (plot.lim.y[1] < 1)
143  plot.lim.y[1] = 1.05;
144 
145  /* Plot color */
146  if (main_altcolor_get_boolean ("colors", "altcolor"))
147  tcolor = main_altcolor_get_string ("colors", "char_untouched_fg");
148  else
149  tcolor = main_preferences_get_string ("colors", "char_untouched_fg");
150  gdk_rgba_parse (&color_black, tcolor);
151  gdk_rgba_parse (&color, PLOT_GREEN_2);
152 
153  /* Point limits */
154  plot.limits = gtk_databox_points_new (2, plot.lim.x, plot.lim.y, &color_black, 1);
155  gtk_databox_graph_add (box, plot.limits);
156  gtk_databox_auto_rescale (box, 0.0);
157 
158  /* Bar kernel
159  */
160  plot.point_kernel = gtk_databox_bars_new (i, plot.data.x, plot.data.y, &color, 5);
161  gtk_databox_graph_add (box, plot.point_kernel);
162 
163  /* Bar frame
164  */
165  plot.point_frame = gtk_databox_bars_new (i, plot.data.x, plot.data.y, &color_black, 7);
166  gtk_databox_graph_add (box, plot.point_frame);
167 
168  /* Data marker
169  */
170  plot.point_marker = gtk_databox_points_new (1, plot.mark.x, plot.mark.y, &color_black, 7);
171  gtk_databox_graph_add (box, plot.point_marker);
172 
173  /* Redraw the plot
174  */
175  gtk_widget_show_all (plot.gtkgrid);
176 }
177 
178 static void
180 {
181  gint i;
182  gchar *tcolor;
183  GdkRGBA color;
184  GdkRGBA color_black;
185  GtkDatabox *box;
186 
187  box = GTK_DATABOX (plot.databox);
189  if (n_points < 1)
190  return;
191  accur_ttime_sort ();
192  for (i = 0; i < DATA_POINTS; i++)
193  {
194  if (i < n_points)
195  plot.data.y[i] = accur_profi_aver (i);
196  else
197  plot.data.y[i] = 0;
198  }
199 
200  /* Format the chart
201  */
202  plot.mark.x[0] = -7;
203  plot.mark.y[0] = -7;
204  plot.lim.x[0] = 0;
205  plot.lim.x[1] = DATA_POINTS + 2;
206  plot.lim.y[0] = 0;
207  plot.lim.y[1] = 1.05 * accur_profi_aver (0);
208  if (plot.lim.y[1] < 0.01)
209  plot.lim.y[1] = 0.0105;
210 
211  /* Plot color */
212  if (main_altcolor_get_boolean ("colors", "altcolor"))
213  tcolor = main_altcolor_get_string ("colors", "char_untouched_fg");
214  else
215  tcolor = main_preferences_get_string ("colors", "char_untouched_fg");
216  gdk_rgba_parse (&color_black, tcolor);
217  gdk_rgba_parse (&color, PLOT_PURPLE);
218 
219  /* Point limits */
220  plot.limits = gtk_databox_points_new (2, plot.lim.x, plot.lim.y, &color_black, 1);
221  gtk_databox_graph_add (box, plot.limits);
222  gtk_databox_auto_rescale (box, 0.0);
223 
224  /* Bar kernel
225  */
226  plot.point_kernel = gtk_databox_bars_new (i, plot.data.x, plot.data.y, &color, 5);
227  gtk_databox_graph_add (box, plot.point_kernel);
228 
229  /* Bar frame
230  */
231  plot.point_frame = gtk_databox_bars_new (i, plot.data.x, plot.data.y, &color_black, 7);
232  gtk_databox_graph_add (box, plot.point_frame);
233 
234  /* Data marker
235  */
236  plot.point_marker = gtk_databox_points_new (1, plot.mark.x, plot.mark.y, &color_black, 7);
237  gtk_databox_graph_add (box, plot.point_marker);
238 
239  /* Redraw the plot
240  */
241  gtk_widget_show_all (plot.gtkgrid);
242 }
243 
244 /*******************************************************************************
245  * Functions to manage the plottings on the progress window
246  */
247 void
249 {
250  static gboolean inited = FALSE;
251  static GtkCssProvider *css;
252  GtkStyleContext *sc;
253  gchar *tcolor;
254  gint i;
255 
256  if (inited)
257  return;
258  inited = TRUE;
259 
260  /* Initialize X data
261  */
262  for (i = 0; i < DATA_POINTS; i++)
263  plot.data.x[i] = i + 1;
264 
265  /* Data Box
266  */
267  gtk_databox_create_box_with_scrollbars_and_rulers (&plot.databox, &plot.gtkgrid, FALSE, FALSE, FALSE, FALSE);
268  gtk_container_add (GTK_CONTAINER (get_wg ("frame_stat")), plot.gtkgrid);
269  g_signal_connect (G_OBJECT (plot.databox), "motion_notify_event", G_CALLBACK (on_databox_hovered), NULL);
270 
271  if (main_altcolor_get_boolean ("colors", "altcolor"))
272  tcolor = main_altcolor_get_string ("colors", "text_intro_bg");
273  else
274  tcolor = main_preferences_get_string ("colors", "text_intro_bg");
275  gtk_databox_set_bg_color (GTK_DATABOX(plot.databox), tcolor);
276 
277  /* Y labels
278  */
279  for (i = 0; i < MAX_Y_LABELS; i++)
280  {
281  plot.label_y[i] = gtk_label_new ("???");
282  gtk_box_pack_start (GTK_BOX (get_wg ("box_grid_label_y")), plot.label_y[i], TRUE, TRUE, 0);
283  }
284 
285  plot_draw_chart (1);
286 }
287 
288 /**********************************************************************
289  * Plots the statistics
290  */
291 void
292 plot_draw_chart (gint pltype)
293 {
294  gint i, len;
295  gchar *kb_name;
296  gchar *tmp_name;
297  gchar *tmp_locale;
298  gchar *tmp_lang;
299  gchar tmp_str[2000];
300  FILE *fh;
301  gchar *tcolor;
302  GdkRGBA color, color2, color3;
303  GdkRGBA color_black;
304  GtkDatabox *box;
305 
306  box = GTK_DATABOX (plot.databox);
307  /* Blank the chart
308  */
309  n_points = 0;
310  gtk_databox_graph_remove_all (box);
311  gtk_widget_hide (plot.gtkgrid);
312 
313  /* Set plot type for external reference */
314  plot_type = pltype;
315 
316  /* Error frequencies or touch times
317  */
318  gtk_widget_set_tooltip_text (get_wg ("entry_stat_x"), _("Character"));
319  gtk_widget_hide (get_wg ("box_grid_label_y"));
320  if (pltype == 6)
321  {
323  return;
324  }
325  else if (pltype == 7)
326  {
327  plot_touch_times ();
328  return;
329  }
330  gtk_widget_set_tooltip_text (get_wg ("entry_stat_x"), _("Date & Time"));
331  gtk_widget_show (get_wg ("box_grid_label_y"));
332 
333  /* Auxiliar variable to track the lesson to be plot
334  */
335  lesson_n = gtk_spin_button_get_value (GTK_SPIN_BUTTON (get_wg ("spinbutton_stat_lesson")));
336 
337  if (tutor_get_type () == TT_BASIC)
338  {
339  gtk_widget_show (get_wg ("label_stat_lesson"));
340  gtk_widget_show (get_wg ("spinbutton_stat_lesson"));
341  }
342  else
343  {
344  gtk_widget_hide (get_wg ("label_stat_lesson"));
345  gtk_widget_hide (get_wg ("spinbutton_stat_lesson"));
346  }
347 
348  /* Get the file name
349  */
350  if (pltype < 4)
351  tmp_name = g_strconcat (main_path_stats (), G_DIR_SEPARATOR_S "stat_",
352  tutor_get_type_name (), ".txt", NULL);
353  else
354  tmp_name = g_build_filename (main_path_stats (), "scores_fluid.txt", NULL);
355 
356  /* Open the data file
357  */
358  fh = (FILE *) g_fopen (tmp_name, "r");
359  if (!fh)
360  {
361  g_message ("no data yet, no statistic file:\n%s", tmp_name);
362  g_free (tmp_name);
363  return;
364  }
365 
366  /* Change to "C" locale, but keep current language
367  */
368  tmp_lang = trans_get_current_language ();
369  tmp_locale = g_strdup (setlocale (LC_NUMERIC, NULL));
370  if (tmp_locale != NULL)
371  setlocale (LC_NUMERIC, "C");
372 
373  /* Keyboard names must be compared without spaces (may appear in custom files)
374  */
375  kb_name = g_strdup (keyb_get_name ());
376  for (i=0; kb_name[i]; i++)
377  kb_name[i] = (kb_name[i] == ' ') ? '_' : kb_name[i];
378 
379  /* Read the first line (header)
380  */
381  if (!fgets (tmp_str, 2000, fh))
382  {
383  g_message ("no data on the statistic file:\n%s", tmp_name);
384  g_free (tmp_name);
385  fclose (fh);
386  return;
387  }
388  g_free (tmp_name);
389 
390  /* Read the first DATA_POINTS points
391  */
392  for (i = 0; i < DATA_POINTS; i++)
393  plot.data.y[i] = -1000;
394  i = 0;
395  while (1)
396  {
397  gint itens;
398  gchar *lang_extra;
399 
400  language[i][0] = '\0';
401  if (pltype < 4)
402  {
403  itens = fscanf (fh, "%f%f%f%s%s%s\t", &accur[i], &velo[i], &fluid[i],
404  date[i], hour[i], lesson[i]);
405  if (itens != 6) break;
406  }
407  else
408  {
409  itens = fscanf (fh, "%f%s%s%i\t", &score[i], date[i], hour[i], &nchars[i]);
410  if (itens != 4) break;
411  }
412  lang_extra = fgets (language[i], 80, fh);
413  if (language[i][len = (strlen(language[i])-1)] == '\n')
414  language[i][len] = '\0';
415 
416  if (tutor_get_type () == TT_BASIC)
417  {
418  if (g_ascii_strtoll (lesson[i], NULL, 10) != lesson_n)
419  if (lesson_n != 0)
420  continue;
421  if (strcmp (language[i], kb_name) != 0) // in BASIC, language field is the keyboard.
422  continue;
423  }
424  if (tutor_get_type () == TT_ADAPT && strcmp (lesson[i], kb_name) != 0)
425  continue;
426  if (tutor_get_type () == TT_VELO && strcmp (language[i], tmp_lang) != 0)
427  continue;
428  if (tutor_get_type () == TT_FLUID && strcmp (language[i], tmp_lang) != 0)
429  continue;
430  switch (pltype)
431  {
432  case 1:
433  plot.data.y[i] = accur[i];
434  break;
435  case 2:
436  plot.data.y[i] = velo[i];
437  break;
438  case 3:
439  plot.data.y[i] = fluid[i];
440  break;
441  case 4:
442  plot.data.y[i] = score[i];
443  break;
444  }
445  if (++i == DATA_POINTS)
446  break;
447  }
448 
449  /* Read until the end, keeping the last DATA_POINTS points
450  */
451  while (1)
452  {
453  gint itens;
454  gchar *lang_extra;
455 
456  language[i][0] = '\0';
457  if (pltype < 4)
458  {
459  itens = fscanf (fh, "%f%f%f%s%s%s\t", &accur[i], &velo[i], &fluid[i],
460  date[i], hour[i], lesson[i]);
461  if (itens != 6) break;
462  }
463  else
464  {
465  itens = fscanf (fh, "%f%s%s%i\t", &score[i], date[i], hour[i], &nchars[i]);
466  if (itens != 4) break;
467  }
468  lang_extra = fgets (language[i], 80, fh);
469  if (language[i][len = (strlen(language[i])-1)] == '\n')
470  language[i][len] = '\0';
471 
472  if (tutor_get_type () == TT_BASIC)
473  {
474  if (g_ascii_strtoll (lesson[i], NULL, 10) != lesson_n)
475  if (lesson_n != 0)
476  continue;
477  if (strcmp (language[i], kb_name) != 0)
478  continue;
479  }
480  if (tutor_get_type () == TT_ADAPT && strcmp (lesson[i], kb_name) != 0)
481  continue;
482  if (tutor_get_type () == TT_VELO && strcmp (language[i], tmp_lang) != 0)
483  continue;
484  if (tutor_get_type () == TT_FLUID && strcmp (language[i], tmp_lang) != 0)
485  continue;
486  for (i = 0; i < DATA_POINTS - 1; i++)
487  {
488  plot.data.y[i] = plot.data.y[i + 1];
489  strcpy (date[i], date[i + 1]);
490  strcpy (hour[i], hour[i + 1]);
491  }
492  strcpy (date[i], date[i + 1]);
493  strcpy (hour[i], hour[i + 1]);
494 
495  switch (pltype)
496  {
497  case 1:
498  plot.data.y[i] = accur[i + 1];
499  break;
500  case 2:
501  plot.data.y[i] = velo[i + 1];
502  break;
503  case 3:
504  plot.data.y[i] = fluid[i + 1];
505  break;
506  case 4:
507  plot.data.y[i] = score[i + 1];
508  break;
509  }
510  i = DATA_POINTS;
511  }
512  fclose (fh);
513  g_free (kb_name);
514 
515  /* Coming back to the right locale
516  */
517  if (tmp_locale != NULL)
518  setlocale (LC_NUMERIC, tmp_locale);
519  g_free (tmp_locale);
520 
521  if (i == 0)
522  {
523  g_message ("no valid data to plot.");
524  return;
525  }
526  n_points = i;
527 
528  /* Format the chart
529  */
530  plot.mark.x[0] = -7;
531  plot.mark.y[0] = -7;
532  plot.goal.x[0] = plot.lim.x[0] = 0;
533  plot.goal.x[1] = plot.lim.x[1] = DATA_POINTS + 2;
534  plot.lim.y[0] = 0;
535  plot.lim.y[1] = 100;
536 
537  if (main_altcolor_get_boolean ("colors", "altcolor"))
538  tcolor = main_altcolor_get_string ("colors", "char_untouched_fg");
539  else
540  tcolor = main_preferences_get_string ("colors", "char_untouched_fg");
541  gdk_rgba_parse (&color_black, tcolor);
542  switch (pltype)
543  {
544  case 1:
545  plot.lim.y[0] = 60;
546  plot.goal.y[0] = tutor_goal_accuracy ();
547  gdk_rgba_parse (&color, PLOT_GREEN);
548  gdk_rgba_parse (&color2, PLOT_GREEN_2);
549  gdk_rgba_parse (&color3, PLOT_GREEN_3);
550  break;
551  case 2:
552  plot.lim.y[1] = 120;
553  plot.goal.y[0] = tutor_goal_speed ();
554  gdk_rgba_parse (&color, PLOT_RED);
555  gdk_rgba_parse (&color2, PLOT_RED_2);
556  gdk_rgba_parse (&color3, PLOT_RED_3);
557  break;
558  case 3:
559  plot.goal.y[0] = tutor_goal_fluidity ();
560  gdk_rgba_parse (&color, PLOT_BLUE);
561  gdk_rgba_parse (&color2, PLOT_BLUE_2);
562  gdk_rgba_parse (&color3, PLOT_BLUE_3);
563  break;
564  case 4:
565  plot.lim.y[1] = 10;
566  plot.goal.y[0] = -1;
567  gdk_rgba_parse (&color, PLOT_ORANGE);
568  gdk_rgba_parse (&color2, PLOT_ORANGE_2);
569  gdk_rgba_parse (&color3, PLOT_ORANGE_3);
570  }
571  plot.goal.y[1] = plot.goal.y[0];
572 
573  /* Point limits */
574  plot.limits = gtk_databox_points_new (2, plot.lim.x, plot.lim.y, &color_black, 1);
575  gtk_databox_graph_add (box, plot.limits);
576  gtk_databox_auto_rescale (box, 0.0);
577 
578  /* Point kernel */
579  plot.point_kernel = gtk_databox_points_new (i, plot.data.x, plot.data.y, &color, 3);
580  gtk_databox_graph_add (box, plot.point_kernel);
581 
582  /* Point frame */
583  plot.point_frame = gtk_databox_points_new (i, plot.data.x, plot.data.y, &color_black, 5);
584  gtk_databox_graph_add (box, plot.point_frame);
585 
586  /* Data marker */
587  plot.point_marker = gtk_databox_points_new (1, plot.mark.x, plot.mark.y, &color_black, 7);
588  gtk_databox_graph_add (box, plot.point_marker);
589 
590  /* Kernel line */
591  plot.line_kernel = gtk_databox_lines_new (i, plot.data.x, plot.data.y, &color, 1);
592  gtk_databox_graph_add (box, plot.line_kernel);
593 
594  /* Frame line */
595  plot.line_frame = gtk_databox_lines_new (i, plot.data.x, plot.data.y, &color2, 3);
596  gtk_databox_graph_add (box, plot.line_frame);
597 
598  /* Outter line */
599  plot.line_outter = gtk_databox_lines_new (i, plot.data.x, plot.data.y, &color3, 5);
600  gtk_databox_graph_add (box, plot.line_outter);
601 
602  /* Goal limit */
603  gdk_rgba_parse (&color3, "#808080");
604  plot.line_goal = gtk_databox_lines_new (2, plot.goal.x, plot.goal.y, &color3, 1);
605  gtk_databox_graph_add (box, plot.line_goal);
606 
607  /* Grid and y labels */
608  gdk_rgba_parse (&color, "#bbbbbb");
609  if (pltype == 1) /* Correctness (%) */
610  {
611  plot.grid = gtk_databox_grid_new (3, 3, &color, 1);
612  for (i = 0; i < 5; i++)
613  {
614  g_sprintf (tmp_str, "%u", 100 - 10*i);
615  gtk_label_set_text (GTK_LABEL (plot.label_y[i]), tmp_str);
616  gtk_label_set_xalign (GTK_LABEL (plot.label_y[i]), 0.9);
617  gtk_label_set_yalign (GTK_LABEL (plot.label_y[i]), i / 4.0);
618  gtk_widget_show (plot.label_y[i]);
619  }
620  for (; i < MAX_Y_LABELS; i++)
621  gtk_widget_hide (plot.label_y[i]);
622  }
623  else if (pltype == 2) /* Speed (WPM) */
624  {
625  plot.grid = gtk_databox_grid_new (11, 3, &color, 1);
626  for (i = 0; i < 13; i++)
627  {
628  g_sprintf (tmp_str, "%u", 120 - 10*i);
629  gtk_label_set_text (GTK_LABEL (plot.label_y[i]), tmp_str);
630  gtk_label_set_xalign (GTK_LABEL (plot.label_y[i]), 0.9);
631  gtk_label_set_yalign (GTK_LABEL (plot.label_y[i]), i / 12.0);
632  gtk_widget_show (plot.label_y[i]);
633  }
634  }
635  else
636  {
637  plot.grid = gtk_databox_grid_new (9, 3, &color, 1);
638  for (i = 0; i < 11; i++)
639  {
640  if (pltype == 3)
641  g_sprintf (tmp_str, "%u", 100 - 10*i);
642  else
643  g_sprintf (tmp_str, "%u", 10 - i);
644  gtk_label_set_text (GTK_LABEL (plot.label_y[i]), tmp_str);
645  gtk_label_set_xalign (GTK_LABEL (plot.label_y[i]), 0.9);
646  gtk_label_set_yalign (GTK_LABEL (plot.label_y[i]), i / 10.0);
647  gtk_widget_show (plot.label_y[i]);
648  }
649  for (; i < MAX_Y_LABELS; i++)
650  gtk_widget_hide (plot.label_y[i]);
651  }
652  gtk_databox_graph_add (GTK_DATABOX (plot.databox), plot.grid);
653 
654  /* Redraw the plot
655  */
656  gtk_widget_show_all (plot.gtkgrid);
657 }
658 
659 void
661 {
662  static glong n_prev = 0;
663  glong n = 0;
664  gchar *xstr;
665  gchar *ystr;
666  gchar *tmp;
667  GtkDatabox *box;
668  gint width;
669 
670  box = GTK_DATABOX (plot.databox);
671 
672  gtk_window_get_size (get_win ("window_stat"), &width, NULL);
673  if (plot_type > 4)
674  width -= 25;
675  else
676  width -= 50;
677 
678  n = rintf (x / width * (DATA_POINTS + 2)) - 1; // Round integer from float
679  if (n == n_prev)
680  return;
681  n_prev = n;
682 
683  if (n < 0 || n >= n_points || n >= DATA_POINTS)
684  {
685  xstr = g_strdup ("--");
686  ystr = g_strdup ("--");
687  plot.mark.x[0] = -7;
688  plot.mark.y[0] = -7;
689  }
690  else
691  {
692  if (plot_type < 6)
693  {
694  if (tutor_get_type () == TT_BASIC && lesson_n == 0)
695  xstr = g_strdup_printf ("%s - %s [%s]", date[n], hour[n], lesson[n]);
696  else
697  xstr = g_strdup_printf ("%s - %s", date[n], hour[n]);
698  ystr = g_strdup_printf ("%.2f", plot.data.y[n]);
699  }
700  else if (plot_type == 6)
701  {
702  xstr = accur_terror_char_utf8 (n);
703  ystr = g_strdup_printf ("%.0f/%.lu", plot.data.y[n], accur_error_total ());
704  }
705  else
706  {
707  xstr = accur_ttime_char_utf8 (n);
708  ystr = g_strdup_printf ("%.3f", plot.data.y[n]);
709  }
710  plot.mark.x[0] = plot.data.x[n];
711  plot.mark.y[0] = plot.data.y[n];
712  }
713  gtk_entry_set_text (GTK_ENTRY (get_wg ("entry_stat_x")), xstr);
714  gtk_entry_set_text (GTK_ENTRY (get_wg ("entry_stat_y")), ystr);
715  gtk_widget_queue_draw (plot.databox);
716  g_free (xstr);
717  g_free (ystr);
718 }
gulong accur_error_total()
Definition: accuracy.c:375
void accur_ttime_sort()
Definition: accuracy.c:483
void accur_terror_sort()
Definition: accuracy.c:430
gulong accur_wrong_get(gint i)
Definition: accuracy.c:124
gchar * accur_terror_char_utf8(gint i)
Definition: accuracy.c:88
gint accur_ttime_n_get(void)
Definition: accuracy.c:82
gchar * accur_ttime_char_utf8(gint i)
Definition: accuracy.c:106
gint accur_terror_n_get(void)
Definition: accuracy.c:76
gdouble accur_profi_aver(gint idx)
Definition: accuracy.c:387
GtkWidget * get_wg(gchar *name)
Definition: auxiliar.c:40
GtkWindow * get_win(gchar *name)
Definition: auxiliar.c:50
#define _(String)
Definition: auxiliar.h:45
G_MODULE_EXPORT void on_databox_hovered(GtkDatabox *dbox, GdkEventMotion *event, gpointer user_data)
Definition: callbacks.c:1507
guint i
Definition: keyboard.c:55
gchar * keyb_get_name()
Definition: keyboard.c:204
gchar * main_preferences_get_string(gchar *group, gchar *key)
Definition: main.c:109
gboolean main_altcolor_get_boolean(gchar *group, gchar *key)
Definition: main.c:158
gchar * main_altcolor_get_string(gchar *group, gchar *key)
Definition: main.c:151
gchar * main_path_stats()
Definition: main.c:67
GtkDataboxGraph * line_kernel
Definition: plot.c:57
gint nchars[50+1]
Definition: plot.c:91
static void plot_error_frequencies()
Definition: plot.c:113
gchar hour[50+1][20]
Definition: plot.c:90
struct @8::@10 mark
GtkDataboxGraph * grid
Definition: plot.c:74
glong n_points
Definition: plot.c:94
gfloat x[50+1]
Definition: plot.c:52
struct @8::@12 lim
void plot_draw_chart(gint pltype)
Definition: plot.c:292
void plot_pointer_update(gdouble x)
Definition: plot.c:660
GtkWidget * plot_get_databox()
Definition: plot.c:103
gfloat score[50+1]
Definition: plot.c:88
gint lesson_n
Definition: plot.c:97
gfloat velo[50+1]
Definition: plot.c:86
struct @8::@9 data
GtkWidget * label_y[13]
Definition: plot.c:75
gchar language[50+1][80+1]
Definition: plot.c:93
struct @8::@11 goal
GtkDataboxGraph * limits
Definition: plot.c:82
GtkDataboxGraph * line_outter
Definition: plot.c:59
gchar date[50+1][20]
Definition: plot.c:89
void plot_initialize()
Definition: plot.c:248
GtkDataboxGraph * point_kernel
Definition: plot.c:55
gfloat accur[50+1]
Definition: plot.c:85
GtkDataboxGraph * line_goal
Definition: plot.c:73
GtkDataboxGraph * line_frame
Definition: plot.c:58
GtkDataboxGraph * point_marker
Definition: plot.c:66
gint plot_type
Definition: plot.c:95
static void plot_touch_times()
Definition: plot.c:179
gfloat y[50+1]
Definition: plot.c:53
GtkDataboxGraph * point_frame
Definition: plot.c:56
static struct @8 plot
gchar lesson[50+1][299]
Definition: plot.c:92
GtkWidget * databox
Definition: plot.c:47
GtkWidget * gtkgrid
Definition: plot.c:48
gfloat fluid[50+1]
Definition: plot.c:87
#define PLOT_BLUE
Definition: plot.h:31
#define DATA_POINTS
Definition: plot.h:21
#define PLOT_BLUE_2
Definition: plot.h:32
#define PLOT_GREEN
Definition: plot.h:24
#define PLOT_GREEN_2
Definition: plot.h:25
#define PLOT_ORANGE_2
Definition: plot.h:35
#define PLOT_RED_3
Definition: plot.h:29
#define PLOT_ORANGE
Definition: plot.h:34
#define PLOT_RED_2
Definition: plot.h:28
#define MAX_Y_LABELS
Definition: plot.h:22
#define PLOT_GREEN_3
Definition: plot.h:26
#define PLOT_RED
Definition: plot.h:27
#define PLOT_PURPLE
Definition: plot.h:30
#define PLOT_ORANGE_3
Definition: plot.h:36
#define PLOT_BLUE_3
Definition: plot.h:33
gchar * trans_get_current_language()
Definition: translation.c:471
gdouble tutor_goal_fluidity()
Definition: tutor.c:266
gdouble tutor_goal_accuracy()
Definition: tutor.c:240
gdouble tutor_goal_speed()
Definition: tutor.c:253
TutorType tutor_get_type()
Definition: tutor.c:107
gchar * tutor_get_type_name()
Definition: tutor.c:113
@ TT_VELO
Definition: tutor.h:41
@ TT_FLUID
Definition: tutor.h:42
@ TT_BASIC
Definition: tutor.h:39
@ TT_ADAPT
Definition: tutor.h:40
gint len
Definition: velocity.c:40