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)  

top10.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  * Contest for fluidness performance
20  */
21 
22 #include <stdio.h>
23 #include <string.h>
24 #include <locale.h>
25 #include <time.h>
26 #include <math.h>
27 #include <sys/stat.h>
28 #include <glib.h>
29 #include <glib/gstdio.h>
30 #include <gtk/gtk.h>
31 #include <curl/curl.h>
32 #include <curl/easy.h>
33 
34 #include "auxiliar.h"
35 #include "main.h"
36 #include "translation.h"
37 #include "top10.h"
38 
39 /**************************************************
40  * Variables
41  */
44 GKeyFile *keyfile = NULL;
45 
46 /**************************************************
47  * Functions
48  */
49 
50 void
52 {
53  gint i;
54  gchar *str;
55  GtkListStore *list;
56  GtkCellRenderer *renderer;
57  GtkTreeViewColumn *column;
58  GtkTreeView *tv;
59  GtkTreeIter iter;
60  GtkComboBox *cmb;
61 
62  renderer = gtk_cell_renderer_text_new ();
63 
64  /* Main info on treeview
65  */
66  tv = GTK_TREE_VIEW (get_wg ("treeview_top10_1"));
67  list = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
68  gtk_tree_view_set_model (tv, GTK_TREE_MODEL (list));
69 
70  column = gtk_tree_view_column_new_with_attributes ("#", renderer, "text", 0, NULL);
71  gtk_tree_view_append_column (tv, column);
72  column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer, "text", 1, NULL);
73  gtk_tree_view_append_column (tv, column);
74  column = gtk_tree_view_column_new_with_attributes (_("Score"), renderer, "text", 2, NULL);
75  gtk_tree_view_append_column (tv, column);
76 
77  for (i = 0; i < 10; i++)
78  {
79  str = g_strdup_printf ("%02i", i + 1);
80  gtk_list_store_append (list, &iter);
81  gtk_list_store_set (list, &iter, 0, str, 1, "--------------------------", 2, "0.000", -1);
82  g_free (str);
83  }
84 
85  /* Extra info on treeview
86  */
87  tv = GTK_TREE_VIEW (get_wg ("treeview_top10_2"));
88  list = gtk_list_store_new (5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
89  G_TYPE_STRING, G_TYPE_STRING);
90  gtk_tree_view_set_model (tv, GTK_TREE_MODEL (list));
91 
92  column = gtk_tree_view_column_new_with_attributes (_("Accuracy"), renderer, "text", 0, NULL);
93  gtk_tree_view_append_column (tv, column);
94  column = gtk_tree_view_column_new_with_attributes (_("Speed"), renderer, "text", 1, NULL);
95  gtk_tree_view_append_column (tv, column);
96  column = gtk_tree_view_column_new_with_attributes (_("Fluidity"), renderer, "text", 2, NULL);
97  gtk_tree_view_append_column (tv, column);
98  column = gtk_tree_view_column_new_with_attributes (_("Chars"), renderer, "text", 3, NULL);
99  gtk_tree_view_append_column (tv, column);
100  column = gtk_tree_view_column_new_with_attributes (_("When"), renderer, "text", 4, NULL);
101  gtk_tree_view_append_column (tv, column);
102 
103  for (i = 0; i < 10; i++)
104  {
105  gtk_list_store_append (list, &iter);
106  gtk_list_store_set (list, &iter, 0, "--", 1, "--", 2, "--", 3, "--", 4, "--", -1);
107  }
108 
109  /* Set modules combo
110  */
111  cmb = GTK_COMBO_BOX (get_wg ("combobox_stat_module"));
112  for (i = 0; i < 4; i++)
113  gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (cmb), 0);
114  str = g_strdup_printf ("1 - %s", _("Basic course"));
115  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cmb), str);
116  g_free (str);
117  str = g_strdup_printf ("2 - %s", _("Adaptability"));
118  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cmb), str);
119  g_free (str);
120  str = g_strdup_printf ("3 - %s", _("Speed"));
121  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cmb), str);
122  g_free (str);
123  str = g_strdup_printf ("4 - %s", _("Fluidity"));
124  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cmb), str);
125  g_free (str);
126  // Fix missing translation bug
127  cmb = GTK_COMBO_BOX (get_wg ("combobox_top10"));
128  gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (cmb), 0);
129  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cmb), _("Local scores"));
130  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cmb), _("External scores"));
131 }
132 
133 void
134 top10_message (gchar * msg)
135 {
136  static gboolean init = TRUE;
137 
138  if (!init)
139  gtk_statusbar_pop (GTK_STATUSBAR (get_wg ("statusbar_top10_message")), 0);
140  if (msg == NULL)
141  {
142  gtk_statusbar_push (GTK_STATUSBAR (get_wg ("statusbar_top10_message")), 0, "");
143  return;
144  }
145  gtk_statusbar_push (GTK_STATUSBAR (get_wg ("statusbar_top10_message")), 0, msg);
146 }
147 
148 #define NOBODY "xxx"
149 void
150 top10_clean_stat (gint i, gboolean locally)
151 {
152  Statistics *top10;
153 
154  top10 = locally ? top10_local : top10_global;
155 
156  if (i > 9)
157  return;
158 
159  top10[i].lang[0] = 'x';
160  top10[i].lang[1] = 'x';
161  top10[i].genv = 'x';
162  top10[i].when = 0;
163  top10[i].nchars = MIN_CHARS_TO_LOG;
164  top10[i].accur = 0.0;
165  top10[i].velo = 0.0;
166  top10[i].fluid = 0.0;
167  top10[i].score = 0.0;
168  top10[i].name_len = strlen (NOBODY);
169  strcpy (top10[i].name, NOBODY);
170 }
171 
172 void
173 top10_init_stats (gboolean locally)
174 {
175  gint i;
176 
177  for (i = 0; i < 10; i++)
178  top10_clean_stat (i, locally);
179 }
180 
181 void
182 top10_insert_stat (Statistics * stat, gint i, gboolean locally)
183 {
184  gint j;
185  Statistics *top10;
186 
187  top10 = locally ? top10_local : top10_global;
188 
189  if (i > 9)
190  return;
191 
192  for (j = 8; j >= i; j--)
193  memmove (&top10[j + 1], &top10[j], sizeof (Statistics));
194 
195  memmove (&top10[i], stat, sizeof (Statistics));
196 }
197 
198 gboolean
199 top10_compare_insert_stat (Statistics * stat, gboolean locally)
200 {
201  gint i, j;
202  gint statnamelen;
203  gchar *pos;
204  Statistics *top10;
205 
206  top10 = locally ? top10_local : top10_global;
207 
208  statnamelen = strlen (stat->name);
209  pos = strrchr (stat->name, '[');
210  if (pos != NULL)
211  if (pos > stat->name && *(pos - 1) == ' ')
212  {
213  statnamelen = pos - stat->name - 1;
214  if (statnamelen < 1)
215  statnamelen = strlen (stat->name);
216  }
217  for (i = 0; i < 10; i++)
218  {
219  if (stat->score > top10[i].score)
220  {
221  for (j = i - 1; j >= 0; j--)
222  {
223  if (strncmp (stat->name, top10[j].name, statnamelen) == 0)
224  return (FALSE);
225  }
226 
227  for (j = i; j < 10; j++)
228  {
229  if (strncmp (stat->name, top10[j].name, statnamelen) == 0 &&
230  stat->score > 0)
231  {
232  top10_delete_stat (j, locally);
233  j--;
234  }
235  }
236  top10_insert_stat (stat, i, locally);
237  return (TRUE);
238  }
239  }
240  return (FALSE);
241 }
242 
243 void
244 top10_delete_stat (gint i, gboolean locally)
245 {
246  gint j;
247  Statistics *top10;
248 
249  top10 = locally ? top10_local : top10_global;
250 
251  if (i > 9)
252  return;
253 
254  for (j = i; j < 9; j++)
255  memmove (&top10[j], &top10[j + 1], sizeof (Statistics));
256 
257  top10_clean_stat (9, locally);
258 }
259 
260 gfloat
262 {
263  gfloat score;
264  /* Weighs: 6 ... 3 ... 1 ==> 10 */
265  score = (6.0 * stat->velo / 1.2 + 3.0 * stat->accur + 1.0 * stat->fluid) / 100;
266  return (score);
267 }
268 
269 gboolean
271 {
272  if (stat->velo >= 222.222)
273  {
274  g_message ("Invalid speed (%g): too much fast for a human on a simple keyboard.", stat->score);
275  return (FALSE);
276  }
277 
278  if (stat->fluid > 95)
279  {
280  g_message ("Invalid fluidity (%g): robots shouldn't compete with humans...",
281  stat->fluid);
282  return (FALSE);
283  }
284 
285  if (stat->score > 17.3333 || stat->score < 0.0)
286  {
287  g_message ("Invalid score (%g): it must be between 0 and 17.3333", stat->score);
288  return (FALSE);
289  }
290 
291  if (stat->score - top10_calc_score (stat) > 1.0e-5)
292  {
293  g_message ("Invalid score (%g): do not edit the scorings file.", stat->score);
294  return (FALSE);
295  }
296 
297  return (TRUE);
298 }
299 
300 gchar *
301 top10_get_score_file (gboolean locally, gint lang)
302 {
303  gchar *tmp = NULL;
304  gchar *ksc;
305 
306  if (lang < 0)
307  tmp = main_preferences_get_string ("interface", "language");
308  else
309  tmp = g_strdup (trans_get_code (lang));
310  if (tmp == NULL)
311  tmp = g_strdup ("en");
312 
313  if (tmp[0] == 'C')
314  ksc = g_strdup (locally ? "local_en.ksc" : "global_en.ksc");
315  else
316  ksc = g_strdup_printf ("%s_%c%c.ksc", locally ? "local" : "global", tmp[0], tmp[1]);
317  g_free (tmp);
318 
319  return (ksc);
320 }
321 
322 static gboolean
324 {
325  gint i, j;
326  gint32 n;
327  FILE *fh;
328  Statistics top10;
329 
330  fh = g_fopen (file, "r");
331  if (fh == NULL)
332  return FALSE;
333  g_message ("1: %s", file);
334 
335  for (i = 0; i < 10; i++)
336  {
337  /* lang[0] */
338  top10.lang[0] = getc (fh);
339  if (!g_ascii_isalpha (top10.lang[0]))
340  {
341  g_message ("Problem: lang[0] = %c", top10.lang[0]);
342  break;
343  }
344 
345  /* lang[1] */
346  top10.lang[1] = getc (fh);
347  if (!g_ascii_isalpha (top10.lang[1]))
348  {
349  top10.lang[0] = 'e';
350  top10.lang[1] = 'o';
351  }
352 
353  /* genv */
354  top10.genv = getc (fh);
355  if (top10.genv != 'x' && top10.genv != 'w')
356  {
357  g_message ("Problem: genv = %c", top10.genv);
358  break;
359  }
360 
361  /* when */
362  //n = fread (&top10.when, sizeof (time_t), 1, fh);
363  n = fread (&top10.when, sizeof (gint32), 1, fh);
364  if (n == 0)
365  {
366  g_message ("Problem: when = %li", top10.when);
367  break;
368  }
369 
370  /* nchars */
371  n = fread (&top10.nchars, sizeof (gint32), 1, fh);
372  if (n == 0 || top10.nchars < MIN_CHARS_TO_LOG)
373  {
374  g_message ("Problem: nchars = %i, < %i", top10.nchars, MIN_CHARS_TO_LOG);
375  break;
376  }
377 
378  /* accur */
379  n = fread (&top10.accur, sizeof (gfloat), 1, fh);
380  if (n == 0 || top10.accur < 0 || top10.accur > 100)
381  {
382  g_message ("Problem: accur = %f <> [0, 100]", top10.accur);
383  break;
384  }
385 
386  /* velo */
387  n = fread (&top10.velo, sizeof (gfloat), 1, fh);
388  if (n == 0 || top10.velo < 0 || top10.velo > 300)
389  {
390  g_message ("Problem: velo = %f <> [0, 300]", top10.velo);
391  break;
392  }
393 
394  /* fluid */
395  n = fread (&top10.fluid, sizeof (gfloat), 1, fh);
396  if (n == 0 || top10.fluid < 0 || top10.fluid > 100)
397  {
398  g_message ("Problem: fluid = %f <> [0, 100]", top10.fluid);
399  break;
400  }
401 
402  /* score */
403  n = fread (&top10.score, sizeof (gfloat), 1, fh);
404  if (n == 0 || top10.score < 0 || top10.score > 20)
405  {
406  g_message ("Problem: score = %f <> [0, 20]", top10.score);
407  break;
408  }
409 
410  /* name_len */
411  n = fread (&top10.name_len, sizeof (gint32), 1, fh);
412  if (n == 0 || top10.name_len < 0 || top10.name_len > MAX_NAME_LEN)
413  {
414  g_message ("Problem: name_len = %i <> [0, MAX_NAME_LEN]", top10.name_len);
415  break;
416  }
417 
418  /* name */
419  n = fread (&top10.name, sizeof (gchar), top10.name_len, fh);
420  top10.name[top10.name_len] = '\0';
421  if (!g_utf8_validate (top10.name, -1, NULL))
422  {
423  for (j = 0; j < top10.name_len; j++)
424  if (!g_ascii_isalpha (top10.name[j]))
425  top10.name[j] = '?';
426  }
427 
428  top10_compare_insert_stat (&top10, TRUE);
429  }
430  fclose (fh);
431  return TRUE;
432 }
433 
434 gboolean
435 top10_read_stats_from_file (gboolean locally, gchar * file)
436 {
437  gint i, j;
438  gint32 n;
439  gboolean success;
440  FILE *fh;
441  Statistics *top10;
442 
443  top10 = locally ? top10_local : top10_global;
444 
445  fh = g_fopen (file, "r");
446  if (fh == NULL)
447  return FALSE;
448 
449  for (i = 0; i < 10; i++)
450  {
451  success = FALSE;
452 
453  /* lang[0] */
454  top10[i].lang[0] = fgetc (fh);
455  if (!g_ascii_isalpha (top10[i].lang[0]))
456  {
457  g_message ("Problem: lang[0] = %c", top10[i].lang[0]);
458  break;
459  }
460 
461  /* lang[1] */
462  top10[i].lang[1] = fgetc (fh);
463  if (!g_ascii_isalpha (top10[i].lang[1]))
464  {
465  top10[i].lang[0] = 'e';
466  top10[i].lang[1] = 'o';
467  }
468 
469  /* genv */
470  top10[i].genv = fgetc (fh);
471  if (top10[i].genv != 'x' && top10[i].genv != 'w')
472  {
473  g_message ("Problem: genv = %c", top10[i].genv);
474  break;
475  }
476 
477  /* when */
478  //n = fread (&top10[i].when, sizeof (time_t), 1, fh);
479  n = fread (&top10[i].when, sizeof (gint32), 1, fh);
480  if (n == 0)
481  {
482  g_message ("Problem: when = %li", top10[i].when);
483  break;
484  }
485 
486  /* nchars */
487  n = fread (&top10[i].nchars, sizeof (gint32), 1, fh);
488  if (n == 0 || top10[i].nchars < MIN_CHARS_TO_LOG)
489  {
490  g_message ("Problem: nchars = %i, < %i", top10[i].nchars, MIN_CHARS_TO_LOG);
491  break;
492  }
493 
494  /* accur */
495  n = fread (&top10[i].accur, sizeof (gfloat), 1, fh);
496  if (n == 0 || top10[i].accur < 0 || top10[i].accur > 100)
497  {
498  g_message ("Problem: accur = %f <> [0, 100]", top10[i].accur);
499  break;
500  }
501 
502  /* velo */
503  n = fread (&top10[i].velo, sizeof (gfloat), 1, fh);
504  if (n == 0 || top10[i].velo < 0 || top10[i].velo > 300)
505  {
506  g_message ("Problem: velo = %f <> [0, 300]", top10[i].velo);
507  break;
508  }
509 
510  /* fluid */
511  n = fread (&top10[i].fluid, sizeof (gfloat), 1, fh);
512  if (n == 0 || top10[i].fluid < 0 || top10[i].fluid > 100)
513  {
514  g_message ("Problem: fluid = %f <> [0, 100]", top10[i].fluid);
515  break;
516  }
517 
518  /* score */
519  n = fread (&top10[i].score, sizeof (gfloat), 1, fh);
520  if (n == 0 || top10[i].score < 0 || top10[i].score > 20)
521  {
522  g_message ("Problem: score = %f <> [0, 20]", top10[i].score);
523  break;
524  }
525 
526  /* name_len */
527  n = fread (&top10[i].name_len, sizeof (gint32), 1, fh);
528  if (n == 0 || top10[i].name_len < 0 || top10[i].name_len > MAX_NAME_LEN)
529  {
530  g_message ("Problem: name_len = %i <> [0, MAX_NAME_LEN]", top10[i].name_len);
531  break;
532  }
533 
534  /* name */
535  n = fread (&top10[i].name, sizeof (gchar), top10[i].name_len, fh);
536  top10[i].name[top10[i].name_len] = '\0';
537  if (!g_utf8_validate (top10[i].name, -1, NULL))
538  {
539  for (j = 0; j < top10[i].name_len; j++)
540  if (!g_ascii_isalpha (top10[i].name[j]))
541  top10[i].name[j] = '?';
542  }
543  success = TRUE;
544  }
545  fclose (fh);
546 
547  return (success);
548 }
549 
550 void
551 top10_read_stats (gboolean locally, gint lang)
552 {
553  gchar *local_ksc;
554  gchar *tmp;
555  gchar *uname;
556  gchar *stat_dir;
557  gboolean success;
558  GDir *home;
559 
560  top10_init_stats (locally);
561 
562  local_ksc = top10_get_score_file (locally, lang);
563 
564  tmp = g_build_filename (main_path_score (), local_ksc, NULL);
565  if (!top10_read_stats_from_file (locally, tmp))
566  {
567  g_message ("Could not read the scores file '%s'.\n Creating a blank one.", tmp);
568  top10_init_stats (locally);
569  top10_write_stats (locally, lang);
570  //top10_show_stat (locally ? top10_local : top10_global);
571  }
572  g_free (tmp);
573 
574  if (!locally)
575  {
576  g_free (local_ksc);
577  return;
578  }
579 
580  /* Go search other users' subdirs
581  */
582  tmp = strchr (main_path_stats (), G_DIR_SEPARATOR);
583  if (tmp)
584  tmp = strchr (tmp + 1, G_DIR_SEPARATOR);
585  if (tmp)
586  tmp = strchr (tmp + 1, G_DIR_SEPARATOR);
587  if (tmp)
588  {
589  stat_dir = tmp + 1;
590  home = g_dir_open ("/home", 0, NULL);
591  }
592  else
593  {
594  stat_dir = NULL;
595  home = NULL;
596  }
597 
598  success = FALSE;
599  if (home)
600  {
601  while ((uname = (gchar*) g_dir_read_name (home)))
602  {
603  if (g_str_equal (uname, "root"))
604  continue;
605  if (g_str_equal (uname, "lost+found"))
606  continue;
607  if (g_str_equal (uname, g_get_user_name ()))
608  continue;
609 
610  tmp = g_build_filename ("/home", uname, stat_dir, "ksc", local_ksc, NULL);
611  success = success ? TRUE : top10_merge_stats_from_file (tmp);
612  g_free (tmp);
613  }
614  g_dir_close (home);
615  }
616  g_free (local_ksc);
617 
618  if (success)
619  top10_write_stats (TRUE, -1);
620 }
621 
622 void
623 top10_write_stats (gboolean locally, gint lang)
624 {
625  gint i;
626  gchar *filename;
627  gchar *lsfile;
628  FILE *fh;
629  Statistics *top10;
630 
631  top10 = locally ? top10_local : top10_global;
632 
633  if (!g_file_test (main_path_score (), G_FILE_TEST_IS_DIR))
634  g_mkdir_with_parents (main_path_score (), DIR_PERM);
635 
636  filename = top10_get_score_file (locally, lang);
637 
638  lsfile = g_build_filename (main_path_score (), filename, NULL);
639 
640  fh = g_fopen (lsfile, "w");
641  if (fh == NULL)
642  {
643  g_warning ("Could not write the scores file in %s", main_path_score ());
644  g_free (filename);
645  g_free (lsfile);
646  return;
647  }
648 
649  for (i = 0; i < 10; i++)
650  {
651  fputc (top10[i].lang[0], fh);
652  fputc (top10[i].lang[1], fh);
653  fputc (top10[i].genv, fh);
654  //fwrite (&top10[i].when, sizeof (time_t), 1, fh);
655  fwrite (&top10[i].when, sizeof (gint32), 1, fh);
656  fwrite (&top10[i].nchars, sizeof (gint32), 1, fh);
657  fwrite (&top10[i].accur, sizeof (gfloat), 1, fh);
658  fwrite (&top10[i].velo, sizeof (gfloat), 1, fh);
659  fwrite (&top10[i].fluid, sizeof (gfloat), 1, fh);
660  fwrite (&top10[i].score, sizeof (gfloat), 1, fh);
661  fwrite (&top10[i].name_len, sizeof (gint32), 1, fh);
662  if (top10[i].name && top10[i].name_len > 0)
663  fputs (top10[i].name, fh);
664  }
665  fputs ("KLAVARO!", fh);
666  fclose (fh);
667 
668  g_free (filename);
669  g_free (lsfile);
670 }
671 
672 /* Test function to show every field of a scoring record, at the terminal
673  */
674 void
676 {
677  g_print ("Language: %c%c\n", stat->lang[0], stat->lang[1]);
678  g_print ("Graphical environment: %s\n", stat->genv == 'x' ? "Linux" : "Windows");
679  g_print ("When: %li\n", stat->when);
680  g_print ("# of characters: %i\n", stat->nchars);
681  g_print ("Accuracy: %2.1f\n", stat->accur);
682  g_print ("Velocity: %2.1f\n", stat->velo);
683  g_print ("Fluidness: %2.1f\n", stat->fluid);
684  g_print ("Score: %05.1f\n", stat->score);
685  g_print ("Name length: %i\n", stat->name_len);
686  g_print ("Name: %s\n", stat->name);
687 }
688 
689 void
690 top10_show_stats (gboolean locally)
691 {
692  gint i;
693  gboolean success;
694  gchar *tmp;
695  gchar *url;
696  gchar *accur;
697  gchar *velo;
698  gchar *fluid;
699  gchar *nchars;
700  gchar *date;
701  struct tm *ltime;
702  Statistics *top10;
703  GtkListStore *list1;
704  GtkListStore *list2;
705  GtkTreeIter iter1;
706  GtkTreeIter iter2;
707 
708  top10 = locally ? top10_local : top10_global;
709 
710  top10_read_stats (locally, -1);
711  top10_read_stats (!locally, -1);
712 
713  /* Set layout
714  */
715  if (top10[0].score == 0.0)
716  {
717  top10_message (_("Empty ranking. Please practice fluidness."));
718  gtk_widget_set_sensitive (get_wg ("treeview_top10_1"), FALSE);
719  gtk_widget_set_sensitive (get_wg ("treeview_top10_2"), FALSE);
720  }
721  else
722  {
723  gtk_widget_set_sensitive (get_wg ("treeview_top10_1"), TRUE);
724  gtk_widget_set_sensitive (get_wg ("treeview_top10_2"), TRUE);
725  }
726 
727  gtk_widget_set_sensitive (get_wg ("button_top10_update"), !locally);
728  if (top10_local[0].score == 0.0)
729  gtk_widget_set_sensitive (get_wg ("button_top10_publish"), FALSE);
730  else
731  gtk_widget_set_sensitive (get_wg ("button_top10_publish"), !locally);
732 
733  /* Set web link
734  */
735  tmp = main_preferences_get_string ("interface", "language");
736  if (tmp[0] == 'C')
737  {
738  g_free (tmp);
739  tmp = g_strdup ("en");
740  }
741  url = g_strdup_printf ("https://" DOWNHOST "/%c%c/", tmp[0], tmp[1]);
742  gtk_widget_set_tooltip_text (get_wg ("button_top10_go_www"), url);
743  g_free (tmp);
744  g_free (url);
745 
746  /* Print the ranking
747  */
748  list1 = GTK_LIST_STORE ( gtk_tree_view_get_model (GTK_TREE_VIEW (get_wg ("treeview_top10_1"))) );
749  list2 = GTK_LIST_STORE ( gtk_tree_view_get_model (GTK_TREE_VIEW (get_wg ("treeview_top10_2"))) );
750  success = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list1), &iter1);
751  success = (success && gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list2), &iter2));
752  if (! success)
753  {
754  g_warning ("not able to set Top10 Treeviews");
755  return;
756  }
757  for (i = 0; i < 10; i++)
758  {
759  if (top10[i].score == 0)
760  {
761  gtk_list_store_set (list1, &iter1, 1, "", 2, "", -1);
762  gtk_list_store_set (list2, &iter2, 0, "", 1, "", 2, "", 3, "", 4, "", -1);
763  }
764  else
765  {
766  /* First treeview: main info
767  */
768  tmp = g_strdup_printf ("%3.4f", top10[i].score);
769  gtk_list_store_set (list1, &iter1, 1, top10[i].name, 2, tmp, -1);
770  g_free (tmp);
771 
772  /* Second treeview: further info
773  */
774  accur = g_strdup_printf ("%2.1f", top10[i].accur);
775  velo = g_strdup_printf ("%2.1f", top10[i].velo);
776  fluid = g_strdup_printf ("%2.1f", top10[i].fluid);
777  nchars = g_strdup_printf ("%i", top10[i].nchars);
778  ltime = localtime (&top10[i].when);
779  date = g_strdup_printf ("%i-%2.2i-%2.2i %02i:%02i", (ltime->tm_year) + 1900,
780  (ltime->tm_mon) + 1, (ltime->tm_mday),
781  (ltime->tm_hour), (ltime->tm_min));
782 
783  gtk_list_store_set (list2, &iter2, 0, accur, 1, velo, 2, fluid, 3, nchars, 4, date, -1);
784 
785  g_free (accur);
786  g_free (velo);
787  g_free (fluid);
788  g_free (nchars);
789  g_free (date);
790  }
791 
792  gtk_tree_model_iter_next (GTK_TREE_MODEL (list1), &iter1);
793  gtk_tree_model_iter_next (GTK_TREE_MODEL (list2), &iter2);
794  }
795 }
796 
797 gboolean
799 {
800  gboolean fail;
801  gchar *tmp;
802  gchar *ksc;
803  gchar *host;
804  gchar *command;
805  GtkImage *img;
806  CURL *curl;
807  FILE *fh;
808 
809  img = GTK_IMAGE (get_wg ("image_top10_update"));
810  top10_message (NULL);
811 
812  if (!main_curl_ok ())
813  {
814  tmp = g_strconcat (_("Not able to download files"), ": 'libcurl' ", _("not found"), ". ",
815  _("Are you sure you have it installed in your system?"), NULL);
816  top10_message (tmp);
817  g_free (tmp);
818  gtk_image_set_from_icon_name (img, "go-bottom", GTK_ICON_SIZE_BUTTON);
819  return FALSE;
820  }
821 
822  /**************************************************
823  * Download from downhost
824  */
825  host = g_strdup (DOWNHOST);
826  ksc = top10_get_score_file (GLOBAL, -1);
827  if (! (curl = curl_easy_init ()) )
828  {
829  g_message ("Not able to initialize 'curl'");
830  gtk_image_set_from_icon_name (img, "go-bottom", GTK_ICON_SIZE_BUTTON);
831  g_free (host);
832  return FALSE;
833  }
834 
835  if (!g_file_test (main_path_score (), G_FILE_TEST_IS_DIR))
836  g_mkdir_with_parents (main_path_score (), DIR_PERM);
837  tmp = g_build_filename (main_path_score (), ksc, NULL);
838  fail = TRUE;
839  command = g_strdup_printf ("https://%s/%s", host, ksc);
840  if ( (fh = g_fopen (tmp, "wb")) )
841  {
842  /*
843  curl_easy_setopt (curl, CURLOPT_VERBOSE, 1);
844  */
845  curl_easy_setopt (curl, CURLOPT_TIMEOUT, TIMEOUT);
846  curl_easy_setopt (curl, CURLOPT_LOW_SPEED_LIMIT, LOW_SPEED_LIMIT);
847  curl_easy_setopt (curl, CURLOPT_LOW_SPEED_TIME, LOW_SPEED_TIME);
848  curl_easy_setopt (curl, CURLOPT_URL, command);
849  curl_easy_setopt (curl, CURLOPT_WRITEDATA, fh);
850  curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0L);
851  fail = curl_easy_perform (curl);
852  if (fail) g_message ("%s", curl_easy_strerror (fail));
853  fclose (fh);
854  }
855  curl_easy_cleanup (curl);
856  g_free (command);
857  g_free (host);
858 
859  if (fail)
860  {
861  top10_message (_("Could not download file from the host server."));
862  gtk_image_set_from_icon_name (img, "go-bottom", GTK_ICON_SIZE_BUTTON);
863  g_free (ksc);
864  g_free (tmp);
865  return FALSE;
866  }
867 
868  if (!g_file_test (tmp, G_FILE_TEST_IS_REGULAR))
869  g_message ("No file downloaded from the host server.");
870 
871  gtk_image_set_from_icon_name (img, "go-bottom", GTK_ICON_SIZE_BUTTON);
872  g_free (tmp);
873  g_free (ksc);
874 
875  if (gtk_combo_box_get_active (GTK_COMBO_BOX (get_wg ("combobox_top10"))) == 0)
877  else
879 
880  return FALSE;
881 }
882 
883 gboolean
885 {
886  gint i;
887  gboolean success;
888  gboolean fail;
889  gchar *tmp;
890  gchar *ksc;
891  gchar *host;
892  gchar *path;
893  gchar *username;
894  gchar *url;
895  GtkImage *img;
896  FILE *fh, *fh2;
897  GStatBuf fs;
898  CURL *curl;
899 
900  fs.st_size = 0;
901  img = GTK_IMAGE (get_wg ("image_top10_publish"));
902  top10_message (NULL);
903 
904  if (!main_curl_ok ())
905  {
906  tmp = g_strconcat (_("Not able to upload files"), ": 'libcurl' ", _("not found"), ". ",
907  _("Are you sure you have it installed in your system?"), NULL);
908  top10_message (tmp);
909  g_free (tmp);
910  gtk_image_set_from_icon_name (img, "go-top", GTK_ICON_SIZE_BUTTON);
911  return FALSE;
912  }
913 
914  if (! (curl = curl_easy_init ()))
915  {
916  g_message ("Not able to initialize curl session");
917  gtk_image_set_from_icon_name (img, "go-top", GTK_ICON_SIZE_BUTTON);
918  return FALSE;
919  }
920 
921  /**************************************************
922  * Upload to uphost, updating local ranking
923  */
924  host = g_strdup (CGI_SERVER);
925  tmp = main_preferences_get_string ("interface", "language");
926  if (tmp[0] == 'C')
927  {
928  g_free (tmp);
929  tmp = g_strdup ("en");
930  }
931  ksc = g_strdup_printf ("local_%c%c.ksc", tmp[0], tmp[1]);
932  path = g_build_filename (main_path_score (), ksc, NULL);
933  g_free (ksc);
934  g_stat (path, &fs);
935 
936  username = g_strdup (g_get_real_name ());
937  username = g_strdelimit (username, " ", '_');
938  if (strlen (username) == 0)
939  {
940  g_free (username);
941  username = g_strdup (g_get_user_name ());
942  }
943  if (strlen (username) == 0)
944  {
945  g_free (username);
946  username = g_strdup ("0-0");
947  }
948  ksc = g_strdup_printf ("%s_%s_%c%c.ksc", username, g_get_host_name (), tmp[0], tmp[1]);
949  url = g_strdup_printf ("https://%s?dosiernomo=%s&lingvo=%c%c", host, ksc, tmp[0], tmp[1]);
950  g_free (username);
951  g_free (host);
952  g_free (ksc);
953  g_free (tmp);
954 
955  /*
956  curl_easy_setopt (curl, CURLOPT_VERBOSE, 1);
957  */
958  curl_easy_setopt (curl, CURLOPT_TIMEOUT, TIMEOUT);
959  curl_easy_setopt (curl, CURLOPT_LOW_SPEED_LIMIT, LOW_SPEED_LIMIT);
960  curl_easy_setopt (curl, CURLOPT_LOW_SPEED_TIME, LOW_SPEED_TIME);
961  curl_easy_setopt (curl, CURLOPT_UPLOAD, TRUE);
962  curl_easy_setopt (curl, CURLOPT_INFILESIZE, (long) fs.st_size);
963  curl_easy_setopt (curl, CURLOPT_URL, url);
964  success = FALSE;
965  if ( (fh = g_fopen (path, "rb")) )
966  {
967  i = 0;
968  while (1)
969  {
970  tmp = g_strdup_printf ("%s/klavaro_%03i.html", g_get_tmp_dir (), i++);
971  if ((fh2 = g_fopen (tmp, "wb")))
972  break;
973  g_free (tmp);
974  }
975  g_free (tmp);
976  curl_easy_setopt (curl, CURLOPT_READDATA, fh);
977  curl_easy_setopt (curl, CURLOPT_WRITEDATA, fh2);
978  curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0L);
979  if (fail = curl_easy_perform (curl))
980  g_message ("HTTPS upload failed: %s", curl_easy_strerror(fail));
981  else
982  success = TRUE;
983  fclose (fh);
984  fclose (fh2);
985  }
986  curl_easy_cleanup (curl);
987  g_free (path);
988  g_free (url);
989 
990  gtk_image_set_from_icon_name (img, "go-top", GTK_ICON_SIZE_BUTTON);
991 
992  if (!success)
993  top10_message (_("Could not upload/download scores."));
994  else
995  g_idle_add ((GSourceFunc) top10_global_update, NULL);
996 
997  return FALSE;
998 }
GtkWidget * get_wg(gchar *name)
Definition: auxiliar.c:40
#define _(String)
Definition: auxiliar.h:45
guint i
Definition: keyboard.c:55
guint j
Definition: keyboard.c:56
gchar * name
Definition: keyboard.c:45
struct @4::@6 pos
gchar * main_preferences_get_string(gchar *group, gchar *key)
Definition: main.c:109
static struct @7 path
gboolean main_curl_ok()
Definition: main.c:85
gchar * score
Definition: main.c:54
gchar * main_path_stats()
Definition: main.c:67
gchar * data
Definition: main.c:53
gchar * main_path_score()
Definition: main.c:79
#define DIR_PERM
Definition: main.h:33
#define LOCAL
Definition: main.h:38
#define GLOBAL
Definition: main.h:39
gint nchars[50+1]
Definition: plot.c:91
gfloat velo[50+1]
Definition: plot.c:86
gchar date[50+1][20]
Definition: plot.c:89
gfloat accur[50+1]
Definition: plot.c:85
gfloat fluid[50+1]
Definition: plot.c:87
gfloat velo
Definition: top10.h:46
gfloat score
Definition: top10.h:48
gint32 nchars
Definition: top10.h:44
gfloat fluid
Definition: top10.h:47
time_t when
Definition: top10.h:43
gfloat accur
Definition: top10.h:45
gint32 name_len
Definition: top10.h:49
gchar genv
Definition: top10.h:42
gchar name[255+1]
Definition: top10.h:50
gchar lang[2]
Definition: top10.h:41
static gboolean top10_merge_stats_from_file(gchar *file)
Definition: top10.c:323
gboolean top10_read_stats_from_file(gboolean locally, gchar *file)
Definition: top10.c:435
void top10_show_stat(Statistics *stat)
Definition: top10.c:675
gchar * top10_get_score_file(gboolean locally, gint lang)
Definition: top10.c:301
void top10_message(gchar *msg)
Definition: top10.c:134
void top10_init_stats(gboolean locally)
Definition: top10.c:173
gboolean top10_global_update(gpointer data)
Definition: top10.c:798
gfloat top10_calc_score(Statistics *stat)
Definition: top10.c:261
void top10_read_stats(gboolean locally, gint lang)
Definition: top10.c:551
Statistics top10_global[10]
Definition: top10.c:43
gboolean top10_compare_insert_stat(Statistics *stat, gboolean locally)
Definition: top10.c:199
void top10_delete_stat(gint i, gboolean locally)
Definition: top10.c:244
gboolean top10_validate_stat(Statistics *stat)
Definition: top10.c:270
void top10_insert_stat(Statistics *stat, gint i, gboolean locally)
Definition: top10.c:182
void top10_clean_stat(gint i, gboolean locally)
Definition: top10.c:150
Statistics top10_local[10]
Definition: top10.c:42
gboolean top10_global_publish(gpointer data)
Definition: top10.c:884
void top10_show_stats(gboolean locally)
Definition: top10.c:690
void top10_write_stats(gboolean locally, gint lang)
Definition: top10.c:623
void top10_init()
Definition: top10.c:51
GKeyFile * keyfile
Definition: top10.c:44
#define NOBODY
Definition: top10.c:148
#define LOW_SPEED_TIME
Definition: top10.h:27
#define TIMEOUT
Definition: top10.h:25
#define CGI_SERVER
Definition: top10.h:22
#define MIN_CHARS_TO_LOG
Definition: top10.h:23
#define DOWNHOST
Definition: top10.h:21
#define LOW_SPEED_LIMIT
Definition: top10.h:26
#define MAX_NAME_LEN
Definition: top10.h:38
static Lang_Name_Code * lang
Definition: translation.c:39
gchar * trans_get_code(gint i)
Definition: translation.c:218
GList * list
Definition: velocity.c:39