1: 2: /* 3: 4: Copyright 2002 Erik Ljungström (erik.ljungstrom@metalab.unc.edu) 5: & 6: Henrik Caesar (henrik.caesar@hotmail.com) 7: 8: This program is free software; you can redistribute it and/or modify 9: it under the terms of the GNU General Public License as published by 10: the Free Software Foundation; either version 2 of the License, or 11: (at your option) any later version. This program is distributed in the hope that it will be useful, 12: but WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14: GNU General Public License for more details. 15: You should have received a copy of the GNU General Public License 16: along with this program; if not, write to the Free Software 17: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18: 19: */ 20: 21: #include "bmi.h" 22: 23: using namespace std; 24: int 25: main ( int argc, char *argv[] ) 26: { 27: 28: 29: /* -------------------------------- 30: * Check for command line options 31: * and act upon them. 32: * -------------------------------- 33: */ 34: 35: if ( argc != 1 ) 36: if ( strcmp ( argv[1], "--help" ) == 0 ) { 37: cout << "There's no need for help..." << endl; 38: leave ( clean ); 39: } 40: else { 41: cout << "There is no command line arguments to pass to BMI." << endl; 42: leave ( clean ); 43: } 44: 45: /* 46: * ----------------------------------------------------------- 47: * Get some environment variables, and attach BMI extensions 48: * to them. 49: * ----------------------------------------------------------- 50: */ 51: char *path = getenv ( "HOME" ), 52: *logname = getenv ( "LOGNAME" ), *display = getenv("DISPLAY"); //generates seg fault if X is missing :/ 53: 54: 55: string bmiDir = path, disp = display, 56: realpath, 57: namn = logname, 58: firstLength, 59: lengthFile = path, 60: loggie, 61: maxMin = path, 62: sex = path, // And no, is has nothing to do with the Swedish meaning of the word. 63: sexStore; // And nothing's for sale :) 64: 65: if(disp.size() == 0){ 66: cerr << "You must have an Xsession going to use BMI..." << endl; 67: leave(error); 68: } 69: 70: 71: double length, 72: weight, 73: BMI, 74: BMIShort = 0, 75: maxBmi = 0, 76: minBmi = 0; 77: weight = 1; // Just to get rid of a warning at compile time. 78: int turn = 0; 79: 80: if ( path == 0 || logname == 0 ) { //Let's hope this'll never happen.. 81: cout << 82: "You have some environment variables lacking. Try exporting HOME and LOGNAME, and try again." 83: << endl; 84: leave ( error ); 85: } 86: else 87: realpath = path; 88: 89: bmiDir += "/.bmi"; // Useless so far 90: realpath += "/.bmi/results"; 91: lengthFile += "/.bmi/length"; 92: maxMin += "/.bmi/maxmin"; 93: sex +="/.bmi/sex"; 94: 95: ifstream firstt ( maxMin.c_str ( ), ios::binary ); //check whether it's the first time bmi is executed. 96: if ( !firstt ) { 97: cout << 98: "Since this is the first time you run BMI, I'd like to know how tall you are; in the format m.cm: "; 99: cin >> length; 100: /* ------------------------------------------------- 101: * In case someone types his length in centi-metres 102: * we'll run a check, and convert to meters, if 103: * the input is invalid. 104: * ------------------------------------------------- 105: */ 106: if ( length > 3 ) 107: length /= 10; 108: mkdir ( bmiDir.c_str ( ), 0755 ); // Creates ~/.bmi with the correct permissions. 109: ofstream tall ( lengthFile.c_str ( ), ios::app ); 110: tall << length; 111: tall.close ( ); 112: 113: /* --------------------------------- 114: * Finds ouy wether the user is a 115: * male of female (since the scale 116: * looks different for the sexes 117: * --------------------------------- 118: */ 119: string userSex; 120: //bool tempLoop = true; 121: //do{ 122: cout << endl << "Are you a male or female (m/f): " << flush; 123: cin.ignore(10, '\n'); 124: getline(cin,userSex); 125: userSex = in_Str2Low(userSex); 126: if ((userSex != "m") && (userSex != "f")) 127: cerr << "You must give f or m here." << endl; 128: //else 129: // tempLoop = false; 130: //} 131: //while (tempLoop) 132: 133: ofstream outSex(sex.c_str(), ios::binary); 134: outSex << userSex; 135: outSex.close(); 136: 137: /* ------------------------------------------------ 138: * Create minmax file which will keep max BMI and 139: * min BMI. Fill them with max with 0, and min with 140: * 100000 141: * ------------------------------------------------ 142: */ 143: 144: ofstream maxx ( maxMin.c_str ( ), ios::app ); 145: maxx << 0 << endl << 1000; 146: maxx.close ( ); 147: } 148: 149: 150: /* --------------------------------- 151: * Some ncurses initializing stuff 152: * --------------------------------- 153: */ 154: initscr ( ); 155: cbreak ( ); 156: noecho ( ); 157: nonl ( ); 158: intrflush ( stdscr, FALSE ); 159: keypad ( stdscr, TRUE ); 160: clear ( ); 161: 162: 163: /* 164: * ---------------------------------------------------------------- 165: * Read in the users height and sex from the files created above, 166: * as well as the highest and lowest BMI. 167: * ---------------------------------------------------------------- 168: */ 169: ifstream ReadFile ( lengthFile.c_str ( ), ios::binary ); //length 170: getline ( ReadFile, loggie ); 171: istringstream in ( loggie ); 172: in >> length; 173: ReadFile.close ( ); 174: loggie = ""; //"Reset" 175: //highest and lowest. Highest in place[0] and lowest in place[1] 176: ifstream readMaxMin ( maxMin.c_str ( ), ios::binary ); 177: while ( getline ( readMaxMin, loggie ) ) { 178: if ( turn == 0 ) { 179: //place.push_back(atof(loggie.c_str())); // till place[0] 180: maxBmi = atof ( loggie.c_str ( ) ); 181: turn++; 182: } 183: if ( turn == 1 ) 184: //place.push_back(atof(loggie.c_str())); // till place[1] 185: minBmi = atof ( loggie.c_str ( ) ); 186: } 187: readMaxMin.close(); 188: 189: loggie = ""; // "Reset" again 190: ifstream readSex(sex.c_str(), ios::binary); 191: while (getline (readSex, loggie)) 192: sexStore = loggie; 193: readSex.close(); 194: 195: do { 196: switch ( meny ( ) ) { 197: 198: case 1: 199: { 200: bool digits = true; 201: do { 202: digits=true; 203: char *cmd2 = "Xdialog --title \"BMI-1.2.4\" --stdout --inputbox \"How much do you weigh?\" 0 0", buf2[2048] = ""; 204: FILE *ptr2 = popen (cmd2, "r"); 205: fgets ( buf2, BUFSIZ, ptr2 ); 206: cout << "buf2 is " << buf2 << " and len is " << strlen(buf2) << endl; 207: 208: /* ----------------------------------------- 209: * Check for other input than numbers 210: * to prevent BMI to result to 0 by 211: * calculating with 0 (return value) 212: * ----------------------------------------- 213: */ 214: for (unsigned int j=0; j < strlen(buf2)-1 ;j++) 215: if ((!isdigit(buf2[j])) && (buf2[j]!='.')) 216: digits = false; 217: if (digits == true) 218: weight = atof(buf2); 219: 220: pclose(ptr2); 221: } 222: while (digits == false); 223: 224: /* 225: * ------------------------------------- 226: * Length is read previously (Line: 71) 227: * ------------------------------------- 228: */ 229: 230: BMI = weight / pow ( length, 2 ); 231: if ( BMI > maxBmi ) //Bigger than the max read in earlier.. 232: maxBmi = BMI; 233: 234: if ( BMI < minBmi ) //Smaller than the min read in earlier.. 235: minBmi = BMI; 236: 237: remove ( maxMin.c_str ( ) ); // Make place for new (?) values? 238: ofstream toMaxMin ( maxMin.c_str ( ), ios::binary ); 239: toMaxMin << maxBmi << endl << minBmi; //Write new (?) max and min. 240: toMaxMin.close ( ); 241: 242: /* 243: * ---------------------------------------------------------- 244: * Writes output to ~/.bmi/result The output consists of 245: * name (grabbed from environment variable LOGNAME), date and 246: * result. 247: * ---------------------------------------------------------- 248: */ 249: 250: ofstream toRes ( realpath.c_str ( ), ios::app ); 251: time_t timer; 252: struct tm *tblock; 253: timer = time ( NULL ); 254: tblock = localtime ( &timer ); 255: toRes << asctime ( tblock ); 256: toRes << namn << " had the BMI value of " << 257: setprecision ( 4 ) << BMI << endl; 258: toRes.close ( ); 259: 260: ostringstream showRes; 261: showRes << "Xdialog --title \"BMI-1.2.4\" --title \"Your BMI is\" --msgbox " 262: << setprecision ( 4 ) << BMI << " 0 0"; 263: system ( showRes.str ( ).c_str ( ) ); 264: BMIShort = floor(BMI*100.0+.5)/100.0; // Reduces the amount of decimals to 2. 265: if (sexStore == "m"){ // so the for loops don't have to go so high. 266: 267: if (BMI > 45.4) 268: system("Xdialog --title \"BMI-1.2.4\" --msgbox \"Morbid obesity. You will for sure suffer from healt problems at higher age.\" 0 0"); 269: if (BMI < 20.7) 270: system("Xdialog --title \"BMI-1.2.4\" --msgbox \"You are underweight! Concider seeing a dietist! You may have som health issues at greater age.\" 0 0"); 271: /* ---------------------------------- 272: * Break to prevent that two dialogs 273: * are shown upon a result excessing 274: * 30. Since 30 > 25. 275: * ---------------------------------- 276: */ 277: 278: 279: for (double i = 31.1; i < 45.5;i +=0.01) 280: { 281: if (fabs(BMIShort - i) < 1e-3){ 282: system 283: ( "Xdialog --title \"BMI-1.2.4\" --msgbox \"Your fatness is _very_ unhealthy. Concider searching help.\" 0 0" ); 284: } 285: } 286: 287: for (double i = 27.8; i < 31.1;i +=0.01) 288: { 289: if (fabs(BMIShort - i) < 1e-3){ 290: system("Xdialog --title \"BMI-1.2.4\" --msgbox \"Your weight is above what's concider healthy. Concider a diet.\" 0 0"); 291: } 292: } 293: 294: for (double i = 26.4; i < 27.8;i +=0.01) 295: { 296: if (fabs(BMIShort - i) < 1e-3){ 297: system("Xdialog --title \"BMI-1.2.4\" --msgbox \"You are marginally overweight. There is some risk for health problems in the future. \" 0 0"); 298: } 299: } 300: for (double i = 20.7; i < 26.4 ;i +=0.01) 301: { 302: if (fabs(BMIShort - i) < 1e-3){ 303: system("Xdialog --title \"BMI-1.2.4\" --msgbox \"Ideal weight! The health risk is minmal! Keep it up! \" 0 0"); 304: } 305: } 306: 307: } // sexStore == m 308: 309: 310: else if (sexStore == "f"){ 311: for (double i = 32.3 ; i < 44.8 ;i +=0.01) 312: { 313: if (fabs(BMIShort - i) < 1e-3){ 314: system("Xdialog --title \"BMI-1.2.4\" --msgbox \"You are very overweight, do concider seeing a dietist.\" 0 0"); 315: } 316: } 317: 318: for (double i = 27.3; i < 32.2;i +=0.01) 319: { 320: if (fabs(BMIShort - i) < 1e-3){ 321: system("Xdialog --title \"BMI-1.2.4\" --msgbox \"You are overweight, concider going on a diet. Moderate health risk \" 0 0"); 322: } 323: } 324: 325: for (double i = 25.8; i < 27.3 ;i +=0.01) 326: { 327: if (fabs(BMIShort - i) < 1e-3){ 328: system("Xdialog --title \"BMI-1.2.4\" --msgbox \"Marginally overweight. There is some risk for healt problems in the future. \" 0 0"); 329: } 330: } 331: 332: for (double i = 19.1 ; i < 25.8;i +=0.01) 333: { 334: if (fabs(BMIShort - i) < 1e-3){ 335: system("Xdialog --title \"BMI-1.2.4\" --msgbox \"This is your ideal weight. Keep it up! \" 0 0"); 336: } 337: } 338: 339: if (BMI > 44.8) 340: system("Xdialog --title \"BMI-1.2.4\" --msgbox \"Morbid obesity. You will for sure suffer from healt problems at higher age.\" 0 0"); 341: if (BMI < 19.1) 342: system("Xdialog --title \"BMI-1.2.4\" --msgbox \"You are underweight! Concider seeing a dietist! You may have som health issues at greater age.\" 0 0"); 343: } // sexStore == f 344: 345: break; 346: } //end of case 1: 347: 348: case 2: 349: { 350: if (sexStore == "m") 351: system ( "Xdialog --title \"BMI-1.2.4\" --tailbox /usr/share/bmi/bmi_scale.m 0 0" ); 352: else if (sexStore == "f") 353: system ( "Xdialog --title \"BMI-1.2.4\" --tailbox /usr/share/bmi/bmi_scale.f 0 0"); 354: break; 355: 356: } //end of case 2 357: 358: case 3: 359: { 360: 361: ostringstream lengthStream; 362: /* 363: * ------------------------------------------------- 364: * Here's _some_ bash scripting. The length is not 365: * put in the ~/.bmi/length by a normal ifstream 366: * but directly from the output from the dialog. 367: * Not that good, if the box is canceled though :/ 368: * ------------------------------------------------- 369: */ 370: lengthStream << 371: "Xdialog --title \"BMI-1.2.4\" --stdout --inputbox \"How tall are you now?\" 0 0 m.cm > " 372: << lengthFile; 373: system ( lengthStream.str ( ).c_str ( ) ); 374: 375: /* 376: * ------------------------------------------------- 377: * In order to prevent an eventual new calculation 378: * to go wrong, let's get the new value of length 379: * into use... 380: * ------------------------------------------------- 381: */ 382: std::string loggie2; 383: ifstream ReadFile2 ( lengthFile.c_str ( ), ios::binary ); 384: getline ( ReadFile2, loggie2 ); 385: istringstream in2 ( loggie2 ); 386: in2 >> length; 387: 388: break; 389: } // end of case 3 390: 391: case 4: 392: { 393: FILE *tf = fopen ( realpath.c_str ( ), "r" ); 394: if ( !tf ) { 395: 396: system 397: ( "Xdialog --title \"BMI-1.2.4\" --msgbox \"The file containing this information does not exist. Creating one...\" 0 0" ); 398: ofstream result ( realpath.c_str ( ), ios::app ); 399: result << ""; 400: result.close ( ); 401: } 402: else { 403: /* 404: * --------------------------------------------------------------------- 405: * Kind of relatively demanding code. Ugly? Yes. Works? Hell yeah! 406: * Fixed from previous version is dialog --textbox, which allows the 407: * user to see all the results, even though the number of posts exceeds 408: * the amount of rows in the terminal. 409: * --------------------------------------------------------------------- 410: */ 411: ostringstream uglyOne; 412: uglyOne << "Xdialog --title \"BMI-1.2.4\" --textbox " << realpath << " 0 0"; 413: system ( uglyOne.str ( ).c_str ( ) ); 414: } 415: break; 416: 417: } //end of case 4 418: 419: case 5: 420: { 421: remove ( maxMin.c_str()); 422: remove ( realpath.c_str ( ) ); 423: break; 424: } 425: 426: case 6: 427: { 428: ostringstream getMinMax; 429: getMinMax << "Xdialog --title \"BMI-1.2.4\" --msgbox \"Max bmi is: " << 430: maxBmi << endl << "Min bmi is: " << minBmi << "\" 0 0" ; 431: system(getMinMax.str().c_str()); 432: break; 433: } 434: 435: case 7: 436: { 437: ostringstream printOut, 438: dispPrint; 439: printOut << "cat " << realpath << " > /dev/lp0"; 440: system ( printOut.str().c_str()); 441: dispPrint << 442: "Xdialog --title \"BMI-1.2.4\" --sleep 2 --infobox \"Printing from \"" 443: << realpath << " 3 45"; 444: system ( dispPrint.str ( ).c_str ( ) ); 445: break; 446: } 447: 448: case 8: 449: { 450: double shouldWeight = 22.5 * pow ( length, 2 ); 451: ostringstream showShould; 452: showShould << 453: "Xdialog --title \"BMI-1.2.4\" --msgbox \"For your length, you should weigh \"" 454: << shouldWeight << " 0 0"; 455: system ( showShould.str ( ).c_str ( ) ); 456: break; 457: } 458: case 9: 459: { 460: leave ( clean ); 461: break; 462: