/*  tally.c is part of Statnet */
/* Statnet is protected under the GNU Public License (GPL2). */
/* Author: Jeroen Baekelandt (jeroenb@igwe.vub.ac.be)       */
/* 08FEB98: Scot E. Wilcoxon (sewilco@fieldday.mn.org)     */

/* This function tallies an item in a tally structure. */

#include "stat.h"

int tally (int type_wanted, struct Tally *tally)
{
    int result;
    int index, search_int, value_now;

    result = 0;
    search_int = 0;

    if( tally == (struct Tally *)0 )
      result = 1;		/* flag that could not tally here */
    else
    {  /* if pointer defined */
	if( tally->count != (unsigned int *)0 )
	{  /* if using counter array */
	  if( type_wanted <= tally->c_max )
	    tally->count[type_wanted]++;
	  else
	    result = 2;		/* flag that could not tally here */
	}  /* if using counter array */
	else
	  result = 3;		/* flag that could not tally here */

	if( result > 0 )
	{  /* if not tallied yet, try an array of types */
	  result = 0;

	  if( tally->types != (unsigned int *)0 &&
	      tally->t_count != (unsigned int *)0 &&
	      tally->t_values != (unsigned int *)0 )
	  {  /* if using an array of type counters */

		  for (index = 0; index < tally->t_max; index++)
		    {			/* for all counters */
		      if ((value_now = tally->types[index]) > 0)
			{		/* if a type to display is defined */
			  if (tally->t_values[value_now] == type_wanted)
			    {		/* if this is the type number which was encountered */
			      tally->t_count[index]++;	/* tally this type */
			      break;
			    }		/* if this is the type number which was encountered */
			}		/* if a type to display is defined */
		    }			/* for all counters */

		  if (index >= tally->t_max)
		    {			/* if type was not found */
		      for (search_int = 0; search_int < tally->t_max_labels; search_int++)
			{		/* for all known types */
			  if (type_wanted == tally->t_values[search_int])
			    {		/* if wanted type was found */
			      if (tally->types[tally->t_max - 1] > 0 &&
				  tally->t_count[tally->t_max - 1] > 0)
				{	/* if last displayed type was in use, add to bottom */
					  tally->t_count[tally->t_max-1] = 1;
					  tally->types[tally->t_max-1] = search_int;	/* remember type index */
				}	/* if last displayed type was in use, add to bottom */
			      tally->types[tally->t_max - 1] = search_int;
			      tally->t_count[tally->t_max - 1] = 1;		/* tally this type */
				  for (index = tally->t_max-1; index > 0; index--)
				    {			/* sort all displayed types */
				      if (tally->t_count[index] > tally->t_count[index-1] )
					{  /* if previous count is smaller than this one, shuffle up */
					  int temp_count, temp_type;

					  temp_count = tally->t_count[index];
					  temp_type = tally->types[index];
					  tally->t_count[index] = tally->t_count[index-1];
					  tally->types[index] = tally->types[index-1];
					  tally->t_count[index-1] = temp_count;
					  tally->types[index-1] = temp_type;
					}  /* if previous count is smaller than this one, shuffle up */
				    }			/* sort all displayed types */
			      break;
			    }		/* if wanted type was found */
			}		/* for all known types */
			if( search_int >= tally->t_max_labels )
				result = 4;	/* not tallied */
		    }			/* if type was not found */
	  }  /* if using an array of type counters */
	  else
		result = 5;	/* not tallied */
	}  /* if not tallied yet, try an array of types */
    }  /* if pointer defined */

    return result;
}
