///////////////////////////////////////////////////////////////////////
// ITS – Visoka Škola Strukovnih Studija Za Informacione Tehnologije
//
https://www.its.edu.rs
// Predmet: Osnovi Programiranja – Programski jezik C
//
// Primer: Program za izracunavanje statistike u grupi
//na SP u fudbalu. Grupa ima 4 tima, u grupi igra svako sa svakim,
//na osnovu odigranih utakmica u grupi i unetih rezultata izracunava
//se: poredak u grupi, ekipa sa najboljom gol razlikom,
//ekipa sa najvise postignutih golova.
///////////////////////////////////////////////////////////////////////
#include<stdio.h>
#include<stdlib.h>
#define BODOVI_POBEDA 3
#define BODOVI_NERESENO 1

struct utakmica
   {
   // Jedinstveni broj tima 1
   int tim1_id;
   // Jedinstveni broj tima 2
   int tim2_id;
   int tim1_golovi;
   int tim2_golovi;
   };

// Red u tabeli, tj. struktura sa podacima koja odredjuje tim i njegovu statistiku
struct clan_tabele
   {
   // Jedinstveni broj tima
   int id;
   // Naziv tima fiksiran na 10 karaktera
   char naziv[10];
   int utakmica;
   int pobeda;
   int nereseno;
   int poraza;
   int postignuti_golovi;
   int primljeni_golovi;
   int bodovi;
   int gol_razlika;
   };

// Niz struktura za unos rezultata utakmica
struct utakmica *utakmice;

// Niz struktura za tabelu, rang-listu timova
struct clan_tabele *tabela;

void
uredi_podatke_u_tabeli_za_tim(int postignuti_golovi, int primljeni_golovi, int id);
void inicijalizacija_podataka_tabele();
void sortiranje_tabele();
void zameni_mesta(struct clan_tabele *tim1, struct clan_tabele *tim2);
void ispis_tabele();
int kombinacije(int n, int k);
int provera_pozicije(struct clan_tabele *tim_a, struct clan_tabele *tim_b);
int provera_medjusobnih_susreta(struct clan_tabele *tim_a, struct clan_tabele *tim_b);
int provera_unosa_rezultata(int goloviA, int goloviB);
int BROJ_TIMOVA;
int BROJ_UTAKMICA;


main()
{
int i, j, susret = 0;
printf(“Unesite broj timova: “);
// Korisnik odredjuje broj timova sto ce odrediti duzinu niza za tabelu
scanf(“%d”, &BROJ_TIMOVA);

if(1 >= BROJ_TIMOVA)
  {
    printf(”
Pogresan unos!!nl!”);
    return 0;
    }


// Inicijalizacija niza struktura

tabela = (struct clan_tabele*)malloc(BROJ_TIMOVA * sizeof(struct clan_tabele));

// Upis podrazumevanih vrednosti u tabelu
inicijalizacija_podataka_tabele();

// Izracunavanje broja svih mogucih utakmica

BROJ_UTAKMICA = kombinacije(BROJ_TIMOVA, 2);

// Alokacija praznog niza sa maksimalnim mogucim brojem utakmica
utakmice = (struct utakmica*)malloc(BROJ_UTAKMICA * sizeof(struct utakmica));
printf(“Unosite nazive timova do 7 karaktera duzine.
“);

// Popunjavanje naziva ekipa
for(i = 0;i < BROJ_TIMOVA;i++)
    {
      printf(“Unesite naziv reprezentacije %d: “, i + 1);
      scanf(“%s”, &tabela[i].naziv);
      tabela[i].id = i;
      }

// Popunjavanje rezultata utakmica
// Iteracijom kroz dve petlje dobijamo broj prolaza koji odgovara promenljivoj BROJ_UTAKMICA.
// To znaci da se dobijaju parovi (utakmice) po kriterijumu ‘svako sa svakim’ – kombinacije bez ponavljanja.
// Timove uzimamo iz tabele timova.

for(i = 0; i < BROJ_TIMOVA – 1;i++)
    {
      for(j = i + 1;j < BROJ_TIMOVA; j++)
           {
            printf(“Unesite rezultat utakmice: %s – %s “, tabela[i].naziv, tabela[j].naziv);
            scanf(“%d %d”, &utakmice[susret].tim1_golovi, &utakmice[susret].tim2_golovi);
             // Provera ispravnog unosa podataka
       if(0 == provera_unosa_rezultata(utakmice[susret].tim1_golovi, utakmice[susret].tim2_golovi))
         {
           printf(”
Pogresan unos!
“);
           return 0;
          }

// Dodela id_a svakog tima po utakmici. Uspostavlja se relacija tim-utakmica.
// Kasnije se id_i koriste za rekonstrukciju rezultata utakmice.
utakmice[susret].tim1_id = tabela[i].id;
utakmice[susret].tim2_id = tabela[j].id;
susret++;
}
}


// Kroz petlju se uredjuju podaci u tabeli
for(i = 0;i < BROJ_UTAKMICA;i++)
  {
   // Za prvi tim
   uredi_podatke_u_tabeli_za_tim(utakmice[i].tim1_golovi, utakmice[i].tim2_golovi, utakmice[i].tim1_id);

// Za drugi tim: primljeni golovi po utakmici su ustvari postignuti golovi za tim broj dva.
// Zato se menja pozicija argumenata
uredi_podatke_u_tabeli_za_tim(utakmice[i].tim2_golovi, utakmice[i].tim1_golovi, utakmice[i].tim2_id);
}

     // Pravljenje rang-liste timova
     sortiranje_tabele();
     ispis_tabele();
}

int provera_unosa_rezultata(int goloviA, int goloviB)
    {
      int retValue = 1;
      if(goloviA < 0 || goloviB < 0)
         {
           retValue = 0;
          }
      return retValue;
      }

