Logo Search packages:      
Sourcecode: tucnak2 version File versions  Download package

stats.c

/*
    Tucnak - VHF contest log
    Copyright (C) 2002-2006  Ladislav Vaiz <ok1zia@nagano.cz>

    This program is free software; you can redistribute it and/or                                                        
    modify it under the terms of the GNU General Public License                                                          
    version 2 as published by the Free Software Foundation.

*/

#include "header.h"


char *get_wwl(char *buf, char *wwl){
    safe_strncpy(buf, wwl,5);
    return buf;
}


void draw_one_bigdigit(int x, int y, int num){
    switch(num%10){
        case 0:
            fill_area(x,y,3,5,COL_INV);
            fill_area(x+1,y+1,1,3,COL_NORM);
            break;
        case 1:
            fill_area(x,y,3,5,COL_INV);
            fill_area(x+2,y,1,4,COL_NORM);
            fill_area(x,y+1,1,3,COL_NORM);
            break;
        case 2:
            fill_area(x,y,3,5,COL_INV);
            fill_area(x,y+1,2,1,COL_NORM);
            fill_area(x+1,y+3,2,1,COL_NORM);
            break;
        case 3:
            fill_area(x,y,3,5,COL_INV);
            fill_area(x,y+1,2,1,COL_NORM);
            fill_area(x,y+3,2,1,COL_NORM);
            break;
        case 4:
            fill_area(x,y,3,5,COL_INV);
            fill_area(x+1,y,1,2,COL_NORM);
            fill_area(x,y+3,2,2,COL_NORM);
            break;
        case 5:
            fill_area(x,y,3,5,COL_INV);
            fill_area(x+1,y+1,2,1,COL_NORM);
            fill_area(x,y+3,2,1,COL_NORM);
            break;
        case 6:
            fill_area(x,y,3,5,COL_INV);
            fill_area(x+1,y+1,2,1,COL_NORM);
            fill_area(x+1,y+3,1,1,COL_NORM);
            break;
        case 7:
            fill_area(x,y,3,5,COL_INV);
            fill_area(x,y+1,2,4,COL_NORM);
            break;
        case 8:
            fill_area(x,y,3,5,COL_INV);
            fill_area(x+1,y+1,1,1,COL_NORM);
            fill_area(x+1,y+3,1,1,COL_NORM);
            break;
        case 9:
            fill_area(x,y,3,5,COL_INV);
            fill_area(x+1,y+1,1,1,COL_NORM);
            fill_area(x,y+3,2,1,COL_NORM);
            break;

    }
}

void draw_bigdigit(int x, int y, int num){
   int qsonr=num;
   
   if (qsonr>=10000) set_char(x-2,y+2,'+');
   
   if (qsonr>=1000) {
       draw_one_bigdigit(x,y,(qsonr/1000)%10);
   }else{
       x-=2;
   }

   draw_one_bigdigit(x+4 ,y, (qsonr/100)%10); 
   draw_one_bigdigit(x+8 ,y, (qsonr/10)%10); 
   draw_one_bigdigit(x+12,y, qsonr%10); 
    
}








struct stats *init_stats(){
    struct stats *st;

    st = (struct stats *)g_new0(struct stats, 1); 

    st->wwls = g_hash_table_new(g_str_hash, g_str_equal);
    st->dxcs = g_hash_table_new(g_str_hash, g_str_equal);
    st->excs = g_hash_table_new(g_str_hash, g_str_equal);
    st->calls = g_hash_table_new(g_str_hash, g_str_equal);
    st->hours = g_hash_table_new(g_str_hash, g_str_equal);
    
    clear_stats(st);
    
    return st;
}


void free_stats(struct stats *st){

    clear_stats(st);
    
    g_hash_table_destroy(st->wwls);
    g_hash_table_destroy(st->dxcs);
    g_hash_table_destroy(st->excs);
    g_hash_table_destroy(st->calls);
    g_hash_table_destroy(st->hours);
    g_free(st);
    
}


