comparison trimal_repo/source/utils.cpp @ 0:b15a3147e604 draft

"planemo upload for repository https://github.com/inab/trimal commit cbe1e8577ecb1a46709034a40dff36052e876e7a-dirty"
author padge
date Fri, 25 Mar 2022 17:10:43 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:b15a3147e604
1 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *****
2 ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *****
3
4 trimAl v1.4: a tool for automated alignment trimming in large-scale
5 phylogenetics analyses.
6
7 readAl v1.4: a tool for automated alignment conversion among different
8 formats.
9
10 2009-2015 Capella-Gutierrez S. and Gabaldon, T.
11 [scapella, tgabaldon]@crg.es
12
13 This file is part of trimAl/readAl.
14
15 trimAl/readAl are free software: you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation, the last available version.
18
19 trimAl/readAl are distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with trimAl/readAl. If not, see <http://www.gnu.org/licenses/>.
26
27 ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *****
28 ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
29
30 #include "utils.h"
31 #include "values.h"
32 #include "defines.h"
33
34 /*++++++++++++++++++++++++++++++++++++++++++++++++
35 | void utils::initVect(int *, int, int) |
36 | This method is used to initializate all |
37 | positions of a vector with a given value. |
38 ++++++++++++++++++++++++++++++++++++++++++++++++*/
39
40 void utils::initlVect(int *vector, int tam, int valor) {
41
42 for(int i = 0; i < tam; i++) vector[i] = valor;
43
44 }
45
46 void utils::initlVect(float *vector, int tam, float valor) {
47
48 for(int i = 0; i < tam; i++) vector[i] = valor;
49
50 }
51
52
53 /*+++++++++++++++++++++++++++++++++++++++++++++
54 | void utils::copyVect(int *, int *, int) |
55 | This method copies integer vector 1 to |
56 | integer vector 2. |
57 +++++++++++++++++++++++++++++++++++++++++++++*/
58
59 void utils::copyVect(int *vect1, int *vect2, int tam) {
60
61 for(int i = 0; i < tam; i++) vect2[i] = vect1[i];
62
63 }
64
65
66 /*+++++++++++++++++++++++++++++++++++++++++++++++
67 | void utils::copyVect(float *, float *, float) |
68 | This method copies float vector 1 to |
69 | float vector 2. |
70 +++++++++++++++++++++++++++++++++++++++++++++++*/
71
72 void utils::copyVect(float *vect1, float *vect2, int tam) {
73
74 for(int i = 0; i < tam; i++) vect2[i] = vect1[i];
75
76 }
77
78
79 /*+++++++++++++++++++++++++++++++++++++++++
80 | int utils::roundToInf(double) |
81 | This method rounds a double number |
82 | to the inferior integer. |
83 +++++++++++++++++++++++++++++++++++++++++*/
84
85 int utils::roundToInf(double number) {
86
87 return ((int) number);
88 }
89
90
91 /*+++++++++++++++++++++++++++++++++++++++++
92 | int utils::roundInt(double) |
93 | This method rounds a double number |
94 | to a integer. |
95 +++++++++++++++++++++++++++++++++++++++++*/
96
97 int utils::roundInt(double number) {
98
99 return ((int) ((double) number + 0.5));
100 }
101
102
103 /*+++++++++++++++++++++++++++++++++++++++++
104 | int utils::roundToSup(double) |
105 | This method rounds a double number |
106 | to the greater integer. |
107 +++++++++++++++++++++++++++++++++++++++++*/
108
109 int utils::roundToSup(double number) {
110
111 return ((int) ((double) number + 1.0));
112 }
113
114
115 /*+++++++++++++++++++++++++++++++++++++++++
116 | int utils::max(int, int) |
117 | This method returns the maximum |
118 | value of the two given arguments. |
119 +++++++++++++++++++++++++++++++++++++++++*/
120
121 int utils::max(int x, int y) {
122
123 if(x > y) return x;
124 else return y;
125 }
126
127 float utils::max(float x, float y) {
128
129 if(x > y) return x;
130 else return y;
131 }
132
133 double utils::max(double x, double y) {
134
135 if(x > y) return x;
136 else return y;
137 }
138
139 int utils::min(int x, int y) {
140
141 if(x < y) return x;
142 else return y;
143 }
144
145 float utils::min(float x, float y) {
146
147 if(x < y) return x;
148 else return y;
149 }
150
151 double utils::min(double x, double y) {
152
153 if(x < y) return x;
154 else return y;
155 }
156
157 /*+++++++++++++++++++++++++++++++++++++++++++
158 | bool utils::isNumber(char *) |
159 | This method checks if the given |
160 | string is a float number. |
161 +++++++++++++++++++++++++++++++++++++++++++*/
162
163 bool utils::isNumber(char *num){
164
165 int tam = strlen(num);
166 int i, flt = 1, expn = 1, sgn = 1;
167
168 for(i = 0; i < tam; i++) {
169 if(num[i] == '.' && flt)
170 flt = 0;
171
172 else if(((num[i] == 'e') ||(num[i] == 'E')) && expn)
173 expn = 0;
174
175 else if(((num[i] == '+') ||(num[i] == '-')) && sgn) {
176 if(!expn) sgn = 0;
177 }
178 else if(num[i] > '9' || num[i] < '0')
179 return false;
180 }
181
182 return true;
183
184 }
185
186
187 /*+++++++++++++++++++++++++++++++++++++++++++
188 | bool utils::compare(char *, char *) |
189 | This method compares the two strings |
190 | given, and returns true if the two |
191 | strings are equal. |
192 +++++++++++++++++++++++++++++++++++++++++++*/
193
194 bool utils::compare(char *a, char *b){
195
196 return(!strcmp(a,b));
197 }
198
199
200 /*++++++++++++++++++++++++++++++++++++++++++
201 | void utils::removeSpaces(char *, char *) |
202 | This method removes spaces in the |
203 | input string and put the result in |
204 | the output string. |
205 ++++++++++++++++++++++++++++++++++++++++++*/
206
207 void utils::removeSpaces(char *in, char *out){
208
209 unsigned int i, j = 0;
210
211 for(i = 0; i < strlen(in); i++){
212
213 if(in[i] != ' ' && in[i] != '\t'){
214 out[j] = in[i];
215 j++;
216 }
217 }
218 out[j] = '\0';
219 }
220
221
222 /*++++++++++++++++++++++++++++++++++++++++++
223 | void utils::quicksort(float *, int, int) |
224 | This method sorts the vector using |
225 | the quicksort method. |
226 ++++++++++++++++++++++++++++++++++++++++++*/
227
228 void utils::quicksort(float *vect, int ini, int fin) {
229
230 float elem_div;
231 int i, j;
232
233 if ((ini >= fin) || (fin < 0))
234 return;
235
236 elem_div = vect[fin];
237 i = ini - 1;
238 j = fin;
239
240 while (1) {
241
242 while (vect[++i] < elem_div)
243 if(i == fin)
244 break;
245
246 while (vect[--j] > elem_div)
247 if(j == 0)
248 break;
249
250 if(i < j)
251 swap(&vect[i], &vect[j]);
252 else
253 break;
254 }
255
256 swap(&vect[i], &vect[fin]);
257
258 quicksort(vect, ini, i - 1);
259 quicksort(vect, i + 1, fin);
260 }
261
262
263 /*++++++++++++++++++++++++++++++++++++++++
264 | void utils::swap(float *, float *) |
265 | This method swaps the values in a |
266 | and b. |
267 ++++++++++++++++++++++++++++++++++++++++*/
268
269 void utils::swap(float *a, float *b){
270
271 float temp;
272
273 temp = *a;
274 *a = *b;
275 *b = temp;
276
277 }
278
279 /*++++++++++++++++++++++++++++++++++++++++++
280 | void utils::quicksort(float *, int, int) |
281 | This method sorts the vector using |
282 | the quicksort method. |
283 ++++++++++++++++++++++++++++++++++++++++++*/
284
285 void utils::quicksort(int *vect, int ini, int fin) {
286
287 int i, j, elem_div;
288
289 if ((ini >= fin) || (fin < 0))
290 return;
291
292 elem_div = vect[fin];
293 i = ini - 1;
294 j = fin;
295
296 while (1) {
297
298 while (vect[++i] < elem_div)
299 if(i == fin)
300 break;
301
302 while (vect[--j] > elem_div)
303 if(j == 0)
304 break;
305
306 if(i < j)
307 swap(&vect[i], &vect[j]);
308 else
309 break;
310 }
311
312 swap(&vect[i], &vect[fin]);
313
314 quicksort(vect, ini, i - 1);
315 quicksort(vect, i + 1, fin);
316 }
317
318
319 /*++++++++++++++++++++++++++++++++++++++++
320 | void utils::swap(float *, float *) |
321 | This method swaps the values in a |
322 | and b. |
323 ++++++++++++++++++++++++++++++++++++++++*/
324
325 void utils::swap(int *a, int *b) {
326
327 int temp;
328
329 temp = *a;
330 *a = *b;
331 *b = temp;
332
333 }
334
335
336 void utils::quicksort(int **vect, int ini, int fin) {
337
338 float elem_div;
339 int i, j;
340
341 /* ***** ***** ***** ***** ***** ***** ***** ***** */
342 if ((ini >= fin) || (fin < 0))
343 return;
344 /* ***** ***** ***** ***** ***** ***** ***** ***** */
345
346 /* ***** ***** ***** ***** ***** ***** ***** ***** */
347 elem_div = vect[fin][0];
348 i = ini - 1;
349 j = fin;
350 /* ***** ***** ***** ***** ***** ***** ***** ***** */
351
352 /* ***** ***** ***** ***** ***** ***** ***** ***** */
353 while (true) {
354 /* ***** ***** ***** ***** ***** ***** ***** ***** */
355 while (vect[++i][0] < elem_div) if(i == fin) break;
356 while (vect[--j][0] > elem_div) if(j == 0) break;
357 /* ***** ***** ***** ***** ***** ***** ***** ***** */
358
359 /* ***** ***** ***** ***** ***** ***** ***** ***** */
360 if(i < j) swap(&vect[i], &vect[j]);
361 else break;
362 /* ***** ***** ***** ***** ***** ***** ***** ***** */
363 }
364 /* ***** ***** ***** ***** ***** ***** ***** ***** */
365
366 /* ***** ***** ***** ***** ***** ***** ***** ***** */
367 swap(&vect[i], &vect[fin]);
368 /* ***** ***** ***** ***** ***** ***** ***** ***** */
369 quicksort(vect, ini, i - 1);
370 quicksort(vect, i + 1, fin);
371 /* ***** ***** ***** ***** ***** ***** ***** ***** */
372 }
373
374 void utils::swap(int **a, int **b){
375
376 int *temp;
377
378 temp = *a;
379 *a = *b;
380 *b = temp;
381 }
382
383 /* *****************************************************************************
384 *
385 * START - Refactored code
386 *
387 * ************************************************************************** */
388
389 bool utils::checkFile(ifstream &file) {
390 /* Check if a given file exists and its size is greater than 0 */
391 long begin, end;
392
393 /* Check whether input file exists or not */
394 if(!file)
395 return false;
396
397 /* Check input file sizes. A valid file should have a size grater than 0 */
398 begin = file.tellg();
399 file.seekg(0, ios::end);
400 end = file.tellg();
401 file.seekg(0, ios::beg);
402 /* Compare difference between file start and end.
403 * Depending on result, return True or False */
404 if(!(end - begin))
405 return false;
406 return true;
407 }
408
409 char* utils::readLine(ifstream &file) {
410 /* Read a new line from current input stream. This function is better than
411 * standard one since cares of operative system compability. It is useful
412 * as well because remove tabs and blank spaces at lines beginning/ending */
413
414 int state;
415 char c = ' ';
416 string nline;
417 static char *line = NULL;
418
419 /* Check it the end of the file has been reached or not */
420 if(file.eof())
421 return NULL;
422
423 /* Store first line found. For -Windows & MacOS compatibility- carriage return
424 * is considered as well as a new line character */
425 for( ; (c != '\n') && ((!file.eof())); file.read(&c, 1))
426 if ((c != '\r'))
427 nline.resize(nline.size() + 1, c);
428
429 /* Remove blank spaces & tabs from the beginning of the line */
430 state = nline.find(" ", 0);
431 while(state != (int) string::npos && state == 0) {
432 nline.erase(state, 1);
433 state = nline.find(" ", state);
434 }
435
436 state = nline.find("\t", 0);
437 while(state != (int) string::npos && state == 0) {
438 nline.erase(state, 1);
439 state = nline.find("\t", state);
440 }
441
442 /* If there is nothing to return, give back a NULL pointer ... */
443 if(nline.size() == 0)
444 return NULL;
445
446 /* Otherwise, initialize the appropiate data structure,
447 * dump the data and return it */
448 line = new char[nline.size() + 1];
449 strcpy(line, nline.c_str());
450 return line;
451 }
452
453 char* utils::trimLine(string nline) {
454 /* This function is used to remove comments inbetween a biological sequence.
455 * Remove all content surrounded by ("") or ([]). It wans as well when a
456 * mismatch for these flags is found */
457
458 int pos, next;
459 static char *line;
460
461 /* Set-up lower and upper limit to look for comments inside of input string */
462 pos = -1;
463
464 /* Identify comments inside of input sequence and remove it */
465 while(true) {
466 pos = nline.find("\"", (pos + 1));
467
468 /* When there is not any more a comment inside of sequence,
469 * go out from this loop */
470 if(pos == (int) string::npos)
471 break;
472
473 /* Look for closing flag */
474 next = nline.rfind("\"", nline.size());
475
476 /* If a pair of comments flags '"' is found, remove everything inbetween */
477 if((int) nline.find("\"", (pos + 1)) == next) {
478 nline.erase(pos, (next - pos + 1));
479 pos = -1;
480 }
481
482 /* If there is only one flag '"' for comments inside of sequence,
483 * user should be warned about that */
484 if (pos == next) {
485 cerr << endl << "ERROR: Possible (\") mismatch for comments" << endl;
486 return NULL;
487 }
488 }
489
490 /* Look for other kind of comments, in this case those with [] */
491 while(true) {
492 pos = -1;
493 next = -1;
494
495 /* Search for last opened bracket. It is supposed to be the first one for
496 * being close */
497 while((pos = nline.find("[", (pos + 1))) != (int) string::npos)
498 next = pos;
499
500 /* If no opening bracket has been found.
501 * Check if there is any closing one */
502 if (next == -1) {
503 /* There are not any bracket in input string */
504 if ((int) nline.find("]", 0) == (int) string::npos)
505 break;
506 /* Otherwise, warn about the error */
507 cerr << endl << "ERROR: Brackets (]) mismatch found" << endl;
508 return NULL;
509 }
510
511 /* Look for closest closing bracket to the opening one found */
512 pos = nline.find("]", (next + 1));
513
514 /* If no closing bracket has been found. Warn about the mismatch */
515 if (pos == (int) string::npos) {
516 cerr << endl << "ERROR: Brackets ([) mismatch found" << endl;
517 return NULL;
518 }
519
520 /* When both brackets have been found, remove comments inbetween them */
521 nline.erase(next, (pos - next + 1));
522 }
523
524 /* Check if after removing all comments from input string there is still part
525 * of sequences or not */
526 if(nline.size() == 0)
527 return NULL;
528
529 /* Initialize and store resulting sequence into an appropiate structure */
530 line = new char[nline.size() + 1];
531 strcpy(line, nline.c_str());
532
533 return line;
534 }
535 /* *****************************************************************************
536 *
537 * END - Refactored code
538 *
539 * ************************************************************************** */
540 string utils::getReverse(string toReverse) {
541
542 string line;
543 int i;
544
545 /* ***** ***** ***** ***** ***** ***** ***** ***** */
546 for(i = toReverse.size() - 1; i >= 0; i--)
547 line += toReverse[i];
548 /* ***** ***** ***** ***** ***** ***** ***** ***** */
549
550 return line;
551 }
552
553 string utils::removeCharacter(char c, string line) {
554
555 int pos;
556
557 /* ***** ***** ***** ***** ***** ***** ***** ***** */
558 pos = line.find(c, 0);
559 while(pos != (int) string::npos) {
560 line.erase(pos, 1);
561 pos = line.find(c, pos);
562 }
563 /* ***** ***** ***** ***** ***** ***** ***** ***** */
564
565 return line;
566 }
567
568 int utils::checkTypeAlignment(int seqNumber, int residNumber, string *sequences) {
569
570 int i, j, k, l, hitDNA, hitRNA, degenerate, gDNA, gRNA, extDNA, extRNA;
571 float ratioDNA, ratioRNA;
572 /* Standard tables */
573 char listRNA[11] = "AGCUNagcun";
574 char listDNA[11] = "AGCTNagctn";
575
576 /* Degenerate Nucleotides codes */
577 char degeneratedCodes[21] = "MmRrWwSsYyKkVvHhDdBb";
578
579 /* For each sequences, this method locks at the 100 letters (excluding gaps).
580 * The method is able to distinguish between pure DNA/RNA nucleotides or those
581 * containing degenerate Nucleotide letters */
582 for(i = 0, gDNA = 0, gRNA = 0, extDNA = 0, extRNA = 0; i < seqNumber; i++) {
583
584 /* Looks at the 100 letters (excluding gaps) while doesn's get the sequence's end */
585 /* When there are less than a 100 characters, break the loop before reaching that limit */
586 residNumber = (int) sequences[i].size();
587 //~ for(j = 0, k = 0, hitDNA = 0, hitRNA = 0, degenerate = 0; j < residNumber && k < 100; j++)
588 for(j = 0, k = 0, hitDNA = 0, hitRNA = 0, degenerate = 0; j < residNumber; j++)
589 if(sequences[i][j] != '-' && sequences[i][j] != '.' && sequences[i][j] != '?') {
590 k++;
591
592 /* Recognizes between DNA and RNA. */
593 for(l = 0; l < (int) strlen(listDNA); l++)
594 if(listDNA[l] == sequences[i][j])
595 hitDNA++;
596
597 for(l = 0; l < (int) strlen(listRNA); l++)
598 if(listRNA[l] == sequences[i][j])
599 hitRNA++;
600
601 for(l = 0; l < (int) strlen(degeneratedCodes); l++)
602 if(degeneratedCodes[l] == sequences[i][j])
603 degenerate++;
604 }
605
606 /* If input sequences have less than 95% of nucleotides, even when residues
607 * are treated with degenerated codes, consider the input file as containing
608 * amino-acidic sequences. */
609 ratioDNA = float(degenerate + hitDNA)/k;
610 ratioRNA = float(degenerate + hitRNA)/k;
611
612 if(ratioDNA < 0.95 && ratioRNA < 0.95)
613 return AAType;
614
615 /* Identify precisely if nucleotides sequences are DNA/RNA strict or
616 * any degenerate code has been used in the sequence */
617 else if(hitRNA > hitDNA && degenerate == 0)
618 gRNA++;
619 else if(hitRNA > hitDNA && degenerate != 0)
620 extRNA++;
621 else if(hitRNA < hitDNA && degenerate == 0)
622 gDNA++;
623 else if(hitRNA < hitDNA && degenerate != 0)
624 extDNA++;
625 }
626 /* Return the datatype with greater values, considering always degenerate
627 * codes */
628 if (extDNA != 0 && extDNA > extRNA)
629 return DNADeg;
630 else if (extRNA != 0 && extDNA < extRNA)
631 return RNADeg;
632 else if(gRNA > gDNA)
633 return RNAType;
634 else
635 return DNAType;
636 }
637
638 int* utils::readNumbers_StartEnd(string line) {
639
640 int comma, nElems = 0;
641 static int *numbers;
642
643 comma = -1;
644 while((comma = line.find(",", comma + 1)) != (int) string::npos)
645 nElems += 2;
646
647 //~ If there is more than two numbers separated by a comma, return NULL
648 if(nElems != 2)
649 return NULL;
650
651 numbers = new int[2];
652 comma = line.find(",", 0);
653 numbers[0] = atoi(line.substr(0, comma).c_str());
654 numbers[1] = atoi(line.substr(comma+1).c_str());
655
656 return numbers;
657 }
658
659
660 int* utils::readNumbers(string line) {
661
662 int i, comma, separ, init, nElems = 0;
663 static int *numbers;
664
665 /* ***** ***** ***** ***** ***** ***** ***** ***** */
666 comma = -1;
667 while((comma = line.find(",", comma + 1)) != (int) string::npos)
668 nElems += 2;
669 nElems += 2;
670 /* ***** ***** ***** ***** ***** ***** ***** ***** */
671
672 /* ***** ***** ***** ***** ***** ***** ***** ***** */
673 numbers = new int[nElems + 1];
674 numbers[0] = nElems;
675 /* ***** ***** ***** ***** ***** ***** ***** ***** */
676
677 /* ***** ***** ***** ***** ***** ***** ***** ***** */
678 init = 0;
679 i = 1;
680 /* ***** ***** ***** ***** ***** ***** ***** ***** */
681
682 do {
683 /* ***** ***** ***** ***** ***** ***** ***** ***** */
684 comma = line.find(",", init);
685 separ = line.find("-", init);
686 /* ***** ***** ***** ***** ***** ***** ***** ***** */
687
688 /* ***** ***** ***** ***** ***** ***** ***** ***** */
689 if(((separ < comma) || (comma == (int) string::npos)) && (separ != (int) string::npos)) {
690 numbers[i++] = atoi(line.substr(init, separ - init).c_str());
691 numbers[i++] = atoi(line.substr(separ+1, comma - separ - 1).c_str());
692 init = comma + 1;
693 }
694 /* ***** ***** ***** ***** ***** ***** ***** ***** */
695
696 /* ***** ***** ***** ***** ***** ***** ***** ***** */
697 else if((separ > comma) || (separ == (int) string::npos)) {
698 numbers[i++] = atoi(line.substr(init, comma - init).c_str());
699 numbers[i++] = atoi(line.substr(init, comma - init).c_str());
700 init = comma + 1;
701 }
702 /* ***** ***** ***** ***** ***** ***** ***** ***** */
703
704 /* ***** ***** ***** ***** ***** ***** ***** ***** */
705 if(numbers[i-2] < 0)
706 return NULL;
707 if(numbers[i-1] < numbers[i-2])
708 return NULL;
709 if(comma == (int) string::npos)
710 break;
711 /* ***** ***** ***** ***** ***** ***** ***** ***** */
712 } while(true);
713
714 /* ***** ***** ***** ***** ***** ***** ***** ***** */
715 return numbers;
716 /* ***** ***** ***** ***** ***** ***** ***** ***** */
717 }
718
719
720 char utils::determineColor(char res, string column) {
721
722 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** */
723 if(toupper(res) == 'G')
724 return 'o';
725 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** */
726 else if(toupper(res) == 'P')
727 return 'y';
728 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** */
729
730 else if(res != '-') {
731 switch(toupper(res)) {
732
733 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
734 /* (W, L, V, I, M, F): {50%, p}{60%, wlvimafcyhp} */
735 case 87: case 76: case 86: case 73: case 77: case 70:
736 if(lookForPattern(column, "p", 0.5)) return 'b';
737 else if(lookForPattern(column, "wlvimafcyhp", 0.6)) return 'b';
738 else return 'w';
739 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
740
741 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
742 /* (A): {50%, p}{60%, wlvimafcyhp}{85% t,s,g} */
743 case 65:
744 if(lookForPattern(column, "p", 0.5)) return 'b';
745 else if(lookForPattern(column, "wlvimafcyhp", 0.6)) return 'b';
746 else if(lookForPattern(column, "t", 0.85)) return 'b';
747 else if(lookForPattern(column, "s", 0.85)) return 'b';
748 else if(lookForPattern(column, "g", 0.85)) return 'b';
749 else return 'w';
750 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
751
752 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
753 /* BLUE: (C): {50%, p}{60%, wlvimafcyhp}{85% s}
754 * PINK: (C): {85%, c}
755 */
756 case 67:
757 if(lookForPattern(column, "p", 0.5)) return 'b';
758 else if(lookForPattern(column, "wlvimafcyhp", 0.6)) return 'b';
759 else if(lookForPattern(column, "s", 0.85)) return 'b';
760 else if(lookForPattern(column, "c", 0.85)) return 'p';
761 else return 'w';
762 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
763
764 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
765 /* (K, R): {60%, kr}{85%, q} */
766 case 75: case 82:
767 if(lookForPattern(column, "kr", 0.6)) return 'r';
768 else if(lookForPattern(column, "q", 0.85)) return 'r';
769 else return 'w';
770 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
771
772 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
773 /* (T): {50%, ts}{60%, wlvimafcyhp } */
774 case 84:
775 if(lookForPattern(column, "ts", 0.5)) return 'g';
776 else if(lookForPattern(column, "wlvimafcyhp", 0.6)) return 'g';
777 else return 'w';
778 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
779
780 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
781 /* (S): {50%, ts}{80%, wlvimafcyhp } */
782 case 83:
783 if(lookForPattern(column, "ts", 0.5)) return 'g';
784 else if(lookForPattern(column, "wlvimafcyhp", 0.8)) return 'g';
785 else return 'w';
786 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
787
788 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
789 /* (N): {50%, n}{85%, d } */
790 case 78:
791 if(lookForPattern(column, "n", 0.5)) return 'g';
792 else if(lookForPattern(column, "d", 0.85)) return 'g';
793 else return 'w';
794 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
795
796 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
797 /* (Q): {50%, qe}{60%, kr} */
798 case 81:
799 if(lookForPattern(column, "qe", 0.5)) return 'g';
800 else if(lookForPattern(column, "kr", 0.6)) return 'g';
801 else return 'w';
802 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
803
804 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
805 /* (D): {50%, de, n} */
806 case 68:
807 if(lookForPattern(column, "de", 0.5)) return 'm';
808 else if(lookForPattern(column, "n", 0.5)) return 'm';
809 else return 'w';
810 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
811
812 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
813 /* (E): {50%, de,qe} */
814 case 69:
815 if(lookForPattern(column, "de", 0.5)) return 'm';
816 else if(lookForPattern(column, "qe", 0.5)) return 'm';
817 else return 'w';
818 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
819
820 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
821 /* (H,Y): {50%, p}{60%, wlvimafcyhp} */
822 case 72: case 89:
823 if(lookForPattern(column, "p", 0.5)) return 'c';
824 else if(lookForPattern(column, "wlvimafcyhp", 0.5)) return 'c';
825 else return 'w';
826 /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */
827 }
828 }
829 return 'w';
830 }
831
832
833 bool utils::lookForPattern(string column, string dataset, float level) {
834
835 float count = 0;
836 int i, j;
837
838 for(i = 0; i < (int) column.size(); i++) {
839 for(j = 0; j < (int) dataset.size(); j++) {
840 if(toupper(column[i]) == toupper(dataset[j])) {
841 count++; break;
842 }
843 }
844 }
845
846 if((count/column.size()) >= level)
847 return true;
848 else return false;
849 }
850