#include <iostream>
#include <exception>
#include <string>
#include <ctime>
#include <sstream>
#include <system_error>
#include <set>
#include <map>
using namespace std;
class Date {
public:
Date(){}
Date(long int y, int m, int d){
string string_y = to_string(y);
string string_m = to_string(m);
string string_d = to_string(d);
year = y;
month = m;
day = d;
string zero_y="";
if(string_y.size()>=4){
} else if(string_y.size()<4 && year>0){
string zeros_y((4-string_y.size()), '0');
zero_y=zeros_y;
}
string zeros_m((2-string_m.size()), '0');
string zeros_d((2-string_d.size()), '0');
data = zero_y + string_y + "-" + zeros_m + string_m + "-" + zeros_d + string_d;
}
int GetYear() const{
return year;
}
int GetMonth() const{
return month;
}
int GetDay() const{
return day;
}
string GetDate() const{
return data;
}
private:
long int year;
int month;
int day;
string data;
};
bool operator<(const Date& lhs, const Date& rhs){
if(lhs.GetYear() < rhs.GetYear()){
return true;
} else if(lhs.GetYear()==rhs.GetYear() && lhs.GetMonth() < rhs.GetMonth()){
return true;
} else if(lhs.GetYear()==rhs.GetYear() && lhs.GetMonth() == rhs.GetMonth() && lhs.GetDay()<rhs.GetDay()){
return true;
} else return false;
}
class Database {
public:
Database(){
basa;
}
void AddEvent(const Date& date, const string& event){
basa[date].insert(event);
}
bool DeleteEvent(const Date& date, const string& event){
set <string>::iterator it;
if(basa.count(date)>0){
it = basa.at(date).find(event);
if(basa.at(date).empty() || it==basa.at(date).end()){
return false;
} else {
basa.at(date).erase(basa.at(date).find(event));
if(basa.at(date).empty()) basa.erase(date);
return true;
}
} else return false;
}
int DeleteDate(const Date& date){
int N;
if(basa.count(date)>0){
N = basa.at(date).size();
basa.erase(date);
} else N=0;
return N;
}
void Find(const Date& date) {
if(basa.count(date)>0){
for(const auto& item: basa.at(date)){
cout<<item<<endl;
}
}
}
void Print() const{
Date dt;
int negat_num=0;
for(const auto& it:basa){
if(it.first.GetYear()<0){
negat_num++;
}
}
if(basa.begin()->first.GetYear()<0){ //если первый год меньше 0
for(const auto& it : basa){
if(it.first.GetYear()<0){
cout<<"";
}
else if(it.first.GetYear()>=0){
string datik = it.first.GetDate();
for(const auto& item: it.second){
cout<<datik<<" "<<item<<endl;
}
}
}
}
else{ //Если первый год больше 0
for(const auto& it: basa){
for(const auto& item : it.second){
string datik = it.first.GetDate();
cout<<datik<<" "<<item<<endl;
}
}
}
}
void Clear() {
basa.clear();
}
private:
map <Date, set <string> > basa;
};
ostream& operator<<(ostream& stream, const Date& d){
stream<<d.GetDate();
return stream;
}
istream& operator>>(istream& ss, Date& d){
long int year;
int month, day;
char def1, def2;
string wrongdate;
ss>>wrongdate;
stringstream stream(wrongdate);
int indicator=0;
if(!(stream.rdbuf()->in_avail()==0)){
stream>>year;
stream>>def1;
if(def1!='-'){
indicator=2;
stringstream wformat;
wformat<<"Wrong date format: "<<wrongdate<<endl;
throw runtime_error(wformat.str());
}
else if(def1=='-'){
stream>>month;
if(month==0 && to_string(month)!="0"){
indicator=2;
stringstream wformat;
wformat<<"Wrong date format: "<<wrongdate<<endl;
throw runtime_error(wformat.str());
} else {
stream>>def2;
if(def2!='-'){
indicator=2;
stringstream wformat;
wformat<<"Wrong date format: "<<wrongdate<<endl;
throw runtime_error(wformat.str());
} else if(def2=='-'){
stream>>day;
if(day==0 && to_string(day)!="0"){
indicator=2;
stringstream wformat;
wformat<<"Wrong date format: "<<wrongdate<<endl;
throw runtime_error(wformat.str());
} if(!stream.eof()){
indicator=2;
stringstream wformat;
wformat<<"Wrong date format: "<<wrongdate<<endl;
throw runtime_error(wformat.str());
}
}}} indicator=1; } else {}
if(indicator==1){
if(month>12 || month<1){
stringstream ss;
ss<<"Month value is invalid: "<<to_string(month)<<endl;
throw runtime_error(ss.str());
} else if(day>31 || day<1){
stringstream ss;
ss<<"Day value is invalid: "<<to_string(day)<<endl;
throw runtime_error(ss.str());
} else d = {year, month, day};
} else if(indicator==2){}
if(indicator==1 || indicator==2) return stream;
}
int main() {
Database db;
string event;
map <string, int> commands = {{"Add", 1}, {"Del", 2}, {"Find", 3}, {"Print", 4}};
string command;
string dothis;
Date dt;
db.Clear();
while (getline(cin, command)) {
stringstream ss(command);
if(command!=""){
ss>>dothis;
ss.ignore(1);
switch(commands[dothis]) {
case 1:
try{
ss>>dt;
ss.ignore(1);
ss>>event;
db.AddEvent(dt, event);
} catch (exception& ex){
cout<<ex.what();
}
break;
case 2:
if(!(ss.rdbuf()->in_avail())==0){
try{
ss>>dt;
ss.ignore(1);
if(ss.eof()){
int N=db.DeleteDate(dt);
cout<<"Deleted "<<N<<" events"<<endl;
} else {
ss>>event;
if(db.DeleteEvent(dt, event)==true){
cout<<"Deleted successfully"<<endl;
}
else cout<<"Event not found"<<endl;
}
} catch (exception& ex){
cout<<ex.what();
}} else cout<<"Deleted 0 events"<<endl;
break;
case 3:
try{
ss>>dt;
db.Find(dt);
} catch (exception& ex){
cout<<ex.what();
}
break;
case 4:
db.Print();
break;
default :
{
if(dothis!=""){
cout << "Unknown command: "<<dothis<<endl;
} else {
break;
};
}
}
}
}
return 0;
}