????

Your IP : 18.221.76.65


Current Path : /root/mod_performance-master/
Upload File :
Current File : //root/mod_performance-master/chart.c

/*
 * Copyright 2012 Alexey Berezhok (alexey_com@ukr.net, bayrepo.info@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * chart.c
 *
 *  Created on: Aug 6, 2011
 *  Author: SKOREE
 *  E-mail: alexey_com@ukr.net
 *  Site: lexvit.dn.ua
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <apr_general.h>
#include <apr_pools.h>
#include <apr_tables.h>
#include <apr_strings.h>

#include <gd.h>
#include <gdfonts.h>

#include "chart.h"

chart_color preColor[7] =
  {
    { 42, 180, 0, 68, 138, 1 },
    { 255, 124, 94, 188, 67, 39 },
    { 231, 207, 0, 155, 139, 0 },
    { 61, 157, 255, 22, 111, 202 },
    { 217, 0, 0, 144, 0, 0 },
    { 255, 201, 107, 242, 154, 0 },
    { 104, 232, 255, 29, 188, 218 } };

//---------------------Debug-----------------------------------------------
void
chart_print_data(apr_array_header_t *data ,char *name)
{
  long i;
  FILE *fp;
  fp = fopen(name, "w");
  if(fp!=NULL){
    for (i = 0; i < data->nelts; i++)
    {
      chart_data_percent *s = ((chart_data_percent **) data->elts)[i];
      fprintf(fp,"%ld) date %d, value %f\n", i, s->date, s->value);
    }
    fprintf(fp, "----------------------\n");
    fclose(fp);
  }
}

void
chart_print_data_pie(apr_array_header_t *data)
{
  long i;
  for (i = 0; i < data->nelts; i++)
    {
      chart_data_pie *s = ((chart_data_pie **) data->elts)[i];
      printf("%ld) name %s, value %f\n", i, s->name, s->value);
    }
  printf("----------------------\n");
}

void
chart_write_to_file(gdImagePtr im, char *file_name)
{
  FILE *fp;
  fp = fopen(file_name, "w");
  if (fp)
    {
      gdImageGif(im, fp);
      fclose(fp);
    }
}

void
printresult(double *a, int K)
{
  //print polynom parameters


  int i = 0;
  printf("\n");
  for (i = 0; i < K + 1; i++)
    {
      printf("a[%d] = %g\n", i, a[i]);
    }
}


//---------------------Approximation---------------------------------------

int
count_num_lines(apr_array_header_t *data)
{
  return data->nelts;
}

void
allocmatrix(apr_pool_t *p, double **a, double **b, double **x, double **y,
    double ***sums, int K, int N)
{
  //allocate memory for matrixes


  int i, j, k;
  *a = apr_palloc(p, sizeof(double) * (K + 1));
  *b = apr_palloc(p, sizeof(double) * (K + 1));
  *x = apr_palloc(p, sizeof(double) * N);
  *y = apr_palloc(p, sizeof(double) * N);
  *sums = apr_palloc(p, sizeof(double*) * (K + 1));

  for (i = 0; i < (K + 1); i++)
    {
      (*sums)[i] = apr_palloc(p, sizeof(double) * (K + 1));
    }
  for (i = 0; i < (K + 1); i++)
    {
      (*a)[i] = 0;
      (*b)[i] = 0;
      for (j = 0; j < (K + 1); j++)
        {
          (*sums)[i][j] = 0;
        }
    }
  for (k = 0; k < N; k++)
    {
      (*x)[k] = 0;
      (*y)[k] = 0;
    }

}

void
readmatrix(apr_array_header_t *data, double **a, double **b, double **x,
    double **y, double ***sums, int K, int N)
{
  int i = 0, j = 0, k = 0;
  //read x, y matrixes from input file
  for (k = 0; k < data->nelts; k++)
    {
      chart_data_percent *s = ((chart_data_percent **) data->elts)[k];
      chart_data_percent *s_0 = ((chart_data_percent **) data->elts)[0];
      (*x)[k] = (double) (s->date - s_0->date);
      (*y)[k] = s->value;
    }
  //init square sums matrix
  for (i = 0; i < (K + 1); i++)
    {
      for (j = 0; j < (K + 1); j++)
        {
          (*sums)[i][j] = 0;
          for (k = 0; k < N; k++)
            {
              (*sums)[i][j] += pow((*x)[k], i + j);
            }
        }

    }
  //init free coefficients column
  for (i = 0; i < K + 1; i++)
    {
      for (k = 0; k < N; k++)
        {
          (*b)[i] += pow((*x)[k], i) * (*y)[k];
        }
    }
}

void
diagonal(double **a, double **b, double **x, double **y, double ***sums, int K,
    int N)
{
  int i, j, k;
  double temp = 0;
  for (i = 0; i < (K + 1); i++)
    {

      if ((*sums)[i][i] == 0)
        {
          for (j = 0; j < (K + 1); j++)
            {
              if (j == i)
                continue;
              if ((*sums)[j][i] != 0 && (*sums)[i][j] != 0)
                {
                  for (k = 0; k < (K + 1); k++)
                    {
                      temp = (*sums)[j][k];
                      (*sums)[j][k] = (*sums)[i][k];

                      (*sums)[i][k] = temp;
                    }
                  temp = (*b)[j];
                  (*b)[j] = (*b)[i];
                  (*b)[i] = temp;
                  break;
                }
            }
        }
    }
}

int
result_approx(double **a, double **b, double **x, double **y, double ***sums,
    int K, int N)
{
  //process rows
  int i, j, k;
  for (k = 0; k < (K + 1); k++)
    {
      for (i = k + 1; i < (K + 1); i++)
        {
          if ((*sums)[k][k] == 0)
            {
              return -1;
            }
          double M = (*sums)[i][k] / (*sums)[k][k];

          for (j = k; j < K + 1; j++)
            {
              (*sums)[i][j] -= M * (*sums)[k][j];
            }
          (*b)[i] -= M * (*b)[k];
        }
    }
  for (i = (K + 1) - 1; i >= 0; i--)
    {
      double s = 0;
      for (j = i; j < K + 1; j++)
        {

          s = s + (*sums)[i][j] * (*a)[j];
        }
      (*a)[i] = ((*b)[i] - s) / (*sums)[i][i];
    }

  return 0;
}

//-------------------------------------------------------------------------

#define chart_get_color_at(im, x, y) ((im)->trueColor ? gdImageGetTrueColorPixel(im, x, y) : \
    gdImageGetPixel(im ,x, y))
#define min(x, y) (x>y)?y:x
#define max(x, y) (x>y)?x:y
#define chart_color_for_index(v, im, c) v[0]=gdImageRed(im, c); \
   v[1]=gdImageGreen(im, c); \
   v[2]=gdImageBlue(im, c)

void
imagesmoothline(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
{
  int colors[3], tempcolors[3];
  chart_color_for_index(colors, im, color);
  if (x1 == x2)
    {
      gdImageLine(im, x1, y1, x2, y2, color);
    }
  else
    {
      double m = (double) (y2 - y1) / (double) (x2 - x1);
      double b = (double) y1 - m * (double) x1;
      if (abs(m) <= 1)
        {
          int x = min ( x1 , x2 );
          int endx = max ( x1 , x2 );
          while (x <= endx)
            {
              double ya, yb, y = m * (double) x + b;
              if (y == floor(y))
                {
                  ya = 1;
                }
              else
                {
                  ya = y - floor(y);
                }
              yb = ceil(y) - y;
              chart_color_for_index(tempcolors, im, chart_get_color_at(im, x , (int)floor ( y )));
              tempcolors[0] = (int) (tempcolors[0] * ya + colors[0] * yb);
              tempcolors[1] = (int) (tempcolors[1] * ya + colors[1] * yb);
              tempcolors[2] = (int) (tempcolors[2] * ya + colors[2] * yb);
              if (gdImageColorExact(im, tempcolors[0], tempcolors[1],
                  tempcolors[2]))
                {
                  gdImageColorAllocate(im, tempcolors[0], tempcolors[1],
                      tempcolors[2]);
                }
              gdImageSetPixel(im, x, (int) floor(y), gdImageColorExact(im,
                  tempcolors[0], tempcolors[1], tempcolors[2]));
              chart_color_for_index(tempcolors, im, chart_get_color_at(im, x , (int)ceil ( y )));
              tempcolors[0] = (int) (tempcolors[0] * yb + colors[0] * ya);
              tempcolors[1] = (int) (tempcolors[1] * yb + colors[1] * ya);
              tempcolors[2] = (int) (tempcolors[2] * yb + colors[2] * ya);
              if (gdImageColorExact(im, tempcolors[0], tempcolors[1],
                  tempcolors[2]))
                {
                  gdImageColorAllocate(im, tempcolors[0], tempcolors[1],
                      tempcolors[2]);
                }
              gdImageSetPixel(im, x, (int) ceil(y), gdImageColorExact(im,
                  tempcolors[0], tempcolors[1], tempcolors[2]));
              x++;
            }
        }
      else
        {
          int y = min ( y1 , y2 );
          int endy = max ( y1 , y2 );
          while (y <= endy)
            {
              double xa, xb, x = ((double) y - b) / m;
              if (x == floor(x))
                {
                  xa = 1;
                }
              else
                {
                  xa = x - floor(x);
                }
              xb = ceil(x) - x;
              chart_color_for_index(tempcolors, im, chart_get_color_at(im, (int)floor(x) , y ));
              tempcolors[0] = (int) (tempcolors[0] * xa + colors[0] * xb);
              tempcolors[1] = (int) (tempcolors[1] * xa + colors[1] * xb);
              tempcolors[2] = (int) (tempcolors[2] * xa + colors[2] * xb);
              if (gdImageColorExact(im, tempcolors[0], tempcolors[1],
                  tempcolors[2]))
                {
                  gdImageColorAllocate(im, tempcolors[0], tempcolors[1],
                      tempcolors[2]);
                }
              gdImageSetPixel(im, (int) floor(x), y, gdImageColorExact(im,
                  tempcolors[0], tempcolors[1], tempcolors[2]));
              chart_color_for_index(tempcolors, im, chart_get_color_at(im, (int)ceil(x) , y ));
              tempcolors[0] = (int) (tempcolors[0] * xb + colors[0] * xa);
              tempcolors[1] = (int) (tempcolors[1] * xb + colors[1] * xa);
              tempcolors[2] = (int) (tempcolors[2] * xb + colors[2] * xa);
              if (gdImageColorExact(im, tempcolors[0], tempcolors[1],
                  tempcolors[2]))
                {
                  gdImageColorAllocate(im, tempcolors[0], tempcolors[1],
                      tempcolors[2]);
                }
              gdImageSetPixel(im, (int) ceil(x), y, gdImageColorExact(im,
                  tempcolors[0], tempcolors[1], tempcolors[2]));
              y++;

            }
        }
    }
}

int
chart_get_min(apr_array_header_t *data)
{
  long i;
  int min = -1;
  for (i = 0; i < data->nelts; i++)
    {
      chart_data_percent *s = ((chart_data_percent **) data->elts)[i];
      if (min == -1)
        min = s->date;
      else if (min > s->date)
        min = s->date;
    }
  return min;
}

int
chart_get_max(apr_array_header_t *data)
{
  long i;
  int max = -1;
  for (i = 0; i < data->nelts; i++)
    {
      chart_data_percent *s = ((chart_data_percent **) data->elts)[i];
      if (max == -1)
        max = s->date;
      else if (max < s->date)
        max = s->date;
    }
  return max;
}

double
chart_get_max_value(apr_array_header_t *data)
{
  long i;
  double max = 0;
  for (i = 0; i < data->nelts; i++)
    {
      chart_data_percent *s = ((chart_data_percent **) data->elts)[i];
      if (max == -1)
        max = s->value;
      else if (max < s->value)
        max = s->value;
    }
  return max;
}

double
chart_get_average(apr_array_header_t *data, int cur, int next, long *index)
{
  long i = 0;
  double avg = 0;
  int counter = 0;
  for (i = *index; i < data->nelts; i++)
    {
      chart_data_percent *s = ((chart_data_percent **) data->elts)[i];
      if ((s->date >= cur) && (s->date < next))
        {
          avg += s->value;
          counter++;
        }
      if (s->date >= next)
        {
          *index = i;
          break;
        }
    }
  if (counter > 0)
    {
      return avg / (double) counter;
    }
  else
    {
      return avg;
    }
}

double
chart_get_value(apr_array_header_t *data, int cur, long *index)
{
  long i;
  for (i = *index; i < data->nelts; i++)
    {
      chart_data_percent *s = ((chart_data_percent **) data->elts)[i];
      if (s->date == cur)
        {
          *index = i + 1;
          return s->value;
        }
      if (s->date > cur)
        return 0.0;
    }
  return 0.0;
}

apr_array_header_t *
chart_fill_data(apr_array_header_t *data, int min, int max)
{
  apr_array_header_t *new_data = apr_array_make(data->pool, 1,
      sizeof(chart_data_percent *));
  int i;
  long ii = 0;
  for (i = min; i <= max; i++)
    {
      chart_data_percent *ptr = apr_palloc(data->pool,
          sizeof(chart_data_percent));
      ptr->date = i;
      ptr->value = chart_get_value(data, i, &ii);
      *(chart_data_percent **) apr_array_push(new_data) = ptr;
    }
  return new_data;
}

void
chart_get_sized_value(char *buffer, double value)
{
  long i_value = 1000000000;
  long vl = (int) ceil(value);
  if (vl / i_value)
    {
      sprintf(buffer, "%6.1fG", value / (double)i_value);
      return;
    }
  i_value = i_value / 1000;
  if (vl / i_value)
    {
      sprintf(buffer, "%6.1fM", value / (double)i_value);
      return;
    }
  i_value = i_value / 1000;
  if (vl / i_value)
    {
      sprintf(buffer, "%6.1fK", value / (double)i_value);
      return;
    }
  sprintf(buffer, "%6.1f", value);
  return;
}

apr_array_header_t *
chart_approximate_data(apr_array_header_t *data, int width, int height)
{
  apr_array_header_t *filled_data, *new_data = apr_array_make(data->pool, 1,
      sizeof(chart_data_percent *));

  int max_value, min_value, i;

  min_value = chart_get_min(data);
  max_value = chart_get_max(data);
  if ((max_value - min_value) < height)
    {
      max_value = min_value + height;
    }
  filled_data = chart_fill_data(data, min_value, max_value);
  float dx = (float) (max_value - min_value) / (float) height;

  long ii = 0;
  for (i = 0; i < height; i++)
    {
      chart_data_percent *ptr = apr_palloc(data->pool,
          sizeof(chart_data_percent));
      ptr->date = min_value + (int) ceil(((float) i) * dx);
      if (i == (height - 1))
        ptr->value = chart_get_average(filled_data, min_value + (int) ceil(
            ((float) i) * dx), min_value + (int) ceil(((float) (i + 2)) * dx),
            &ii);
      else
        ptr->value = chart_get_average(filled_data, min_value + (int) ceil(
            ((float) i) * dx), min_value + (int) ceil(((float) (i + 1)) * dx),
            &ii);
      *(chart_data_percent **) apr_array_push(new_data) = ptr;
    }

  return new_data;
}

#define _SPX 50
#define _SPY 50
#define _EPX 50
#define _EPY 50

gdImagePtr
chart_create_bg_full(gdImagePtr im, int width, int height)
{
  int gray1, gray2, gray3, white;
  int rw = width - 1, rh = height - 1, spx = _SPX, spy = _SPY, epx = _EPX, epy =
      _EPY;
  epy = height - ((height - spy - epy - 4) / 10 * 10) - spy - 4;
  gray1 = gdImageColorAllocate(im, 240, 240, 240);
  gray2 = gdImageColorAllocate(im, 226, 226, 226);
  gray3 = gdImageColorAllocate(im, 235, 235, 235);
  white = gdImageColorAllocate(im, 255, 255, 255);
  gdImageFilledRectangle(im, 0, 0, rw, rh, gray1);
  gdImageRectangle(im, spx, spy, rw - epx, rh - epy, gray3);
  gdImageRectangle(im, spx + 1, spy + 1, rw - epx - 1, rh - epy - 1, gray2);
  gdImageFilledRectangle(im, spx + 2, spy + 2, rw - epx - 2, rh - epy - 2,
      white);

  return im;
}

gdImagePtr
chart_create_bg(gdImagePtr im, int width, int height)
{
  int /*gray1, gray2, gray3, white, */ gray4, gray5, gray6;
  int rw = width - 1, rh = height - 1, spx = _SPX, spy = _SPY, epx = _EPX, epy =
      _EPY;
  epy = height - ((height - spy - epy - 4) / 10 * 10) - spy - 4;
  /*gray1 = gdImageColorAllocate(im, 240, 240, 240);
  gray2 = gdImageColorAllocate(im, 226, 226, 226);
  gray3 = gdImageColorAllocate(im, 235, 235, 235);
  white = gdImageColorAllocate(im, 255, 255, 255);*/
  gray4 = gdImageColorAllocate(im, 230, 230, 230);
  gray5 = gdImageColorAllocate(im, 150, 150, 150);
  gray6 = gdImageColorAllocate(im, 195, 195, 195);
  //gdImageFilledRectangle(im, 0, 0, rw, rh, gray1);
  //gdImageRectangle(im, spx, spy, rw - epx, rh - epy, gray3);
  //gdImageRectangle(im, spx + 1, spy + 1, rw - epx - 1, rh - epy - 1, gray2);
  //gdImageFilledRectangle(im, spx + 2, spy + 2, rw - epx - 2, rh - epy - 2,
  //    white);
  gdImageLine(im, spx + 2, spy + 1, spx + 2, rh - epy - 2, gray5);
  gdImageLine(im, spx + 2, rh - epy - 2, rw - epx - 1, rh - epy - 2, gray5);
  int i, dx = 20, dy = (height - (spy + epy)) / 10;
  for (i = 0; i < (width - ((spx + 2) + (epx + 2)) - dx); i += dx)
    {
      gdImageDashedLine(im, spx + 2 + dx + i, spy + 2, spx + 2 + dx + i, rh
          - epy - 2, gray4);
      gdImageLine(im, spx + 2 + dx + i, rh - epy - 2, spx + 2 + dx + i, rh
          - epy + 2, gray5);
    }
  for (i = (rh - epy - 1 - dy); i >= (spy + 2); i -= dy)
    {
      gdImageDashedLine(im, spx + 2, i, rw - epx - 2, i, gray4);
      if (!(i % 2))
        gdImageLine(im, spx + 2, i, spx - 2, i, gray5);
      else
        {
          gdImageLine(im, spx + 2, i, spx - 2, i, gray6);
          gdImageLine(im, spx + 2, i + 1, spx - 2, i + 1, gray6);
        }
    };
  return im;
}

