#include #include #include #include using namespace std; const int wxID_START = 1001; // Funkcija vraca slucajan broj na intervalu od 0 do 1 double random() { return rand()/(1.0*RAND_MAX); } // Stanja enum state { reading_card, // Citam kartu reading_pin, // Citam PIN choosing_transaction, // Izabiram transakciju performing_transaction, // Transakcija ejecting_card // Izbacujem karticu }; // Dogadjaji enum event { card_readable, // Kartica moze da se procita card_not_readable, // Kartica ne moze da se procita cancel, // Otkazivanje pin_read, // Ucitan PIN invalid_pin, // Neispravan PIN transaction_chosen, // Izabrana transakcija another_transaction, // Druga transakcija customer_finished // Korisnik zavrsava }; // Dijagram stanja class statechart { // Zastavica prelaska u zavrsno stanje bool _final; // Tekuce stanje state _current; public: // Konstruktor statechart(): _final(false) {} // Postavljamo pocetno stanje void initial(const state s) { _current = s; } // Tranzicija iz stanja u stanje na osnovu okinutog dogadjaja void transition(const event e) { // Proveravamo koji je dogadja okinut i na osnovu okinutog dogadjaja sprovodimo promenu stanja. switch (e){ case card_readable: if(_current==reading_card) { _current = reading_pin; cout << "READING_PIN" << endl; } else { cerr << "Error" << std::endl; exit(1); } break; case card_not_readable: if(_current==reading_card) { _current = ejecting_card; cout << "EJECTING_CARD" << endl; } else { cerr << "Error" << std::endl; exit(1); } break; case cancel: if(_current==reading_pin) { _current = ejecting_card; cout << "EJECTING_CARD" << endl; } else if(_current==choosing_transaction) { _current = ejecting_card; cout << "EJECTING_CARD" << endl; } else { cerr << "Error" << std::endl; exit(1); } break; case pin_read: if(_current==reading_pin) { _current = choosing_transaction; cout << "CHOOSING_TRANSACTION" << endl; } else { cerr << "Error" << std::endl; exit(1); } break; case invalid_pin: if(_current==reading_pin) { _current = reading_pin; cout << "READING_PIN" << endl; } else { cerr << "Error" << std::endl; exit(1); } break; case transaction_chosen: if(_current==choosing_transaction) { _current = performing_transaction; cout << "PERFORMING_TRANSACTION" << endl; } else { cerr << "Error" << std::endl; exit(1); } break; case another_transaction: if(_current==performing_transaction) { _current = choosing_transaction; cout << "CHOOSING_TRANSACTION" << endl; } else { cerr << "Error" << std::endl; exit(1); } break; case customer_finished: if(_current==performing_transaction) { _current = ejecting_card; cout << "EJECTING_CARD" << endl; } else { cerr << "Error" << std::endl; exit(1); } break; default: break; } } public: // Postavi u finalno stanje i vrati da li je u finalnom stanju bool get_final() { return _final; } void set_final(const bool f) { _final = f; } // Postavi i vrati tekuce stanje void set_current(const state s) { _current = s; } state get_current() const { return _current; } }; void RunATM(wxPanel* pPanel) { wxPaintDC dc(pPanel); wxSize size = pPanel->GetSize(); dc.SetBrush(*wxBLACK_BRUSH); dc.SetPen(*wxRED_PEN); dc.DrawCircle(size.GetWidth()/2,30,10); dc.DrawLine(size.GetWidth()/2,40,size.GetWidth()/2,60); dc.SetBrush(*wxYELLOW_BRUSH); dc.DrawRoundedRectangle(size.GetWidth()/2-50,60,100,40,5); dc.DrawLabel("READING CARD",wxRect(size.GetWidth()/2-50,60,100,40),wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL); dc.DrawLine(size.GetWidth()/2,100,size.GetWidth()/2,120); dc.DrawText("Card readable",size.GetWidth()/2+5,103); dc.DrawRoundedRectangle(size.GetWidth()/2-50,120,100,40,5); dc.DrawLabel("READING PIN",wxRect(size.GetWidth()/2-50,120,100,40),wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL); dc.DrawLine(size.GetWidth()/2,160,size.GetWidth()/2,180); dc.DrawText("PIN read",size.GetWidth()/2+5,163); dc.DrawRoundedRectangle(size.GetWidth()/2-60,180,120,50,5); dc.DrawLabel("CHOOSING\nTRANSACTION",wxRect(size.GetWidth()/2-60,180,120,50),wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL); dc.DrawLine(size.GetWidth()/2,230,size.GetWidth()/2,250); dc.DrawText("Trans. chosen",size.GetWidth()/2+5,233); dc.DrawRoundedRectangle(size.GetWidth()/2-60,250,120,50,5); dc.DrawLabel("PERFORMING\nTRANSACTION",wxRect(size.GetWidth()/2-60,250,120,50),wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL); dc.DrawLine(size.GetWidth()/2,300,size.GetWidth()/2,320); dc.DrawText("Cust. finished",size.GetWidth()/2+5,303); dc.DrawRoundedRectangle(size.GetWidth()/2-60,320,120,50,5); dc.DrawLabel("EJECTING CARD",wxRect(size.GetWidth()/2-60,320,120,50),wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL); dc.DrawLine(size.GetWidth()/2,370,size.GetWidth()/2,397); dc.SetBrush(*wxBLACK_BRUSH); dc.DrawCircle(size.GetWidth()/2,410,10); dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.DrawCircle(size.GetWidth()/2,410,13); // Card not readable dc.DrawLine(size.GetWidth()/2+50,80,size.GetWidth()/2+180,80); dc.DrawLine(size.GetWidth()/2+180,80,size.GetWidth()/2+180,410); dc.DrawText("Card not readable",size.GetWidth()/2+65,65); // Cancel dc.DrawLine(size.GetWidth()/2+50,140,size.GetWidth()/2+140,140); dc.DrawLine(size.GetWidth()/2+140,140,size.GetWidth()/2+140,410); dc.DrawText("Cancel",size.GetWidth()/2+65,125); // Cancel dc.DrawLine(size.GetWidth()/2+60,205,size.GetWidth()/2+100,205); dc.DrawLine(size.GetWidth()/2+100,205,size.GetWidth()/2+100,410); dc.DrawText("Cancel",size.GetWidth()/2+65,190); dc.DrawLine(size.GetWidth()/2+13,410,size.GetWidth()/2+180,410); // Too many invalid pins dc.DrawLine(size.GetWidth()/2-50,130,size.GetWidth()/2-160,130); dc.DrawLine(size.GetWidth()/2-160,130,size.GetWidth()/2-160,410); dc.DrawLine(size.GetWidth()/2-13,410,size.GetWidth()/2-160,410); dc.DrawRotatedText("Too many invalid pins", wxPoint(size.GetWidth()/2-180,320), 90); // Invalid pin dc.DrawLine(size.GetWidth()/2-80,130,size.GetWidth()/2-80,150); dc.DrawLine(size.GetWidth()/2-80,150,size.GetWidth()/2-50,150); dc.DrawText("Invalid PIN",size.GetWidth()/2-110,153); // Another transaction dc.DrawLine(size.GetWidth()/2-60,275,size.GetWidth()/2-100,275); dc.DrawLine(size.GetWidth()/2-100,275,size.GetWidth()/2-100,205); dc.DrawLine(size.GetWidth()/2-100,205,size.GetWidth()/2-60,205); dc.DrawRotatedText("Another\ntransaction", wxPoint(size.GetWidth()/2-135,270), 90); } void Start() { // Verovatnoca double p; // Brojac pogresno unetih PIN-ova int ip = 1; // Objekat dijagrama stanja statechart sc; // Seme generatora slucajnih brojeva iniciramo vremenom. // Na ovaj nacin sa svakim izvresenjem programa dobijamo druge vrednosti stanja. srand(time(NULL)); // Postavljamo pocetno stanje sc.initial(reading_card); cout << "READING_CARD" << endl; // Prolazimo kroz sva stanja dijagrama stanja dok ne dodjemo do finalnog while(!sc.get_final()) { if(sc.get_current()==reading_card) { p = random(); if(p<=0.05) { sc.transition(card_not_readable); sc.set_final(true); } else { sc.transition(card_readable); } } else if(sc.get_current()==reading_pin) { p = random(); if(p<=0.05) { if(ip<3) { sc.transition(invalid_pin); ++ip; } else { sc.set_final(true); } } if(p<=0.25) { sc.transition(cancel); sc.set_final(true); } else { sc.transition(pin_read); } } else if(sc.get_current()==choosing_transaction) { p = random(); if(p<=0.20) { sc.transition(cancel); sc.set_final(true); } else { sc.transition(transaction_chosen); } } else if(sc.get_current()==performing_transaction) { p = random(); if(p<=0.40) { sc.transition(another_transaction); } else { sc.transition(customer_finished); sc.set_final(true); } } } cout << endl; } void ShowMainWindow() { wxFrame* pMainFrame = new wxFrame(nullptr,wxID_ANY,"Bankomat",wxDefaultPosition,wxSize(800,600)); wxBoxSizer* pSizer = new wxBoxSizer(wxVERTICAL); wxPanel* pPanel = new wxPanel(pMainFrame,wxID_ANY); wxButton* pStart = new wxButton(pMainFrame,wxID_START,"Start"); pSizer->Add(pPanel,1,wxEXPAND); pSizer->Add(pStart,0,wxEXPAND); pPanel->Bind(wxEVT_PAINT, [pPanel](wxPaintEvent& ev) { RunATM(pPanel); } ); pMainFrame->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent& event){ Start(); }, wxID_START); pMainFrame->SetSizer(pSizer); pMainFrame->SetAutoLayout(true); pMainFrame->Show(); } int main(int argc,char *argv[]) { wxApp::SetInstance(new wxApp); if(wxEntryStart(argc,argv)) { ShowMainWindow(); // Pokrecemo glavnu aplikacionu petlju wxTheApp->OnRun(); wxEntryCleanup(); } return 0; }