void clear_stats(struct stats *st){
 /*   dbg("clear_stats(%p)\n", st);*/
    
    st->first_date = G_MAXINT;
    st->last_date  = 0;
    
    st->nqsos = 0;
    st->nqsop = 0;
    st->nwwlp = 0;
    st->nexcp = 0;
    st->ndxcp = 0;
    st->ntotal = 0;
    
    g_hash_table_foreach_remove(st->wwls, free_gpointer_item, NULL);
    g_hash_table_foreach_remove(st->dxcs, free_gpointer_item, NULL);
    g_hash_table_foreach_remove(st->excs, free_gpointer_item, NULL);
    g_hash_table_foreach_remove(st->calls, free_gpointer_item, NULL);
    g_hash_table_foreach_remove(st->hours, free_gpointer_item, NULL);
    
    if (st->odxcall)     {g_free(st->odxcall);     st->odxcall      = NULL;}
    if (st->odxwwl)      {g_free(st->odxwwl);      st->odxwwl       = NULL;}
    if (st->odxoperator) {g_free(st->odxoperator); st->odxoperator  = NULL;}
    st->odxqrb_int = 0;
}

int find_preferred_dxc(int type, char *dxc){
      char *prefs9[]  = {"ES","LA","LY","OH","OH0","OJ0","OY","OZ","SM","TF","YL",NULL};
      char *prefs10[] = {"G","GD","GI","GJ","GM","GU","GW",NULL};
    char *prefs11[] = {"F",NULL}; 
      char **prefs;
      int multi=1;
      int i;
      
      switch(type){
            case 9: 
                  prefs=prefs9;
                  multi=3;
                  break;
            case 10: 
                  prefs=prefs10;
                  multi=5;
                  break;
            case 11: 
                  prefs=prefs11;
                  multi=3;
                  break;
            default:
                  return 1;   
      }

      for (i=0; prefs[i]!=NULL; i++){
            if (strcasecmp(dxc,prefs[i])==0) return multi;
      }
      return 1;
      
}
/* set and dirty */
#define SAD_INT(item,value) {if (q->item!=value) band->dirty_save=1;q->item=value;}

void update_stats(struct band *band, struct stats *st, struct qso *q){
    gint date,qsop,anew;
    gchar s[120];
    gpointer orig_key;
    struct cntpts *orig_value;
    gint wwls, dxcs, excs;

    qsop=0;
    if (band->stats_thread && band->stats_thread!=g_thread_self()){
        /* Thread is computing statistics.
         * No reason to update stats, they will be overwritten and statistics
         * must not be consistent. We must kill thread and create new to 
         * cover all qsos. 
         */
        stats_thread_kill(band);
        stats_thread_create(band);
        return;
    }
    if (band->stats==st) LOCK(band->stats);
    
/*    dbg("update_stats(%p, %c, %p)\n", st, b->bandchar, q);*/
    if (!q->error){
        date = atoi(q->date_str);
        if (date < st->first_date) st->first_date = date;
        if (date > st->last_date)  st->last_date  = date;
    }
    
    if (q->error) {
        SAD_INT(new,0);
        SAD_INT(qsop,0);
        SAD_INT(susploc,0);
        SAD_INT(unkcall,0);
        goto x;
    }
    st->nqsos++;

    
/*    dbg("update_stats(%s) calls->size=%d \n", q->qsonrs, g_hash_table_size(st->calls));
    dbg("   dupe=%d  qsop=%d \n", q->dupe, q->qsop);*/
    
    get_raw_call(s, q->callsign);
    if (g_hash_table_lookup_extended(st->calls, s, &orig_key, (gpointer) &orig_value)){
        SAD_INT(dupe,1);
    }else{
        g_hash_table_insert(st->calls, g_strdup(s), NULL);
        SAD_INT(dupe,0);
    }
    
    switch (ctest->qsop_method){
        case 1: /* rounded distance */
            qsop = iaru_round(q->qrb) * ctest->qsomult;
            break;
        case 2: /* 1 */
            qsop = ctest->qsomult;
            break;
            case 3: /* FIXME! it's really correct? */
                  qsop = ((q->qrb/50)*2+1 ) * ctest->qsomult;
                  break;      
        case 4: /* WWL ring */
            qsop = qsopwr(ctest->pwwlo, q->locator) * ctest->qsomult;
            break;
            case 5: /* statute miles (anglicka mile) */
                  qsop = q->qrb/1.6094 * ctest->qsomult;    
                  break;
            case 6: /* 1 * qso-points multi + 1 point for CW QSO FIXME! bug in taclog? */
                  qsop = ctest->qsomult;
                  if (q->mode==MOD_CW_CW) q->qsop++;
                  break;
            case 7: /* distance(min 50) */      
                  qsop = (q->qrb>50 ? q->qrb : 50) * ctest->qsomult;
                  break;
            case 8: /* distance(min 10) */      
                  qsop = (q->qrb>10 ? q->qrb : 10) * ctest->qsomult;
                  break;
            case 9:
            case 10:
            case 11:
                  qsop = ctest->qsomult * 
                        find_preferred_dxc(ctest->qsop_method,
                                    get_dxcc(dw,s,q->callsign));
                  break;

            
    }
    if (q->dupe) qsop=0;
    SAD_INT(qsop,qsop);
    
/*    dbg("   dupe=%d  qsop=%d \n", q->dupe, q->qsop);*/
    
    st->nqsop += q->qsop;

    
    if ((int)q->qrb > st->odxqrb_int){
        if (st->odxcall)     { g_free(st->odxcall);     st->odxcall = NULL; }
        if (st->odxwwl)      { g_free(st->odxwwl);      st->odxwwl  = NULL; }
        if (st->odxoperator) { g_free(st->odxoperator); st->odxoperator  = NULL;}
         
        st->odxqrb_int  = (int)q->qrb;
        st->odxcall     = g_strdup(q->callsign);
        st->odxwwl      = g_strdup(q->locator);  
        st->odxoperator = g_strdup(q->operator);
    }

    q->unkcall=!find_wwl_by_call(cw, q->callsign);
    q->susploc = get_susp_loc(cw, dw, q->callsign, q->locator) & 0xff;
    
    anew=q->new;

    if (ctest->wwlused){    
        get_wwl(s, q->locator);
        if (g_hash_table_lookup_extended(st->wwls, s, &orig_key, (gpointer) &orig_value)){
            orig_value->count++; 
                  orig_value->points+=qsop;
            anew &= ~NEW_WWL;
        }else{
            orig_value = g_new0(struct cntpts, 1);
            orig_value->count = 1;
            orig_value->points = qsop;
            g_hash_table_insert(st->wwls, g_strdup(s), orig_value);
            anew |= NEW_WWL;
        }
    }
    
 
    get_dxcc(dw, s, q->callsign);
    if (g_hash_table_lookup_extended(st->dxcs, s, &orig_key, (gpointer) &orig_value)){
        orig_value->count++; 
            orig_value->points+=qsop;
        anew &= ~NEW_DXC;
    }else{
        orig_value = g_new0(struct cntpts, 1);
            orig_value->count = 1;
            orig_value->points = qsop;
        g_hash_table_insert(st->dxcs, g_strdup(s), orig_value);
        anew |= NEW_DXC;
    }
        

    if (ctest->excused){
        safe_strncpy0(s, q->exc, 20);
        if (g_hash_table_lookup_extended(st->excs, s, &orig_key, (gpointer) &orig_value)){
              orig_value->count++; 
                  orig_value->points+=qsop;
            anew &= ~NEW_EXC;
        }else{
            orig_value = g_new0(struct cntpts, 1);
            orig_value->count = 1;
            orig_value->points = qsop;
            g_hash_table_insert(st->excs, g_strdup(s), orig_value);
            anew |= NEW_EXC;
        }
    } 

    safe_strncpy0(s, q->time_str, 3);
      if (!g_hash_table_lookup_extended(st->hours, s, &orig_key, (gpointer) &orig_value)){
            orig_value = g_new0(struct cntpts, 1);
            g_hash_table_insert(st->hours, g_strdup(s), orig_value);
    }
    orig_value->count++; 
    orig_value->points+=qsop;
    if (!orig_value->qso){
        orig_value->qso = q;
    }else{
        if (q->qrb > orig_value->qso->qrb){
            orig_value->qso = q;
        }
    }
    
    SAD_INT(new,anew);
    
    wwls = g_hash_table_size(st->wwls);
    dxcs = g_hash_table_size(st->dxcs);
    excs = g_hash_table_size(st->excs);

    switch (ctest->total_method){
        case 1:      
            st->ntotal = ( st->nqsop +
                           wwls * ctest->wwlbonu + 
                           dxcs * ctest->dxcbonu +
                           excs * ctest->excbonu 
                         ) *
                           (ctest->wwlmult ? wwls * ctest->wwlmult : 1 ) *
                           (ctest->dxcmult ? dxcs * ctest->dxcmult : 1 ) *
                           (ctest->excmult ? excs * ctest->excmult : 1 )
                         ;  
            break;              
        case 2:      
            st->ntotal = ( st->nqsop +
                           wwls * ctest->wwlbonu + 
                           dxcs * ctest->dxcbonu +
                           excs * ctest->excbonu 
                         ) *
                         ( wwls * ctest->wwlmult +
                           dxcs * ctest->dxcmult +
                           excs * ctest->excmult 
                         );  
            break;              
    }
x:;    
    if (band->stats==st) UNLOCK(band->stats);
}