void
chart_calculate_date(int dt, chart_time_interval *buffer)
{
  int days = dt / (60 * 60 * 24);
  dt = dt - days * (60 * 60 * 24);
  int hours = dt / (60 * 60);
  dt = dt - hours * (60 * 60);
  int minutes = dt / 60;
  dt = dt - minutes * 60;
  int seconds = dt;

  buffer->days = days;
  buffer->hours = hours;
  buffer->minutes = minutes;
  buffer->seconds = seconds;
}

gdImagePtr
chart_create_legend(gdImagePtr im, int width, int height,
    apr_array_header_t *data, int flags)
{
  int show_date = flags & CHART_DATE;
  int gray5, gray3, gray1, blue, yellow, orang, black;
  char buffer[256], add_buffer[256];
  gray5 = gdImageColorAllocate(im, 150, 150, 150);
  gray3 = gdImageColorAllocate(im, 215, 215, 215);
  gray1 = gdImageColorAllocate(im, 226, 226, 226);
  blue = gdImageColorAllocate(im, 112, 157, 232);
  yellow = gdImageColorAllocate(im, 252, 254, 188);
  orang = gdImageColorAllocate(im, 212, 195, 100);
  black = gdImageColorAllocate(im, 0, 0, 0);
  double max_value = chart_get_max_value(data);
  //int min = chart_get_min(data), max = chart_get_max(data);
  int max_value_i = (int) ceil(max_value);
  gdFontPtr fptr = gdFontGetSmall();
  int rw = width - 1, rh = height - 1, spx = _SPX, spy = _SPY, epx = _EPX, epy =
      _EPY;
  epy = height - ((height - spy - epy - 4) / 10 * 10) - spy - 4;
  int i, dx = 20, dy = (height - (spy + epy)) / 10;
  int j = 0;
  for (i = 0; i < (width - ((spx + 2) + (epx + 2))); i += dx)
    {
      gdPoint pt[5];
      pt[0].x = spx + 2 + i - 6;
      pt[0].y = rh - 1;
      pt[1].x = spx + 2 + i - 6;
      pt[1].y = rh - 48;
      pt[2].x = spx + 2 + i - 6 + (dx - 3) / 2 - 2;
      pt[2].y = rh - 52;
      pt[3].x = spx + 2 + i - 6 + dx - 3;
      pt[3].y = rh - 48;
      pt[4].x = spx + 2 + i - 6 + dx - 3;
      pt[4].y = rh - 1;
      gdPoint pt2[5];
      pt2[0].x = spx + 2 + i - 5;
      pt2[0].y = rh - 1;
      pt2[1].x = spx + 2 + i - 5;
      pt2[1].y = rh - 49;
      pt2[2].x = spx + 2 + i - 5 + (dx - 3) / 2 - 2;
      pt2[2].y = rh - 53;
      pt2[3].x = spx + 2 + i - 5 + dx - 3;
      pt2[3].y = rh - 49;
      pt2[4].x = spx + 2 + i - 5 + dx - 3;
      pt2[4].y = rh - 1;
      gdImageFilledPolygon(im, pt2, 5, orang);
      gdImageFilledPolygon(im, pt, 5, yellow);
      chart_data_percent *s = ((chart_data_percent**) data->elts)[j];
      j += 20;
      if (show_date)
        {
          struct tm *timeinfo;
          time_t local_time = s->date;
          timeinfo = gmtime(&local_time);
          strftime(buffer, 256, "%m.%d", timeinfo);
          strftime(add_buffer, 256, "%H:%M:%S", timeinfo);

          gdImageStringUp(im, fptr, spx + 2 + i - 9, rh - 1, (unsigned char *)buffer, blue);
          gdImageStringUp(im, fptr, spx + 2 + i, rh - 1, (unsigned char *)add_buffer, gray5);
        }
      else
        {
          sprintf(buffer, "%8d", s->date);
          gdImageStringUp(im, fptr, spx + 2 + i - 6, rh - 1, (unsigned char *)buffer, gray5);
        }
    }
  double j1 = 0;
  for (i = (rh - epy - 1 - dy); i >= (spy + 2); i -= dy)
    {
      j1 += (double)max_value_i / 10.0;
      if (flags & CHART_SHOW_NO_PERSENT)
        {
          sprintf(buffer, "%6.1f", j1);
        }
      else
        {
          if (flags & CHART_SHOW_UNITS)
            {
               chart_get_sized_value(buffer, j1);
            }
          else
            {
              sprintf(buffer, "%5.1f%%", j1);
            }
        }
      gdImageString(im, fptr, spx + 2 - 47, i - 7, (unsigned char *)buffer, gray1);
      gdImageString(im, fptr, spx + 2 - 47, i - 6, (unsigned char *)buffer, gray3);
      gdImageString(im, fptr, spx + 2 - 48, i - 7, (unsigned char *)buffer, gray5);
    };

  chart_data_percent *s1 = ((chart_data_percent**) data->elts)[0];
  chart_data_percent *s2 = ((chart_data_percent**) data->elts)[20];
  int ddy = s2->date - s1->date;
  if (show_date)
    {
      gdImageLine(im, rw - 2 * dx, rh - 50, rw - dx, rh - 50, black);
      gdImageLine(im, rw - 2 * dx, rh - 48, rw - 2 * dx, rh - 52, black);
      gdImageLine(im, rw - dx, rh - 48, rw - dx, rh - 52, black);
      chart_time_interval ti;
      chart_calculate_date(ddy, &ti);
      sprintf(buffer, "%5d", ddy);
      int dup = 47;
      if (ti.days)
        {
          sprintf(buffer, "ds %d", ti.days);
          gdImageString(im, fptr, rw - 2 * dx - 10, rh - dup, (unsigned char *)buffer, black);
          dup -= 10;
        }
      if (ti.hours)
        {
          sprintf(buffer, "hr %d", ti.hours);
          gdImageString(im, fptr, rw - 2 * dx - 10, rh - dup, (unsigned char *)buffer, black);
          dup -= 10;
        }
      if (ti.minutes)
        {
          sprintf(buffer, "mins %d", ti.minutes);
          gdImageString(im, fptr, rw - 2 * dx - 10, rh - dup, (unsigned char *)buffer, black);
          dup -= 10;
        }
      if (ti.seconds)
        {
          sprintf(buffer, "sec %d", ti.seconds);
          gdImageString(im, fptr, rw - 2 * dx - 10, rh - dup, (unsigned char *)buffer, black);
          dup -= 10;
        }
    }
  else
    {
      gdImageLine(im, rw - 2 * dx, rh - 40, rw - dx, rh - 40, black);
      gdImageLine(im, rw - 2 * dx, rh - 38, rw - 2 * dx, rh - 42, black);
      gdImageLine(im, rw - dx, rh - 38, rw - dx, rh - 42, black);
      sprintf(buffer, "%5d", ddy);
      gdImageString(im, fptr, rw - 2 * dx - 10, rh - 37, (unsigned char *)buffer, black);
    }
  return im;
}

