shoorick: (Default)
[personal profile] shoorick
А всей проги-то было — всего ничего
/*
 BioRhythm

 рассчёт биоритмов человека
 каждый из ритмов представляется синусоидой
 цикл каждой задан константой.
 Внешние данные - дата рождения, ФИО, интересующий период
 дата рождения и месяц прогноза проверяются на правильность
 и при необходимости корректируются
 */

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <math.h>
#include <dos.h>
#include <graphics.h>

#define VERSION "0.4.20030108"

/* Продолжительность циклов */
#define CICLE_PHYS   23     /* физический */
#define CICLE_EMOT   28     /* эмоциональный */
#define CICLE_INTL   33     /* интеллектуальный */

/* Цвета */
#define COLOR_BG     BLACK      /* фон */
#define COLOR_AXIS   LIGHTGRAY  /* ось */
#define COLOR_PHYS   YELLOW     /* циклы */
#define COLOR_EMOT   LIGHTGREEN
#define COLOR_INTL   LIGHTBLUE
#define COLOR_WHO    WHITE      /* для кого */
#define COLOR_ALARM  LIGHTRED   /* критические дни */
/* Шрифт */
#define FONT         DEFAULT_FONT
#define AXIS_RMARGIN 10         /* Правое поле - чтоб число 30 влезло */
#define LEGEND       100        /* Верхнее */

/* Глобальные переменные */
int month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    maxx, maxy;  /* Вспомогательные переменные */

/* Прототипы функций */
int isleap(int);
int dayinyear(int, int, int);
void date_input(struct date*);
long daysbetween(int, int, int, int, int, int);
int isOK(char*);
int ny(float);
char* getst(int);

/*********************************/
void main()
{
 char   *name;                  /* Персональные данные */
 struct date   date_birth;
 int    res_year, res_month,    /* Интересующая дата */
        mdays,                  /* количество дней в месяце */
        critical[33],           /* критические дни */
        period[3] = {CICLE_PHYS, CICLE_EMOT, CICLE_INTL},
         color[3] = {COLOR_PHYS, COLOR_EMOT, COLOR_INTL};
 char*  cyname[3] = {"физический", "эмоциональный", "интеллектуальный"};
        /* Зачем? А чтоб
        1) все константы висели в начале программы и ясно назывались
        2) можно было использовать циклы */
 long   age;      /* Возраст на начало периода */
 char   ch, *st, stb[255];  /* Вспомогательные переменные */
 int    i, j, day, gd = DETECT, gm, stry;
 float  cycle[3][33];           /* Массив значений графиков */

/* Крутимся в цикле, пока пользователю не надоест */
 do
 {
  /* Ввод данных */
  textattr(0x1F); clrscr();
  cprintf("\n\n\r Рассчёт биоритмов\n\r Введи необходимые данные\n\n\r");
  textattr(0x1B); cprintf("     Фамилия, имя, отчество ");
  textattr(0x4E); cprintf("                                ");
  gotoxy(30, wherey() );
  strcpy(name, getst(30)); /* без strcpy строка name портится сразу же */

  textattr(0x1B); cprintf("\n\r              Дата рождения ");

  textattr(0x1B); gotoxy(50, wherey());
  cprintf("Введи день (1..31)");

  gotoxy(29, wherey() );
  textattr(0x4E); cprintf("    ");
  gotoxy(30, wherey() );
  st = getst(2);
  date_birth.da_day = atoi(st);

  textattr(0x1B); gotoxy(50, wherey());
  cprintf("Введи месяц (1..12)");

  gotoxy(32, wherey());
  textattr(0x4E); cprintf(".   ");
  gotoxy(33, wherey() );
  st = getst(2);
  date_birth.da_mon = atoi(st);

  textattr(0x1B); gotoxy(50, wherey());
  cprintf("Введи год (4 цифры)");

  gotoxy(35, wherey());
  textattr(0x4E); cprintf(".     ");
  gotoxy(36, wherey() );
  st = getst(4);
  date_birth.da_year = atoi(st);

  /* Проверка правильности даты и коррекция в случае необходимости */
  date_birth.da_mon = (date_birth.da_mon < 1) ? 1 : (date_birth.da_mon > 12) ? 12 : date_birth.da_mon;
  date_birth.da_day = (date_birth.da_day < 1) ? 1 : (date_birth.da_day > month[date_birth.da_mon-1]+isleap(date_birth.da_year)) ? month[date_birth.da_mon-1]+isleap(date_birth.da_year) : date_birth.da_day;

  textattr(0x1B); gotoxy(50, wherey());
  cprintf("                      \r\n");

  textattr(0x1B); cprintf("               Год прогноза ");
  textattr(0x4E); cprintf("      ");
  gotoxy(30, wherey() );
  st = getst(4);
  res_year = atoi(st);

  textattr(0x1B); cprintf("\r\n              Месяц (1..12) ");
  textattr(0x4E); cprintf("    ");
  gotoxy(30, wherey() );
  st = getst(2);
  res_month = atoi(st);
  /* Проверка и коррекция */
  res_month = (res_month < 1) ? 1 : (res_month > 12) ? 12 : res_month;



  textattr(0x1B);
  age = daysbetween(date_birth.da_year, date_birth.da_mon, date_birth.da_day, res_year, res_month, 1);
  if ((age < -30) || (date_birth.da_year > res_year))
  {
   textattr(0x9E);
   cprintf("\r\n\n Ошибка!");
   textattr(0x1C);
   cprintf("\r\n Прогнозируемый период находится до даты рождения\r\n\n");
   textattr(0x1B);
  }
  else
  {
   cprintf("\r\n\n %s (род. %d.%02d.%04d)", name, date_birth.da_day, date_birth.da_mon, date_birth.da_year);
   cprintf("\r\n Возраст на 1.%02d.%04d - %ld дней", res_month, res_year, age);

   mdays = month[res_month-1];
   for  (j=0; j<=mdays; j++)             /* i - цикл, j - день */
   {
    critical[j] = 0;                     /* Считаем критические дни */
    for (i=0; i<3; i++)
    {
     day = (age+j) % period[i];        /* Дней от начала периода */
     if ((day == 0) ||
         (day == floor((float) period[i]/2)) ||
         (day == ceil((float) period[i]/2)))
     /* Проверяем оба перехода через 0 */
      critical[j]++;
     cycle[i][j] = sin((float) day / period[i]*2*M_PI);
    }
   }

   textcolor(0x1F);
   cprintf("\r\n Критические дни: ");
   for  (j=1; j<=mdays; j++)
    if (critical[j] > 1)
     cprintf("%d, ", j);

   /* Графика */
   textcolor(0x1B);
   cprintf("\r\n Нарисовать график? (Y/n) ");
   st = getst(1);
   if (isOK(st))
   {
    initgraph(&gd, &gm, "");     /* Инициализируем графику*/
    setbkcolor(COLOR_BG);
    cleardevice();
    maxx = getmaxx();            /* и определяем размер экрана */
    maxy = getmaxy();

    setcolor(COLOR_AXIS);         /* рисуем оси */
    line(0, LEGEND, 0, maxy);
    line(0, (maxy+LEGEND)/2, maxx, (maxy+LEGEND)/2);

    settextstyle(FONT, HORIZ_DIR, 1);

    for  (i=1; i <= mdays; i++)
    {
     for (j=0; j < 3; j++)
     {
      setcolor(color[j]);         /* рисуем синусы */
      line((i-1)*(maxx-AXIS_RMARGIN)/mdays, ny(cycle[j][i-1]),
               i*(maxx-AXIS_RMARGIN)/mdays, ny(cycle[j][i]));
     }
     setcolor(COLOR_AXIS);
     if (critical[i] > 1)
      setcolor(COLOR_ALARM);
     line(i*(maxx-AXIS_RMARGIN)/mdays, maxy/2+40, i*(maxx-AXIS_RMARGIN)/mdays, maxy/2+60);

     if ((i%5 == 0) || (critical[i] > 1))
     {
      itoa(i, st, 10);
      outtextxy(i*(maxx-AXIS_RMARGIN)/mdays-textwidth(st)/2, maxy/2+65, st);
     }
    } /* for */

    /* Текст */
    settextstyle(FONT, HORIZ_DIR, 2);
    stry = textheight("Hj")+1;
    outtextxy(0, 0, "Биоритмы");
    strcpy(stb, "Нажми [ENTER]");
    outtextxy(maxx - textwidth(stb), maxy-stry, stb);

    for (j=0; j < 3; j++)
    {
     setcolor(color[j]);         /* рисуем легенду */
     outtextxy(0, stry*(j+1)+10, cyname[j]);
    }

    settextstyle(FONT, HORIZ_DIR, 1);
    setcolor(COLOR_WHO);
    sprintf(stb, "%s (род. %d.%02d.%04d). Прогноз на %02d.%04d", name, date_birth.da_day, date_birth.da_mon, date_birth.da_year, res_month, res_year);
    outtextxy(0, stry, stb);

    getst(1);
    closegraph();
    textattr(0x1B); clrscr();
   } /* Графика */
  }  /* if age */
  cprintf("\r\n\n Повторить рассчёт с другими данными? (Y/n) ");
  st = getst(1);
 } while (isOK(st));

 textattr(0x07);
 clrscr();
 printf("BioRhythm %s\n", VERSION);
} /* main */

