#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <cmath>
using namespace std;

struct kozbeszerzes {
    string ajanlatkero;
    string nyertes;
    unsigned long int ar;
    float CRI;
};

unsigned long to_long(string szam){
    stringstream ss;
    ss << szam;
    unsigned long eredmeny;
    ss >> eredmeny;
    return eredmeny;
}

float to_float(string szam){
    stringstream ss;
    ss << szam;
    float eredmeny;
    ss >> eredmeny;
    return eredmeny;
}

kozbeszerzes sorbol_olvas(string sor){
    stringstream ss;
    ss << sor;
    string adat;
    kozbeszerzes kb;
    getline(ss, adat, ';'); // ID --> nem kell
    getline(ss, adat, ';'); // Cim --> nem kell
    getline(ss, kb.ajanlatkero, ';'); // Ajanlatkero
    getline(ss, kb.nyertes, ';'); // Nyertes
    getline(ss, adat, ';'); // Ar
    kb.ar = to_long(adat);
    getline(ss, adat, ';'); // Konzorciumi tagokra szamolt ar --> nem kell
    getline(ss, adat, ';'); // CRI
    kb.CRI = to_float(adat);
    // Az url nem érdekel, azt ki sem olvasom a sorból...
    return kb;
}

struct kozbeszerzesek {
private:
    vector<kozbeszerzes> adatok;

    int keres(string mit, vector<string>& cegek) {
        for (unsigned i = 0; i < cegek.size(); i++)
            if (cegek[i] == mit)
                return i;
        return -1;
    }

public:
    void beolvas(string fname) {
        ifstream bf(fname);
        if (bf.fail())
            cerr << "Nem sikerült a fájl megnyitása!\n";
        string sor;
        getline(bf,sor); // Beolvasom a fejléc sort, amiben az egyes mezők nevei vannak, és el is vetem rögtön
        while(getline(bf,sor))
            adatok.push_back(sorbol_olvas(sor));
    }
    void ellenoriz() {
        for (unsigned i = 0; i < 10; i++)
            cout << adatok[i].ajanlatkero << endl << adatok[i].nyertes << endl
                 << adatok[i].ar << endl << adatok[i].CRI << endl << endl;
    }
// A csoport feladatai
    void makulatlan() {
        vector<string> cegek;
        for(unsigned i = 0; i < adatok.size(); i++) {
            if (adatok[i].CRI == 0 and keres(adatok[i].nyertes, cegek) == -1)
                cegek.push_back(adatok[i].nyertes);
        }
        cout << cegek.size() << " cég vett részt makulátlan eljárásban.\n";
    }
    void legnagyobb() {
        long eddigi_legnagyobb_ar = adatok[0].ar;
        string eddigi_legnagyobb_nyertes = adatok[0].ajanlatkero;
        for (unsigned i = 1; i < adatok.size(); i++)
            if (eddigi_legnagyobb_ar < adatok[i].ar) {
                eddigi_legnagyobb_ar = adatok[i].ar;
                eddigi_legnagyobb_nyertes = adatok[i].ajanlatkero;
            }
        cout << eddigi_legnagyobb_nyertes << " volt a megrendelője a legnagyobb összegű pályázatnak.\n";
    }
    void viszonylag_tiszta() {
        vector<string> cegek;
        vector<unsigned> hany_palyazatot_nyert;
        for (unsigned i = 0; i < adatok.size(); i++) {
            if (adatok[i].CRI == -1 or adatok[i].CRI >= .1)
                continue;
            int hely = keres(adatok[i].nyertes, cegek);
            if (hely == -1) {
                cegek.push_back(adatok[i].nyertes);
                hany_palyazatot_nyert.push_back(1);
            } else
                hany_palyazatot_nyert[hely]++;
        }
        unsigned maximum = hany_palyazatot_nyert[0], hely = 0;
        for (unsigned i = 1; i < hany_palyazatot_nyert.size(); i++)
            if (maximum < hany_palyazatot_nyert[i]) {
                maximum = hany_palyazatot_nyert[i];
                hely = i;
            }
        cout << cegek[hely] << " nyert legtöbbször viszonylag tiszta körülmények között.\n";
    }
// B csoport feladatai
    // Ennél a feladatnál sajnos nem egyértelmű, hogy azok a cégek kellenek, amiknek volt 0.05 CRI alatti pályázatuk,
    // vagy akiknek CSAK olyan pályázatuk volt. Ezért most azt oldom meg, hogy ha csak olyan pályázatuk volt.
    bool volt_e_gyanus_palyazata(string cegnev) {
        for (unsigned i = 0; i < adatok.size(); i++)
            if (adatok[i].nyertes == cegnev and adatok[i].CRI >= .05)
                return true;
        return false;
    }
    void legkevesbe_gyanus() {
        // Azok a cégek, amelyeknek volt 0.05 CRI alatti pályázatuk
        vector<string> cegek;
        for(unsigned i = 0; i < adatok.size(); i++) {
            if (adatok[i].CRI != -1 and adatok[i].CRI < .05 and keres(adatok[i].nyertes, cegek) == -1)
                cegek.push_back(adatok[i].nyertes);
        }

        // Ezek közül csak azokat írom ki, akiknek nem volt 0.05 CRI feletti pályázatuk
        cout << "A következő cégek nyertek a legkevésbé gyanús körülmények közt:\n";
        for (unsigned i = 0; i < cegek.size(); i++)
            if (!volt_e_gyanus_palyazata(cegek[i]))
                cout << cegek[i] << endl;
        cout << endl;
    }
    void tulcsordulas() {
        const unsigned long maximum = pow(2, 32) / 2;
        unsigned szamlalo = 0;
        for (unsigned i = 0; i < adatok.size(); i++)
            if (adatok[i].ar > maximum)
                szamlalo++;
        cout << szamlalo << " db pályázat volt, aminek az összege nem ábrázolható 32 bites egészekkel.\n";
    }
    void egyszer_nyert() {
        vector<string> cegek;
        vector<unsigned> hany_palyazatot_nyert;
        for (unsigned i = 0; i < adatok.size(); i++) {
            int hely = keres(adatok[i].nyertes, cegek);
            if (hely == -1) {
                cegek.push_back(adatok[i].nyertes);
                hany_palyazatot_nyert.push_back(1);
            } else
                hany_palyazatot_nyert[hely]++;
        }
        unsigned szamlalo = 0;
        for (unsigned i = 1; i < hany_palyazatot_nyert.size(); i++)
            if (hany_palyazatot_nyert[i] == 1)
                szamlalo++;
        cout << szamlalo << " db cég nyert csak egy pályázatot.\n";
    }
};

int main(){
    setlocale(0, "");
    kozbeszerzesek k;
    k.beolvas("budapest_kozbeszerzesek.csv");
    //k.ellenoriz();

    // A csoport feladatai
    k.makulatlan();
    k.legnagyobb();
    k.viszonylag_tiszta();
    cout << endl;

    // B csoport feladatai
    k.legkevesbe_gyanus();
    k.tulcsordulas();
    k.egyszer_nyert();
}