void recalc_stats(struct band *band){
    
    if (!band->dirty_stats) return;
    stats_thread_kill(band);
    stats_thread_create(band);
    
            
  /*  ST_STOP;*/
}

void recalc_all_stats(struct contest *ctest){
    int i;
    struct band *band;

    for (i=0; i<ctest->bands->len; i++){
        band = (struct band *)g_ptr_array_index(ctest->bands, i);
        band->dirty_stats = 1;
        recalc_stats(band);
            
    }
}

void recalc_all_qrbqtf(struct contest *ctest){
    int i, j;
    struct band *band;
      struct qso *q;

    for (i=0; i<ctest->bands->len; i++){
        band = (struct band *)g_ptr_array_index(ctest->bands, i);
            
            for (j=0; j<band->qsos->len; j++){
                  q = get_qso(band, j);
                  compute_qrbqtf(q);
            }

        for (j=0; j<TMP_QSOS;j++){
            int qtf_int;
            double qrb, qtf;
            
            if (!band->tmpqsos[j].locator || !*band->tmpqsos[j].locator) break;
            
            /* CHANGE look at add_tmqso_locator */
            qrbqtf(ctest->pwwlo, band->tmpqsos[j].locator, &qrb, &qtf, NULL, 2);
            qtf_int=(int)(qtf+0.5);
            if (qrb < 0.1) {
                qtf_int=0;
            }  
            band->tmpqsos[j].qrb=qrb;
            band->tmpqsos[j].qtf=qtf_int;
        }
    }
}

#define STATS_X 2
#define STATS_Y 2

void redraw_stats(struct band *band){
    gchar *c;
    struct stats *st=band->stats;    
    
    LOCK(band->stats);
    print_text(STATS_X,STATS_Y,-1,VTEXT(T_SES_ODX),COL_NORM);
    if (st->odxcall && st->odxwwl){
        c = g_strdup_printf(VTEXT(T_SES_ODX_DATA), st->odxcall, st->odxwwl, st->odxqrb_int, st->odxoperator);
        print_text(STATS_X+5,STATS_Y,term->x-QSONR_WIDTH-BAND_WIDTH-8, c,COL_NORM);
        g_free(c);
    }    
    print_text(STATS_X,STATS_Y+2,term->x-QSONR_WIDTH-BAND_WIDTH-3,VTEXT(T_SES_STAT_TIT),COL_NORM);
    c = g_strdup_printf("%4d  %6d  %4d  %4d   %4d  %7d",
            st->nqsos, st->nqsop, 
            g_hash_table_size(st->excs), 
            g_hash_table_size(st->wwls), 
            g_hash_table_size(st->dxcs),
            st->ntotal);
    print_text(STATS_X,STATS_Y+3,term->x-QSONR_WIDTH-BAND_WIDTH-3,c,COL_NORM);
    g_free(c);

    if (st->nqsos){
        c = g_strdup_printf(VTEXT(T_SES_AVG), (double)st->ntotal/(double)st->nqsos);
        print_text(term->x-QSONR_WIDTH-BAND_WIDTH,ORIG_Y+1,BAND_WIDTH-1, c, COL_NORM); 
        g_free(c);
    }
    UNLOCK(band->stats);
    
}


#define F b->statsfifo1

void sf_wwl_func(gpointer key, gpointer value, gpointer user_data){
    gchar       *wwl;
    struct cntpts *n;
    GIndexArray *ia;
    
    
    wwl   = (gchar *)       key;  
      n     = (struct cntpts *) value;
    ia    = (GIndexArray *) user_data;

    g_index_array_add(ia, g_strdup_printf("%4s:%6d %3d    ", wwl, n->points, n->count));
}


gint compare_colon_int (gconstpointer a, gconstpointer b){
      gchar **ca, **cb, *c;
      int ia, ib;

      ca=(gchar **)a;
      cb=(gchar **)b;

      c=index(*ca, ':');
      if (c) ia=atoi(c+1);
      else ia=0;
      c=index(*cb, ':');
      if (c) ib=atoi(c+1);
      else ib=0;

      return ib-ia;
}

