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: