"Fossies" - the Fresh Open Source Software Archive

Member "klavaro-3.13/src/top10.c" (18 Apr 2021, 25698 Bytes) of package /linux/privat/klavaro-3.13.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "top10.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.12_vs_3.13.

    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  */
   42 Statistics top10_local[10];
   43 Statistics top10_global[10];
   44 GKeyFile *keyfile = NULL;
   45 
   46 /**************************************************
   47  * Functions
   48  */
   49 
   50 void
   51 top10_init ()
   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
  261 top10_calc_score (Statistics * stat)
  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
  270 top10_validate_stat (Statistics * stat)
  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
  323 top10_merge_stats_from_file (gchar * file)
  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
  675 top10_show_stat (Statistics * stat)
  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
  798 top10_global_update (gpointer data)
  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)
  876         top10_show_stats (LOCAL);
  877     else
  878         top10_show_stats (GLOBAL);
  879 
  880     return FALSE;
  881 }
  882 
  883 gboolean
  884 top10_global_publish (gpointer data)
  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 }