#define COLS 4
void add_sf_wwls(struct band *b){
    GString *gs;
    GIndexArray *ia;
    int i,j,k,lines;
    gchar *c;
    
    gs = g_string_new("");
    fifo_addf(F, "");
    fifo_addf(F, VTEXT(T_SF_WWLS), g_hash_table_size(b->stats->wwls));
    fifo_addf(F, VTEXT(T_SF_WWLS_UNDER));
   /* for (i=0;i<COLS;i++) g_string_append(gs, " WWL  QSO-p cnt    ");
      fifo_addf(F, gs->str);*/
    
    ia = g_index_array_new();
    g_hash_table_foreach(b->stats->wwls, sf_wwl_func, ia);
    g_index_array_qsort(ia, compare_colon_int);
    g_string_truncate(gs, 0);
    j = 0;
    lines=(ia->len+COLS-1)/COLS;
    
    for (i=0; i<lines ; i++){
        for (j=0;j<COLS; j++){
            k = i+j*lines;
            if (k>=ia->len) continue;
            c = (gchar *)g_index_array_index(ia, k);
            g_string_append(gs, c);        
        }
        fifo_addf(F, "%s", gs->str);
        g_string_truncate(gs, 0);
    }
    g_string_free(gs,1);
    g_index_array_free_all(ia);
}

void sf_dxc_func(gpointer key, gpointer value, gpointer user_data){
    gchar       *dxc;
    struct cntpts *n;
    GIndexArray *ia;
    
    
    dxc   = (gchar *)       key;  
      n     = (struct cntpts *) value;
    ia    = (GIndexArray *) user_data;

    g_index_array_add(ia, g_strdup_printf("%4s:%6d %3d    ", dxc, n->points, n->count));
}

#undef COLS
#define COLS 4
void add_sf_dxcs(struct band *b){
    GString *gs;
    GIndexArray *ia;
    int i,j,k,lines;
    gchar *c;
    
    gs = g_string_new("");
    fifo_addf(F, "");
    fifo_addf(F, VTEXT(T_SF_DXCS), g_hash_table_size(b->stats->dxcs));
    fifo_addf(F, VTEXT(T_SF_DXCS_UNDER));
/*    for (i=0;i<COLS;i++) g_string_append(gs, " DXCC QSO-p cnt    ");
      fifo_addf(F, gs->str);*/
    
    ia = g_index_array_new();
    g_hash_table_foreach(b->stats->dxcs, sf_dxc_func, ia);
    g_index_array_qsort(ia, compare_colon_int);
    g_string_truncate(gs, 0);
    j = 0;
    lines = (ia->len+COLS-1)/COLS;
    for (i=0; i<lines ; i++){
        for (j=0;j<COLS; j++){
            k = i+j*lines;
            if (k>=ia->len) continue;
            c = (gchar *)g_index_array_index(ia, k);
            g_string_append(gs, c);        
        }
        fifo_addf(F, "%s", gs->str);
        g_string_truncate(gs, 0);
    }
    g_string_free(gs,1);
    g_index_array_free_all(ia);
}

void add_sf_wkd_wwls(struct band *b){
    int w,len, lines, i, j, myw, myh;
    GString *gs;

    fifo_addf(F, "");
    fifo_addf(F, VTEXT(T_SF_WKD_WWLS), g_hash_table_size(b->stats->wwls));
    fifo_addf(F, VTEXT(T_SF_WKD_WWLS_UNDER));
    
    w=term->x - 2;
    len = w / 5;
    lines = len;
    
    myh = qthwr(ctest->pwwlo, 0);
    myw = qthwr(ctest->pwwlo, 1);

   /* fifo_addf(F, "w: %d, h:%d ", myw, myh);*/

    gs=g_string_new("");
    
    for(i=0; i<lines ; i++){
        g_string_truncate(gs,0);
        for (j=0; j<len; j++){
            char s[10];
            int aw, ah;
            
            aw = lines-i - lines/2; 
            ah = j - len/2;

            if (aw==0 && ah==0){
                g_string_append(gs, ">QTH<");
                continue;
            }
            mkwwl4(s, aw+ myw , ah + myh);

            if (g_hash_table_lookup(b->stats->wwls, s)){
                g_string_append(gs, "     ");
                continue;
            }
            g_string_sprintfa(gs, " %s", s); 
            
        }
        fifo_addf(F, "%s", gs->str);
    }
    g_string_free(gs, 1);
}