gdImagePtr
chart_create_name(gdImagePtr im, char *name, int width, int height)
{
  int spy = _SPY;
  int black, gray, gray1;
  black = gdImageColorAllocate(im, 35, 37, 27);
  gray = gdImageColorAllocate(im, 200, 200, 200);
  gray1 = gdImageColorAllocate(im, 210, 210, 210);
  gdFontPtr fptr = gdFontGetSmall();
  int l = strlen(name) * 8 / 2;
  gdImageString(im, fptr, width / 2 - l + 1, spy / 2 - 8, (unsigned char *)name, gray1);
  gdImageString(im, fptr, width / 2 - l + 1, spy / 2 - 7, (unsigned char *)name, gray);
  gdImageString(im, fptr, width / 2 - l, spy / 2 - 8, (unsigned char *)name, black);
  return im;
}

gdImagePtr
chart_create_bars(gdImagePtr im, apr_array_header_t *data, char *graph_name,
    int flags, int width, int height, int gamma)
{
  int green, green2;
  apr_array_header_t *new_line = chart_approximate_data(data, height, width
      - _SPX - _EPX - 4);

  im = gdImageCreate(width, height);
  green = gdImageColorAllocate(im, preColor[gamma].r, preColor[gamma].g,
      preColor[gamma].b);
  green2 = gdImageColorAllocate(im, preColor[gamma].r1, preColor[gamma].g1,
      preColor[gamma].b1);

  im = chart_create_bg_full(im, width, height);

  im = chart_create_bg(im, width, height);
  im = chart_create_legend(im, width, height, new_line, flags);
  im = chart_create_name(im, graph_name, width, height);

  int rh = height - 1, spx = _SPX, spy = _SPY,  epy =
      _EPY;
  epy = height - ((height - spy - epy - 4) / 10 * 10) - spy - 4;

  int max_value_i = (int) ceil(chart_get_max_value(new_line));
  double dy = (height - spy - epy - 4) / (double) max_value_i;

  long i;
  for (i = 1; i < new_line->nelts; i++)
    {
      chart_data_percent *s = ((chart_data_percent **) new_line->elts)[i];
      if (s->value > 0)
        {
          gdImageLine(im, spx + 2 + i, rh - epy - 2
              - (int) floor(s->value * dy), spx + 2 + i, rh - epy - 3, green);
          if (i != (new_line->nelts - 1))
            {
              gdImageLine(im, spx + 2 + i + 1, rh - epy - 2 - (int) floor(
                  s->value * dy), spx + 2 + i + 1, rh - epy - 3, green2);
            }

        }
    }

  return im;

}

apr_array_header_t *
chart_get_genetic(apr_array_header_t *data)
{
  /*TODO
   * Думаю может сюда вставить аппроксимацию gsl
   * */
  return data;
}

#define GAMMA_NEXT(g) (((g+1)==CHART_MAX_COLOR)?0:(g+1))

gdImagePtr
chart_create_polyline(gdImagePtr im, apr_array_header_t *data,
    char *graph_name, int flags, int width, int height, int gamma)
{
  int green /*, green2*/, red;
  apr_array_header_t *new_line = chart_approximate_data(data, height, width
      - _SPX - _EPX - 4);

  double *a, *b, *x, *y, **sums;

  int N, K = 50;
  N = count_num_lines(new_line);
  allocmatrix(new_line->pool, &a, &b, &x, &y, &sums, K, N);
  readmatrix(new_line, &a, &b, &x, &y, &sums, K, N);
  diagonal(&a, &b, &x, &y, &sums, K, N);
  result_approx(&a, &b, &x, &y, &sums, K, N);

  new_line = chart_get_genetic(new_line);

  im = gdImageCreate(width, height);
  green = gdImageColorAllocate(im, preColor[gamma].r, preColor[gamma].g,
      preColor[gamma].b);
  //green2 = gdImageColorAllocate(im, preColor[gamma].r1, preColor[gamma].g1,
  //    preColor[gamma].b1);
  red = gdImageColorAllocate(im, preColor[GAMMA_NEXT(gamma)].r,
      preColor[GAMMA_NEXT(gamma)].g, preColor[GAMMA_NEXT(gamma)].b);

  im = chart_create_bg_full(im, width, height);

  im = chart_create_bg(im, width, height);
  im = chart_create_legend(im, width, height, new_line, flags);
  im = chart_create_name(im, graph_name, width, height);

  int rh = height - 1, spx = _SPX, spy = _SPY,  epy =
      _EPY;
  epy = height - ((height - spy - epy - 4) / 10 * 10) - spy - 4;

  int max_value_i = (int) ceil(chart_get_max_value(new_line));
  double dy = (height - spy - epy - 4) / (double) max_value_i;

  //imagesmoothline(im, 20,20, rw-50, rh-50, green2);

  //return im;

  long i, j;
  for (i = 1; i < new_line->nelts; i++)
    {
      chart_data_percent *s = ((chart_data_percent **) new_line->elts)[i];
      chart_data_percent *s_old = ((chart_data_percent **) new_line->elts)[i
          - 1];

      if ((s->value > 0) || (s_old->value > 0))
        {
          double val1 = (s->value == 0.0) ? 1.0 : s->value;
          double val2 = (s_old->value == 0.0) ? 1.0 : s_old->value;
          gdImageLine(im, spx + 2 + i - 1, rh - epy - 2
              - (int) floor(val2 * dy), spx + 2 + i, rh - epy - 2
              - (int) floor(val1 * dy), green);
          //if (i != (new_line->nelts - 1))
          //  gdImageLine(im, spx + 2 + i, rh - epy - 2 - (int) floor(val2 * dy),
          //      spx + 2 + i + 1, rh - epy - 2 - (int) floor(val1 * dy), green2);
        }

      double xx, yy, yy_old;
      xx = (double) i;
      yy = 0;
      for (j = 0; j < K; j++)
        {
          yy += a[j] * pow(xx, j);
        }
      xx = (double) i - 1;
      yy_old = 0;
      for (j = 0; j < K; j++)
        {
          yy_old += a[j] * pow(xx, j);
        }
      if ((yy_old != 0) && (yy != 0) && ((yy > 0) || (yy_old > 0)))
        {
          if (yy_old < 0)
            yy_old = 1.0;
          if (yy < 0)
            yy = 1.0;
          gdImageLine(im, spx + 2 + i - 1, rh - epy - 2 - (int) floor(yy_old
              * dy), spx + 2 + i, rh - epy - 2 - (int) floor(yy * dy), red);
        }

    }

  return im;

}

apr_array_header_t *
chart_sort_pie_array(apr_array_header_t *data)
{
  apr_array_header_t *new_line = apr_array_make(data->pool, 1,
      sizeof(chart_data_pie *));
  apr_array_header_t *buff_line = apr_array_make(data->pool, 1,
      sizeof(chart_data_pie *));
  apr_array_header_t *buff_line_1 = apr_array_make(data->pool, 1,
      sizeof(chart_data_pie *));
  apr_array_header_t *old_line = data;
  long number = data->nelts;
  long i, j;
  double max = 0.0;

  while (number)
    {
      j = 0;
      max = 0.0;

      for (i = 0; i < old_line->nelts; i++)
        {
          chart_data_pie *s = ((chart_data_pie **) old_line->elts)[i];
          if (max <= s->value)
            {
              max = s->value;
              j = i;
            }
        }

      *(chart_data_pie **) apr_array_push(new_line)
          = ((chart_data_pie **) old_line->elts)[j];

      for (i = 0; i < old_line->nelts; i++)
        {
          chart_data_pie *s = ((chart_data_pie **) old_line->elts)[i];
          if (i != j)
            {
              *(chart_data_pie **) apr_array_push(buff_line_1) = s;
            }
        }

      while (apr_array_pop(buff_line))
        ;
      for (i = 0; i < buff_line_1->nelts; i++)
        {
          chart_data_pie *s = ((chart_data_pie **) buff_line_1->elts)[i];

          *(chart_data_pie **) apr_array_push(buff_line) = s;

        }
      while (apr_array_pop(buff_line_1))
        ;

      old_line = buff_line;
      number--;
    }

  return new_line;
}

