#include <functional>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <random>
#include <map>
using namespace std;
class PersonalIdentificationNumber{
public:
static constexpr unsigned LENGTH = 4;
explicit PersonalIdentificationNumber(unsigned number): _number(number){
cut_if_necessary(_number);
}
operator unsigned() const{ return _number; }
string formatted() const{
ostringstream ss;
ss << setw(LENGTH) << setfill('0') << _number;
return ss.str();
}
private:
void cut_if_necessary(unsigned &number) const{
while(number >= 10000)
number /= 10;
}
unsigned _number;
};
using PID = PersonalIdentificationNumber;
bool operator==(const PID &lhs, const PID &rhs){
return (unsigned)lhs == (unsigned)rhs;
}
template<typename T>
class LoginAttemptor{
public:
struct Actions{
function<T()> in;
function<bool(T)> onCheck;
function<void(T)> onSuccess;
function<void(T)> onPartialFailure;
function<void(T)> onTotalFailure;
function<void()> onNoMoreAttemptsLeft;
};
LoginAttemptor(Actions actions, size_t maxFailures)
: _actions(actions), _maxFailures(maxFailures), _failures(0){}
bool canAttempt() const{
return _maxFailures > _failures;
}
bool attempt(){
if(!canAttempt()){
_actions.onNoMoreAttemptsLeft();
return false;
};
T in_result = _actions.in();
if(_actions.onCheck(in_result)){
_actions.onSuccess(in_result);
return true;
}
_failures += 1;
if(canAttempt()) _actions.onPartialFailure(in_result);
else _actions.onTotalFailure(in_result);
}
private:
const Actions _actions;
const size_t _maxFailures;
size_t _failures;
};
int main(){
const size_t maxNumberOfLoginAttempts = 3;
PersonalIdentificationNumber a(1), b(10000);
cout << a.formatted() << " " << b.formatted() << endl;
auto loginAttemptor = LoginAttemptor<PID>({
[]{unsigned in; cin >> in; return PID(in);},
[](PID r){return r == PID(133);},
[](PID r){cout << "Success with " << r.formatted() << "!" << endl;},
[](PID r){cout << "Partial failure with " << r.formatted() << "." << endl;},
[](PID r){cout << "Total failure with " << r.formatted() << "!" << endl;},
[]{cout << "No more attempts left!" << endl;}
}, maxNumberOfLoginAttempts
), copy = loginAttemptor;
for(size_t i = 0; i <= maxNumberOfLoginAttempts; ++i)
loginAttemptor.attempt();
while(!copy.attempt());
return 0;
}