/********* функции ********/

/* Год високосный? */
int isleap(int num)
{
 return !(num % 4 || (!(num % 100) && (num % 400)));
}

/* Номер дня в году */
int dayinyear(int y, int m, int d)
{
 int    ret = 0, /* Возвращаемое значение */
        i;
 for(i=1; i<m; i++)     /* Считаем дни */
  ret += month[i-1];    /* Массив месяцев начинается с 0 */
 ret  += d;             /* Получили номер дня без поправки на високосность */

 if (isleap(y) && (m > 2)) /* Если год високосный и месяц - март и т.д. */
  ret++;

 return ret;
}

/* Вычисляет разницу между датами в днях */
long daysbetween(int y1, int m1, int d1, int y2, int m2, int d2)
{
 long    ret = 0; /* Возвращаемое значение */
 int     i;

 for(i=y1; i<y2; i++)     /* Считаем годы */
  ret += 365+isleap(i);   /* в цикле прибавляем дни */

 ret += dayinyear(y2, m2, d2) - dayinyear(y1, m1, d1);

 return ret;
}

/* Возвращает флаг положительного ответа юзера */
int isOK(char *st)
{
 return !(strcmp(st, "")  && /* По умолчанию - ENTER = Да */
          strcmp(st, "Y") && strcmp(st, "y") &&
          strcmp(st, "Д") && strcmp(st, "д"));
}

/* Преобразует координаты [-1..1] в экранные [LEGEND..maxy]*/
int ny(float f)
{
 return LEGEND+(maxy-LEGEND)*(1-f)/2;
}

/* Читает строку длиной не более len символов */
char* getst(int len)
{
 char buf[256];
 buf[0] = len+1;
 return cgets(buf);
}

/*************** The END **************/

Profile

shoorick: (Default)
shoorick

December 2016

S M T W T F S
    1 23
45678910
11121314151617
18 19 2021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Mar. 21st, 2026 04:29 am
Powered by Dreamwidth Studios