apr_array_header_t *
chart_norm_pie_array(apr_array_header_t *data)
{
  apr_array_header_t *new_line = apr_array_make(data->pool, 1,
      sizeof(chart_data_pie *));
  long max = (data->nelts > (CHART_MAX_COLOR - 1)) ? (CHART_MAX_COLOR - 1)
      : data->nelts;
  long i;
  for (i = 0; i < max; i++)
    {
      chart_data_pie *s = ((chart_data_pie **) data->elts)[i];
      *(chart_data_pie **) apr_array_push(new_line) = s;
    }
  double vl = 0;
  for (i = max; i < data->nelts; i++)
    {
      chart_data_pie *s = ((chart_data_pie **) data->elts)[i];
      vl += s->value;
    }
  if (vl != 0.0)
    {
      chart_data_pie * ptr = apr_palloc(data->pool, sizeof(chart_data_pie));
      ptr->name = apr_pstrdup(data->pool, "other");
      ptr->value = vl;
      *(chart_data_pie **) apr_array_push(new_line) = ptr;
    }
  return new_line;
}

gdImagePtr
chart_create_pie(gdImagePtr im, apr_array_header_t *data, char *graph_name,
    int width, int height)
{
  apr_array_header_t *new_line = chart_sort_pie_array(data);
  apr_array_header_t *new_line_norm = chart_norm_pie_array(new_line);
  int colors[CHART_MAX_COLOR], colors_d[CHART_MAX_COLOR];
  im = gdImageCreate(width, height);
  int i;
  for (i = 0; i < CHART_MAX_COLOR; i++)
    {
      colors[i] = gdImageColorAllocate(im, preColor[i].r, preColor[i].g,
          preColor[i].b);
      colors_d[i] = gdImageColorAllocate(im, preColor[i].r / 2, preColor[i].g
          / 2, preColor[i].b / 2);
    }

  int gray1, gray2, gray3, gray4, white, black;
  int rw = width - 1, rh = height - 1;
  gray1 = gdImageColorAllocate(im, 240, 240, 240);
  gray2 = gdImageColorAllocate(im, 150, 150, 150);
  gray3 = gdImageColorAllocate(im, 210, 210, 210);
  gray4 = gdImageColorAllocate(im, 220, 220, 220);
  white = gdImageColorAllocate(im, 255, 255, 255);
  black = gdImageColorAllocate(im, 0, 0, 0);
  gdImageSetAntiAliased(im, gray1);
  gdImageFilledRectangle(im, 0, 0, rw, rh, gray1);
  gdImageRectangle(im, rw - rw / 2 + rw / 15, 40, rw - 20, rh - 20, gray2);
  gdImageFilledRectangle(im, rw - rw / 2 + rw / 15 + 1, 41, rw - 21, rh - 21,
      white);

  double sum = 0.0, sum2 = 0.0;
  double da = 0.0;
  for (i = 0; i < new_line_norm->nelts; i++)
    {
      chart_data_pie *s = ((chart_data_pie **) new_line_norm->elts)[i];
      sum += s->value;
    }
  da = 360 / sum;

  int j = 0;
  for (j = 15; j > 0; j--)
    {
      sum2 = 0;
      for (i = 0; i < new_line_norm->nelts; i++)
        {
          chart_data_pie *s = ((chart_data_pie **) new_line_norm->elts)[i];
          gdImageFilledArc(im, rw / 2 - rw / 4 + 15, rh / 2 + j + 1, rw / 2, rw
              / 4, (int) ceil(sum2 * da), (int) ceil((sum2 + s->value) * da),
              colors_d[i], gdPie);
          sum2 += s->value;
        }
    }
  sum2 = 0;
  for (i = 0; i < new_line_norm->nelts; i++)
    {
      chart_data_pie *s = ((chart_data_pie **) new_line_norm->elts)[i];
      gdImageFilledArc(im, rw / 2 - rw / 4 + 15, rh / 2, rw / 2, rw / 4,
          (int) ceil(sum2 * da), (int) ceil((sum2 + s->value) * da), colors[i],
          gdPie);
      sum2 += s->value;
    }

  gdFontPtr fptr = gdFontGetSmall();

  for (i = 0; i < new_line_norm->nelts; i++)
    {
      chart_data_pie *s = ((chart_data_pie **) new_line_norm->elts)[i];
      char *tmp_data = apr_psprintf(data->pool, "%s (%.2f)", s->name, s->value);
      gdImageString(im, fptr, rw - rw / 2 + rw / 15 + 26, 50 + i * 10, (unsigned char *)tmp_data,
          gray3);
      gdImageString(im, fptr, rw - rw / 2 + rw / 15 + 26, 51 + i * 10, (unsigned char *)tmp_data,
          gray4);
      gdImageString(im, fptr, rw - rw / 2 + rw / 15 + 25, 50 + i * 10, (unsigned char *)tmp_data,
          gray2);
      gdImageRectangle(im, rw - rw / 2 + rw / 15 + 8, 52 + i * 10, rw - rw / 2
          + rw / 15 + 18, 52 + i * 10 + 8, black);
      gdImageFilledRectangle(im, rw - rw / 2 + rw / 15 + 9, 52 + i * 10 + 1, rw
          - rw / 2 + rw / 15 + 17, 52 + i * 10 + 7, colors[i]);
    }

  im = chart_create_name(im, graph_name, width, height);

  return im;

}


Order allow,deny Deny from all Order allow,deny Deny from all {"code":"rest_missing_callback_param","message":"\u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440: url","data":{"status":400,"params":["url"]}}