void add_sf_cnt_in_wwls(struct band *b){
    int w,len, lines, i, j, myw, myh;
    GString *gs;

    fifo_addf(F, "");
    fifo_addf(F, VTEXT(T_SF_QSO_WWL4), g_hash_table_size(b->stats->wwls));
    fifo_addf(F, VTEXT(T_SF_QSO_WWL4_UNDER));
    
    w=term->x - 2;
    len = w / 5;
    lines = len;
    
    myh = qthwr(ctest->pwwlo, 0);
    myw = qthwr(ctest->pwwlo, 1);

    /*fifo_addf(F, "w: %d, h:%d ", myw, myh);*/

    gs=g_string_new("");
    
    for(i=0; i<lines ; i++){
        g_string_truncate(gs,0);
        for (j=0; j<len; j++){
            char s[10];
            gint *cnt;
            int aw, ah;
            
            
            aw = lines-i - lines/2; 
            ah = j - len/2;

            mkwwl4(s, aw+ myw , ah + myh);

            if ((cnt = (gint *)g_hash_table_lookup(b->stats->wwls, s))!=NULL){
                if (aw==0 && ah==0){
                    g_string_sprintfa(gs, ">%3d<", *cnt);
                }else{
                    g_string_sprintfa(gs, " %3d ", *cnt); 
                }
                continue;
            }
            g_string_append(gs, "     ");
        }
        fifo_addf(F, "%s", gs->str);
    }
    g_string_free(gs, 1);
}

void add_sf_top_dx(struct band *b)
{
#define TOPS_NUM  10
      int i, cnt=0;
      signed int j;
      struct qso *q, *top[TOPS_NUM];

      memset(top, 0, TOPS_NUM * sizeof(struct qso *));
      for (i = 0; i < b->qsos->len; i++) {
            if (!top[0]) { /* init first item */
                  q = get_qso(b, i);
                  if (!q->error && !q->dupe) {
                        cnt = 0;
                        top[cnt++] = q;
                        /*dbg("init: %s %u\n=\n", top[0]->callsign, (int) top[0]->qrb);*/
                  }
                  continue;
            }

            q = get_qso(b, i);
            /*dbg("selected %u: %s %u\n", i, q->callsign, (int) q->qrb);*/
            if (q->error || q->dupe)
                  continue;

            if (cnt >= TOPS_NUM)
                  cnt = TOPS_NUM - 1;
            
            /* initialize or find top dx and sort top array */
            if (!top[cnt] || q->qrb > top[cnt]->qrb) {
                  for (j = cnt; j >= 0; j--) {
                        if (j && q->qrb > top[j - 1]->qrb) {
                              top[j] = top[j - 1]; /* move down */
                              /*dbg("down %u: %s %u\n", j, top[j]->callsign, (int) top[j]->qrb);*/
                        } else {
                              top[j] = q; /* insert */
                              cnt++;
                              /*dbg("insert %u: %s %u\n", j, top[j]->callsign, (int) top[j]->qrb);*/
                              break;
                        }
                  }
            }
      }

      fifo_addf(F, "");
      fifo_addf(F, VTEXT(T_SF_TOP_DX), TOPS_NUM);
      fifo_addf(F, VTEXT(T_SF_TOP_DX_UNDER));
      for (i = 0; i < TOPS_NUM && i < b->qsos->len && top[i]; i++) {
            q = top[i];
            fifo_addf(F, "%-12s  %-6s  %u km by %-6s %s", q->callsign, q->locator, (int) q->qrb, q->operator, mode_msg[q->mode]);
      }
}

gint compare_hour14 (gconstpointer a, gconstpointer b){
      gchar **ca, **cb;
      int ia, ib;

      ca=(gchar **)a;
      cb=(gchar **)b;

      ia=atoi(*ca);
      if (ia<14) ia+=100;
      
      ib=atoi(*cb);
      if (ib<14) ib+=100;

      return ia-ib;
}

static int maxhourpoints, maxhourcount;
void sf_hour_max_func(gpointer key, gpointer value, gpointer user_data){
    struct cntpts *n;
      n = (struct cntpts *) value;
    
    if (n->points > maxhourpoints) maxhourpoints=n->points;
    if (n->count > maxhourcount) maxhourcount=n->count;
}