// Funkcija postavlja podrazumevane vrednosti u inicijalizovan niz struktura
void inicijalizacija_podataka_tabele()
     {
       int i;
       for(i = 0; i < BROJ_TIMOVA;i++)
          {
            (*(tabela + i)).bodovi = 0;
            (*(tabela + i)).gol_razlika = 0;
            (*(tabela + i)).nereseno = 0;
            (*(tabela + i)).pobeda = 0;
            (*(tabela + i)).poraza = 0;
            (*(tabela + i)).postignuti_golovi = 0;
            (*(tabela + i)).primljeni_golovi = 0;
            (*(tabela + i)).utakmica = 0;
           }
     }

// Funkcija izracunava max broj kombinacija.
// Formula za kombinacije bez ponavljanja je: n! / (k! * (n – k)!)
int kombinacije(int n, int k)
    {
      int i, a = 1, b = 1, c = 1;
      for(i = 1;i <= n;i++)
          {
            a *= i;
           }
            for(i = 1;i <= k;i++)
                {
                  b *= i;
                 }
                 for(i = 1;i <= n – k;i++)
                      {
                       c *= i;
                       }
   return a / (b * c);
   }

 

// Funkcija azurira vrednosti u tabeli
void uredi_podatke_u_tabeli_za_tim(int postignuti_golovi, int primljeni_golovi, int id)
     {
      int i;
      for(i = 0; i < BROJ_TIMOVA;i++)
         {
         if(id == tabela[i].id)
           {
            tabela[i].utakmica += 1;
            tabela[i].postignuti_golovi += postignuti_golovi;
            tabela[i].primljeni_golovi += primljeni_golovi;

            // Za svaku izmenu se azurira i gol-razlika
           tabela[i].gol_razlika = tabela[i].postignuti_golovi – tabela[i].primljeni_golovi;
          if(postignuti_golovi > primljeni_golovi)
             {
              tabela[i].pobeda += 1;

             // Za pobedu se dodeljuje 3 boda
             tabela[i].bodovi += BODOVI_POBEDA;
             }

             else if(postignuti_golovi == primljeni_golovi)
                 {
                  tabela[i].nereseno += BODOVI_NERESENO;

                 // Za nereseno 1 bod
                 tabela[i].bodovi += 1;
                 }
             else
                {
                tabela[i].poraza += 1;
                }
            }
         }
      }

// Funkcija odredjuje kriterijum za zamenu mesta dva tima u tabeli
int provera_pozicije(struct clan_tabele *tim_a, struct clan_tabele *tim_b)
   {
    int retValue = 0;
    // Prvi kriterijum je broj bodova
    if((*tim_a).bodovi < (*tim_b).bodovi)
     {
       retValue = 1;
     }
     else if((*tim_a).bodovi == (*tim_b).bodovi)
          {
           // Drugi kriterijum je gol razlika
          if((*tim_a).gol_razlika < (*tim_b).gol_razlika)
           {
            retValue = 1;
            }
     else if((*tim_a).gol_razlika == (*tim_b).gol_razlika)
          {
          // Treci kriterijum je uspesnost u medjusobnim susretima
          if(1 == provera_medjusobnih_susreta(tim_a, tim_b))
            {
              retValue = 1;
            }
     else
          {
          // Cetvrti kriterijum je broj postignutih golova
         if((*tim_a).postignuti_golovi < (*tim_b).postignuti_golovi)
           {
             retValue = 1;
            }
         }
      }
   }
   return retValue;
   }

int provera_medjusobnih_susreta(struct clan_tabele *tim_a, struct clan_tabele *tim_b)
   {
   int retValue = 0, i, j;
   for(i = 0; i < BROJ_UTAKMICA;i++)
     {
    // U tabeli utakmica se trazi konkretna utakmica pomocu id timova, da bi se uporedio
    // skor u medjusobnom susretu
    if(utakmice[i].tim1_id == (*tim_a).id && utakmice[i].tim2_id == (*tim_b).id)
     {
     // Drugi tim je dao vise golova u datoj utakmici – pobedio je,
    // znaci da je bolji u medjusobnom susretu
    if(utakmice[i].tim1_golovi < utakmice[i].tim2_golovi)
       {
        retValue = 1;
        }
      }
    }
  return retValue;
  }

// Funkcija sortiranja tabele na osnovu postignutih rezultata timova
void sortiranje_tabele()
   {
    int i, j;
    for(i = 0; i < BROJ_TIMOVA – 1;i++)
       {
       for(j = i + 1; j < BROJ_TIMOVA;j++)
           {

            //Uslov odlucuje o zameni mesta u tabeli
            if(provera_pozicije(&tabela[i], &tabela[j]))
              {
              zameni_mesta(&tabela[i], &tabela[j]);
              }
            }
          }
        }

// Funkcija menja mesta timovima
void zameni_mesta(struct clan_tabele *tim1, struct clan_tabele *tim2)
      {
       struct clan_tabele temp;
       temp = *tim1;
       *tim1 = *tim2;
       *tim2 = temp;
       }

// Ispis tabele
void ispis_tabele()
      {
       int i;
       printf(“!nl!”);
       printf(“Naziv bodovi meceva pobeda remi poraza g+ g- g+-!nl!”);

 printf(“——————————————————————–!nl!”);
 for(i = 0; i < BROJ_TIMOVA;i++)
  {
  printf(“%s %d %d %d %d %d %d %d %d
“, tabela[i].naziv, tabela[i].bodovi, tabela[i].utakmica, tabela  [i].pobeda, tabela[i].nereseno, tabela[i].poraza, tabela[i].postignuti_golovi, tabela[i].primljeni_golovi, tabela[i].gol_razlika);
 }
 }