-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdominio.cpp
600 lines (494 loc) · 18.8 KB
/
dominio.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
///
/// \file dominio.cpp
/// \version 1.0
///
// /**********************************************************************************************
// BIBLIOTECAS
// ***********************************************************************************************/
#include <iostream>
#include <string>
#include <exception>
#include <regex>
#include "dominio.h"
#include "testes.h"
#include "func.h"
using namespace std;
// ************************************************************************************************
// * DESENVOLVIMENTO dominio.cpp
// ************************************************************************************************/
///
/// \brief Duração do passeio pode ser de 30, 60, 90, 120 ou 180 minutos.
/// O instrutor pode oferecer seu passeio dentre estas opções de duração.
/// A função abaixo busca validar o valor de entrada.
/// \param valor
///
/// \throw invalid_argument("Duracao invalida.")
///
void Duracao::validar(int valor){
if (valor != 30 && valor != 60 && valor != 90 && valor != 120 && valor != 180)
throw invalid_argument("Duracao invalida.");
}
///
/// \brief Método setValor permite salvar números válidos.
///
/// \param valor
///
void Duracao::setValor(int valor){
Duracao::validar(valor);
this->valor = valor;
}
///
/// \brief Nota pode ser valor de 0 à 5.
///
/// \param valor
///
/// \throw invalid_argument("Nota invalida.")
///
void Nota::validar(int valor){
if (valor != 0 && valor != 1 && valor != 2 && valor != 3 && valor != 4 && valor != 5)
throw invalid_argument("Nota invalida.");
}
///
/// \brief Método setValor permite salvar números válidos.
///
/// \param valor
///
void Nota::setValor(int valor){
Nota::validar(valor);
this->valor = valor;
}
///
/// \brief Há 16 cidades válidas para excursão:
///
/// hong kong, bangkok, macau, singapura, londres, paris, dubai, delhi, istambul,
/// kuala, lumpur, nova iorque, antalya, mumbai, shenzhen, phuket.
///
/// \param nomeCidade
///
/// \throw invalid_argument("Cidade invalida.")
///
void Cidade::validar(string nomeCidade){
// O vetor estatico e suficiente para a aplicacao
string cidadeDisponivel[16] = {"hong kong", "bangkok", "macau", "singapura", "londres", "paris",
"dubai", "delhi", "istambul", "kuala", "lumpur", "nova iorque",
"antalya", "mumbai", "shenzhen", "phuket"};
// Passar a string para minusculo garante que a funcao seja 'case no sensitive'
lowerstr(nomeCidade);
// A criacao de variavel auxiliar objetiva nao alterar o valor original da variavel parametro.
string cidadeNomeAux = nomeCidade;
// Contador de igualdade entre cidade requisitada e cidades disponiveis.
int selecao = 0;
// Mecanismo de comparacao entre parametro e vetor de cidades disponiveis.
for(int i=0; i<16; i++){
if(cidadeNomeAux == cidadeDisponivel[i]){
selecao = selecao+1;
}
}
if (selecao != 1){
throw invalid_argument("Cidade invalida.");
}
}
///
/// \brief Método setCidade permite salvar cidades válidas.
///
/// \param nomeCidade
///
void Cidade::setCidade (string nomeCidade){
validar(nomeCidade);
this->nomeCidade = nomeCidade;
}
///
/// \brief Código deve ser 6 dígitos númericos diferentes de '000000'.
///
/// algoritmo de verificacao: Titulo eleitoral <http://ghiorzi.org/DVnew.htm>
///
/// \param valor
///
/// \throw invalid_argument("Codigo invalido. O codigo deve conter 6 algarismos diferente de 000000.")
///
void Codigo::validar(string valor){
int numerador = stoi(valor); // Conversao de string para int;
int somatorio = 0; // Somatario dos digitos
int resto = 0; // resto da div por 11
int i=0; // Indice Multiplicativo.
regex CODIGO_VALIDO ("[0-9]{6}"); // codigo aceitavel
regex CODIGO_INVALIDO ("[0]{1,6}"); // codigo invalido.
int DV=0; // Digito Verificador
if (regex_match(valor, CODIGO_INVALIDO) || !regex_match(valor, CODIGO_VALIDO))
throw invalid_argument("Codigo invalido. O codigo deve conter 6 algarismos diferente de 000000.");
///
/// Algorítmo de Dígito de verificação (Título Eleitoral)
///
while(numerador>0){ // Neste laco cada algarismo e multiplicado por
resto = (numerador%10)*(9-i); // uma constante diferente, conforme o algoritmo.
somatorio = somatorio+resto;
numerador = numerador/10;
i++;
}
DV = somatorio % 11; //O resto esta em INT
if(DV == 10) // Condicao para %11=10 (div. por 11) = 10
DV=0;
valor = valor+to_string(DV);
}
///
/// \brief Método setValor permite salvar códigos válidos.
///
void Codigo::setValor(string valor){
validar(valor);
this->valor = valor;
}
///
/// Validação da Data em que: dia, m&ês e ano, serão representados por
/// DIA, MES, ANO, respectivamente.
///
/// \param data
///
/// \throw invalid_argument
///
void Data::validar(string data){
std::smatch matches;
string DIA, MES, ANO;
regex DATA_VALIDA ("\\b(\\d{2})[- /\\.]([a-zA-Z]{3})[- /\\.](\\d{4})\\b");
regex JAN ("[jJ][aA][nN]"); //A Codificao dos meses generalizada.
regex FEV ("[fF][eE][vV]"); //A entrada e no-sensitive.
regex MAR ("[mM][aA][rR]");
regex ABR ("[aA][bB][rR]");
regex MAI ("[mM][aA][iI]");
regex JUN ("[jJ][uU][nN]");
regex JUL ("[jJ][uU][lL]");
regex AGO ("[aA][gG][oO]");
regex SET ("[sS][eE][tT]");
regex OUT ("[oO][uU][tT]");
regex NOV ("[nN][oO][vV]");
regex DEZ ("[dD][eE][zZ]");
if(regex_search(data, matches, DATA_VALIDA)){
DIA = matches.str(1); // Aqui sera guardado DIA, MES e ANO
MES = matches.str(2); // o tratamento da data sera facilitado
ANO = matches.str(3);
// Tratamento do ano
int ano = stoi(ANO);
if (ano<2000 || ano>9999){
throw invalid_argument("Entrada invalida. O ano deve ser entre 2000 - 9999.");
}
// Tratamento dos Meses com 30 dias
if (regex_match(MES,ABR) || regex_match(MES,JUN) ||
regex_match(MES,SET) || regex_match(MES,NOV)){
int dia30 = stoi(DIA);
if(dia30<1 || dia30>30)
throw invalid_argument("Entrada invalida. Este mes possui 30 dias.");
}
// Tratamento dos Meses com 31 dias
if (regex_match(MES,JAN) || regex_match(MES,MAR) ||
regex_match(MES,MAI) || regex_match(MES,JUL) ||
regex_match(MES,AGO) || regex_match(MES,OUT) ||
regex_match(MES,DEZ)){
int dia31 = stoi(DIA);
if(dia31<1 || dia31>31)
throw invalid_argument("Entrada invalida. Este mes possui 31 dias.");
}
// Tratamento do mês de Fevereiro.
if (regex_match(MES, FEV)){
int diaMaxFev = stoi(DIA);
if(diaMaxFev>29){
throw invalid_argument("Entrada invalida. Fevereiro nao possui mais de 29 dias");
}else if(diaMaxFev == 29 && !(ano%4 == 0 && (ano%100 != 0 || ano%400 == 0))){
throw invalid_argument("Entrada invalida. Este ano nao e bissexto.");
}
}
}else{
throw invalid_argument("Data inválida, deve ser DIA-MES-ANO, números para DIA e ANO e 3 letras para o MES.");
}
}
///
/// \brief Método setData permite salvar data válida.
///
void Data::setData(string data){
validar(data);
this->data = data;
}
///
/// \brief Descricao contém de 0 à 30 carácteres
/// nao deve haver espaço em branco, nem ponto final em sequência.
///
/// \param descricao
///
/// \throw invalid_argument
///
void Descricao::validar(string descricao){
smatch matches;
regex DESCRICAO_INVALIDA("([ ]{2,})"); //analise para cada caso separadamente.
regex DESCRICAO_INVALIDA2("([.]{2,})");
// Condicao de padrao valido
if(regex_search(descricao,matches,DESCRICAO_INVALIDA) ||
regex_search(descricao,matches,DESCRICAO_INVALIDA2))
throw invalid_argument ("Descricao invalida. use apenas 1 espaco e ponto por vez.");
//Condicao de comprimento de string
if(descricao.length()>30)
throw invalid_argument("Entrada invalida. No max 30 caracteres.");
}
///
/// \brief Método setDescricao permite salvar descrição válida.
///
/// \param descricao
///
void Descricao::setDescricao (string descricao){
validar(descricao);
this->descricao = descricao;
}
///
/// \brief Endereço deve ser de 0 à 20 caracteres
/// e não há nem espaço em branco, nem ponto final em sequência.
///
/// \param descrição
///
/// \throw invalid_argument("Endereco invalido.")
///
void Endereco::validar(string endereco){
smatch matches;
regex ENDERECO_INVALIDO("([ ]{2,})"); //analise para cada caso separadamente.
regex ENDERECO_INVALIDO2("([.]{2,})");
// Condicao de padrao valido.
if(regex_search(endereco,matches,ENDERECO_INVALIDO) ||
regex_search(endereco,matches,ENDERECO_INVALIDO2))
throw invalid_argument ("Endereco invalido. Use apenas 1 espaco e ponto por vez.");
//Condicao de comprimento de string
if(endereco.length()>20)
throw invalid_argument("Endereco invalido. No max 20 caracteres.");
}
///
/// \brief Método setEndereco permite salvar endereço válido.
///
/// \param endereco
///
void Endereco::setEndereco (string endereco){
validar(endereco);
this->endereco = endereco;
}
///
/// \brief Validação do Horário abrange de 00-23 Horas e 00-59 minutos.
///
/// \param horario
///
/// \throw invalid argument("Horario invalido.")
///
void Horario::validar(string horario){
smatch matches;
string HH, MM;
int hora, minuto;
regex HORA_VALIDA("([0-2][0-9])[:]([0-5][0-9])");
// Verificacao de tipo de dado. Sem filtro de hora especifico.
if(regex_search(horario,matches,HORA_VALIDA)){
HH = matches.str(1);
hora = stoi(HH);
MM = matches.str(2);
minuto = stoi(MM);
// Verificacao de horario permitido
if(hora<0 || hora>23 || minuto<0 || minuto>59)
throw invalid_argument("Horario invalido. Formato valido: 00:00 ate 23:59.");
}else{throw invalid_argument("Formato de horario invalido.");}
}
///
/// \brief Método setHorario permite salvar horário válido.
///
/// \param horario
///
void Horario::setHorario (string horario){
validar(horario);
this->horario = horario;
}
///
/// \brief Idiomas disponíveis:
/// ingles, chines mandarim, hindi, espanhol, frances, arabe, bengali, russo, portugues, indonesio.
///
/// \param linguagem
///
void Idioma::validar(string linguagem){
// O vetor de string estatico e sulficiente para a aplicacao, pois os Idiomas nao sao alterados.
string idiomaDisponivel[10] = {"ingles", "chines mandarim", "hindi", "espanhol", "frances", "arabe",
"bengali", "russo", "portugues", "indonesio"};
lowerstr(linguagem); ///< Manipula a string para minúsculo e salva na mesma variável.
string idiomaAux = linguagem;
int selecao = 0; // Contador de igualdade entre idiomas.
// Comparacao de idioma requisitado e idiomas disponiveis
for(int i=0; i<10; i++){
if(idiomaAux == idiomaDisponivel[i]){
selecao = selecao+1;
}
}
if (selecao != 1){
throw invalid_argument("Idioma invalido. Suas opcoes sao: ingles, chines mandarim, hindi, espanhol, frances, arabe, bengali, russo, portugues, indonesio");
}
}
///
/// \brief Método setIdioma permite salvar idioma válido.
///
/// \param linguagem
///
void Idioma::setIdioma (string linguagem){
validar(linguagem);
this->idioma = linguagem;
}
///
/// \brief Título deve contér de 0 à 20 caracteres
///
/// e não há nem espaco em branco, nem ponto final em sequência.
///
/// \param titulo
///
/// \throw invalid_argument("Titulo invalido.")
///
void Titulo::validar(string titulo){
smatch matches;
regex TITULO_INVALIDO("([ ]{2,})|([.]{2,})|([0-9])");
// Condicao invalida
if(regex_search(titulo,matches,TITULO_INVALIDO)){
throw invalid_argument ("Titulo invalido. E permitido apenas letras e use apenas 1 espaco e ponto por vez.");
}
// Condicao de comprimento da string
if(titulo.length()<5 || titulo.length()>20)
throw invalid_argument("Titulo invalido. No min 5 e no max 20 caracteres.");
}
///
/// \brief Método setTitulo permite salvar título válido.
///
/// \param titulo
///
void Titulo::setTitulo (string titulo){
validar(titulo);
this->titulo = titulo;
}
///
/// \brief Validação da senha abrange 6 caracteres.
/// Não é permitido carácter repetido e deve conter, no min: 1 letra "M", 1 letra "m" e 1 núm.
///
/// \param segredo
///
/// \throw invalid_argument("Senha invalida.")
///
void Senha::validar(string segredo){
smatch matches;
int charMin = 0, charMai = 0, charNum = 0;
char caracter;
string caracterStr;
regex CAR_MIN("[a-z]");
regex CAR_MAI("[A-Z]");
regex CAR_NUM("[0-9]");
regex SENHA_INVALIDA("[ ]|[\\.]|[!@#$%&¨&*)\(+=£¢¬§]");
// 1 verificacao de senha: caracteres invalidos e comprimento de senha.
if (segredo.length()<6 || segredo.length()>6 || regex_search(segredo,matches,SENHA_INVALIDA))
throw invalid_argument ("Senha invalida. So sao permitido 6 digitos de aA-zZ 0-9.");
// Tratamento de Senha para verificacoes 2 e 3
for (int i=0; i<(int)segredo.length(); i++){
caracter = segredo[i];
caracterStr = segredo[i];
if(regex_match(caracterStr,CAR_MIN)){
charMin++;
}else{ if(regex_match(caracterStr,CAR_MAI)){
charMai++;
}else{ if(regex_match(caracterStr,CAR_NUM)){
charNum++;
}
}
}
// 2 verificação de senha: Vedada ocorrencia de 'char' repetido em sequencia.
if(i != ((int)segredo.length()-1)){
if(caracter == segredo[i+1])
throw invalid_argument("Senha invalida. Nao e permito caracteres repetidos em sequencia.");
}
}
// 3 verificacao de senha: pelo menos 1 ocorrencia de 'char': minusc., maiusc., numero.
if(charMin == 0 || charMai == 0 || charNum == 0)
throw invalid_argument("Senha invalida. Deve conter pelo menos 1 caracter minusculo, 1 maiusculo e 1 numero");
}
///
/// \brief Método setSenha permite salvar senha válida.
///
/// \param segredo
///
void Senha::setSenha(string segredo){
validar(segredo);
this->senha = segredo;
}
///
/// \brief Validacao da email abrange parte-local@dominio
///
/// \param email
///
/// \throw invalid_argument("Email invalido.")
///
void Email::validar(string email){
smatch matches;
int i = 0;
stringstream full_email(email);
string intermediate;
regex EMAIL_VALIDO("[a-zA-Z0-9!#\\$%&'*\\+\\-\\/=^_`{|}~\\.]{1,64}[@][a-zA-Z0-9\\.\\-]{1,253}");
regex CAR_INVALIDO("[\\[\\];:,<>¨ \"()ç\\ ]");
// 1 verificacao de email: caracteres invalidos, comprimento de email e formato.
if(!regex_search(email,matches,EMAIL_VALIDO))
throw invalid_argument ("Email invalido. Tamanho ou formato invalido.");
// 2 verificacao de email: Ocorrencia de ponto
while(getline(full_email, intermediate, '@')){
if(i == 0 && (intermediate.front() == '.' || intermediate.back() == '.')){
throw invalid_argument ("Email invalido. Parte-local iniciando ou terminado com ponto.");
}
if(i == 1 && intermediate.front() == '.'){
throw invalid_argument ("Email invalido. Parte dominio iniciando com ponto.");
}
i++;
}
// 3 verificacao de email: Pontos duplos
if(email.find("..") != string::npos){
throw invalid_argument ("Email invalido. Pontos multiplos.");
}
// 4 verificacao de email: Char invalido
if(regex_search(email,matches,CAR_INVALIDO)){
throw invalid_argument ("Email invalido. Caractere invalido.");
}
// 5 verificacao de email: @ multiplo
if(count(email.begin(), email.end(), '@') > 1){
throw invalid_argument ("Email invalido. @ multiplos.");
}
}
///
/// \brief Inclusão do Endereço da excursão
///
/// \param email
///
void Email::setEmail(string email){
validar(email);
this->email = email;
}
///
/// \throw Validacao de nome
///
/// \param nome
///
/// \throw invalid_argument("Nome invalido.")
///
void Nome::validar(string nome){
smatch matches;
stringstream ss_nome(nome);
string intermediate;
regex CAR_INVALIDO("[^a-zA-Z \\.]");
regex MINUSCULO_VALIDO_MEIO("[\\. ][a-z]");
regex MINUSCULO_VALIDO_INICIO("^[A-Z]");
regex PONTO_ESPACO_INVALIDO("([\\.][A-Za-z])|([\\.][\\.])|([ ][ ])|([ ][a-z\\.])");
// 1 verificacao de nome: caracteres invalidos, comprimento de nome e formato.
if(nome.length() < 5 || nome.length() > 20 || regex_search(nome,matches,CAR_INVALIDO))
throw invalid_argument ("Nome invalido: Tamanho ou formato invalido.");
// 2 verificacao de nome: Ocorrencia nome iniciando minusculo
if(regex_search(nome,matches,MINUSCULO_VALIDO_MEIO) || !regex_search(nome,matches,MINUSCULO_VALIDO_INICIO))
throw invalid_argument ("Nome invalido: Nome minusculo.");
// 3 verificacao de nome: Ocorrencias com ponto e espaco
if(regex_search(nome,matches,PONTO_ESPACO_INVALIDO))
throw invalid_argument ("Nome invalido: Ponto usado de maneira incorreta.");
}
///
/// \brief Inclusão do Endereço da excursão
///
/// \param nome
///
void Nome::setNome(string nome){
validar(nome);
this->nome = nome;
}