#define PS 20
#define CS 20

void sf_hour_func(gpointer key, gpointer value, gpointer user_data){
    gchar       *hour;
    struct cntpts *n;
    GIndexArray *ia;
      int h, i, l, avg;
    char ps[40], cs[40];
    
    
    hour   = (gchar *)       key;  
      n     = (struct cntpts *) value;
    ia    = (GIndexArray *) user_data;

      h=atoi(hour)+1;
      if (h==25) h=0;
      
    if (maxhourpoints>0) l=(n->points*PS)/maxhourpoints;
    else l=0;
    for (i=0;i<PS;i++) if (i<l) ps[i]='*'; else ps[i]=' ';
    ps[i]='\0';
    
    if (maxhourcount>0) l=(n->count*PS)/maxhourcount;
    else l=0;
    for (i=0;i<CS;i++) if (i<l) cs[i]='*'; else cs[i]=' ';
    cs[i]='\0';

    if (n->count>0) avg=n->points/n->count;
    else avg=0;
    
      
    g_index_array_add(ia, g_strdup_printf("%2s-%02d: [%s]%6d  :  [%s]%3d  : %4d  odx %s", hour, h,ps, n->points, cs, n->count, avg, n->qso?n->qso->callsign:"")); /* n->qso should not be nul but for sure... */
}

#undef COLS
void add_sf_hours(struct band *b){
    GIndexArray *ia;
    int i/*,j,k,lines*/;
    gchar *c;
    
    fifo_addf(F, "");
    fifo_addf(F, VTEXT(T_SF_HOURS));
    fifo_addf(F, VTEXT(T_SF_HOURS_UNDER));
    fifo_addf(F, VTEXT(T_SF_HOURS_TITLE));
    
    ia = g_index_array_new();
    maxhourpoints=0;
    maxhourcount=0;
    g_hash_table_foreach(b->stats->hours, sf_hour_max_func, ia);
    g_hash_table_foreach(b->stats->hours, sf_hour_func, ia);
    g_index_array_qsort(ia, compare_hour14);
    for (i=0; i<ia->len ; i++){
        c = (gchar *)g_index_array_index(ia, i);
        fifo_addf(F, "%s", c);
    }
    g_index_array_free_all(ia);
}


void recalc_statsfifo(struct band *b){
    
    if (!b || !b->dirty_statsf) return;

    stats_thread_join(b);
    /*ST_START;*/
    free_fifo(F);
    F = init_fifo(1000);
    F->withouttime = 1;

    fifo_addf(F, "");
    fifo_addf(F, VTEXT(T_SF_STATS_BAND), b->pband);
    fifo_addf(F, VTEXT(T_SF_STATS_BAND_UNDER));
    fifo_addf(F, "");

    if (b->stats->nqsos>0){
        fifo_addf(F, VTEXT(T_SF_AVG_PTS), ((double)b->stats->ntotal) / ((double)b->stats->nqsos));
        fifo_addf(F, VTEXT(T_SF_AVG_QSOP), ((double)b->stats->nqsop) / ((double)b->stats->nqsos));
            fifo_addf(F, VTEXT(T_SF_QSO_HOUR), b->stats->qso_per_hour);
            fifo_addf(F, VTEXT(T_SF_QSOP_HOUR), b->stats->pts_per_hour);
            fifo_addf(F, VTEXT(T_SF_QSOP_50QSO), b->stats->pts_per_50qso);

    }
    fifo_addf(F, "");

      if (ctest->qsop_method==4){
      add_sf_wkd_wwls(b);
      add_sf_cnt_in_wwls(b);
      }
      add_sf_wwls(b);
    add_sf_dxcs(b);
    add_sf_hours(b);
      add_sf_top_dx(b);

    fifo_addf(F, "");
    b->dirty_statsf = 0;
    /*ST_STOP; */
}

/* Exports statistics of actual band to a text file */
void export_stats_fifo(void) {
      gchar *fname;
      int i;
      
      fname = NULL;
      for (i = 0; 1; i++) {
            struct stat st;
            
            fname = g_strdup_printf("%s/stat%c%d.txt", ctest->directory, aband->bandchar, i);
            if (stat(fname, &st) != 0)
                  break;

            g_free(fname);
            fname = NULL;
      }
      
      recalc_statsfifo(aband);
      save_fifo_to_file(aband->statsfifo1, fname);
      
      g_free(fname);
}

gpointer stats_thread_func(gpointer data){
    struct qso *q;
    int i;
    struct band *band=(struct band*)data;
    struct stats *tmp;
    char s[256];

/*    ST_START;*/
    clear_stats(band->tmpstats);

    for (i=0; i<band->qsos->len; i++){
        if (band->stats_break) break;
        q = get_qso(band, i);
        update_stats(band, band->tmpstats, q);
    }
    LOCK(band->stats);
    tmp=band->stats;
    band->stats=band->tmpstats;
    band->tmpstats=tmp;
    UNLOCK(band->stats);

      minute_stats(band);
    
    band->dirty_save = 1;
    
    sprintf(s, "ST\n");
    write(tpipe->threadpipe_write, s, strlen(s));
    
    band->dirty_stats = 0;
   /* dbg("stats done %c\n", band->bandchar);*/
    return 0;
}

void stats_thread_create(struct band *band){
    if (band->stats_thread) raise(SIGSEGV);
    /*dbg("stats_thread_create(%c)\n", band->bandchar);*/
    band->stats_break=0;
    band->stats_thread=g_thread_create(stats_thread_func, (gpointer)band, TRUE, NULL);
    if (!band->stats_thread) raise(SIGSEGV);
}

void stats_thread_join(struct band *band){
    if (!band->stats_thread) return;
   /* dbg("stats_thread_join(%c)...\n", band->bandchar);*/
    g_thread_join(band->stats_thread);
 /*   dbg("done\n");*/
    band->stats_thread=NULL;
    
}

void stats_thread_kill(struct band *band){
    if (!band->stats_thread) return;
/*    dbg("stats_thread_kill(%c)\n", band->bandchar);*/
    band->stats_break=1;
    g_thread_join(band->stats_thread);
    band->stats_thread=NULL;
}


void minute_stats(struct band *band){
    struct qso *qso;
    int j,brk, cnt50;
      int qso_per_hour, pts_per_hour, pts_per_50qso;
      char s[100], hourbefore[100];
    time_t hb;
    struct tm utc;
    
      hb=time(NULL)-3600;
    gmtime_r(&hb, &utc);
    sprintf(hourbefore, "%4d%02d%02d%02d%02d",1900+utc.tm_year, 1+utc.tm_mon, utc.tm_mday, utc.tm_hour, utc.tm_min);  

      
      if (band->qsos->len==0) return;
      qso_per_hour=pts_per_hour=pts_per_50qso=0;
      cnt50=50;
      brk=0;
      for (j=band->qsos->len-1;j>=0;j--){
            if (band->stats_break) break;
            qso = (struct qso *)g_ptr_array_index(band->qsos, j);

            if (qso->error || qso->dupe) continue;
            
            strcpy(s, qso->date_str);
            strcat(s, qso->time_str);
/*          dbg("s=%s h=%s\n", s, hourbefore);*/
            if (strcmp(s, hourbefore)>0){
                  qso_per_hour++;
                  pts_per_hour+=qso->qsop;
            }else{
                  brk|=0x01;
            }
            
            
            if (cnt50-->0){
                  pts_per_50qso+=qso->qsop;
            }else{
                  brk|=0x02;
            }

            if (brk==0x03) break;
      }
      LOCK(band->stats);
      if (band->stats->qso_per_hour!=qso_per_hour ||
            band->stats->pts_per_hour!=pts_per_hour ||
            band->stats->pts_per_50qso!=pts_per_50qso){
      
            band->stats->qso_per_hour=qso_per_hour;
            band->stats->pts_per_hour=pts_per_hour;
            band->stats->pts_per_50qso=pts_per_50qso;
            band->dirty_statsf = 1;
      }
      UNLOCK(band->stats);
}

void minute_stats_all(void){
    struct band *band;
      int i;

      if (!aband) return;
      

    for (i=0;i<ctest->bands->len;i++){
        band = (struct band *)g_ptr_array_index(ctest->bands, i);

            minute_stats(band);
      }
      if (aband->dirty_statsf) recalc_statsfifo(aband);
}

void timer_minute_stats_all(union cba_t cba){
      minute_stats_all();
      ctest->minute_timer_id=install_timer(60000, timer_minute_stats_all, CBA0);
}

Generated by  Doxygen 1.6.0   Back to index