00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "cgi.h"
00023
00024 #include "math.h"
00025
00026 typedef struct {int count; double sum, sum2; char* field; char* query;} counter;
00027
00028 void UpdateCounts(CGINameValue* record,counter* counts,int length)
00029 {
00030 size_t j;
00031 for(j=0; j< length; j++)
00032 {
00033 if (counts[j].query == 0 || EvaluateLogic(counts[j].query,record,0))
00034 {
00035 counts[j].count ++;
00036 if (counts[j].field)
00037 {
00038 double d = strtod(GetFieldValue(record,counts[j].field),0);
00039 if (d < 10E16 && d > -10E16)
00040 {
00041 counts[j].sum += d;
00042 counts[j].sum2 += d * d;
00043 }
00044 }
00045 }
00046 }
00047 }
00048
00049 counter* SetupList(CGINameValue*x,int field, int* length)
00050 {
00051 int i = 0;
00052 counter* list;
00053 while (x[i].name) i++;
00054 if (!i) return 0;
00055 list = malloc(i * sizeof(counter));
00056 for (i=0; x[i].name; i++)
00057 {
00058 if (field)
00059 {
00060 char* c = strchr(x[i].value,',');
00061 if (c) *c++ = 0;
00062 list[i].query = c;
00063 list[i].field = x[i].value;
00064 }
00065 else
00066 {
00067 list[i].field = 0;
00068 list[i].query = x[i].value;
00069 }
00070 list[i].sum = list[i].sum2 = 0;
00071 list[i].count = 0;
00072 }
00073 if (length) *length = i;
00074 return list;
00075 }
00076
00077 CGINameValue* GetTotal(CGINameValue* count,CGINameValue* sum,
00078 counter* countList,
00079 counter* sumList,
00080 int countLength,
00081 int sumLength)
00082 {
00083 CGINameValue* result = NewNVP(countLength + (sumLength * 6));
00084 int i;
00085 int j=0;
00086 char temp[32];
00087
00088 if (count && countList)
00089 for (i=0; count[i].name; i++)
00090 {
00091 result[j].name = strdup(count[i].name);
00092 sprintf(temp,"%d",countList[i].count);
00093 result[j++].value = strdup(temp);
00094 }
00095
00096 if (sum && sumList)
00097 for (i=0; sum[i].name; i++)
00098 {
00099 double Average = 0;
00100 double StdDev = 0;
00101 double StdError = 0;
00102
00103 result[j].name = strdup(sum[i].name);
00104 sprintf(temp,"%d",sumList[i].sum);
00105 result[j++].value = strdup(temp);
00106
00107 result[j].name = strdup3(sum[i].name,".sum","");
00108 sprintf(temp,"%f",sumList[i].sum);
00109 result[j++].value = strdup(temp);
00110
00111 result[j].name = strdup3(sum[i].name,".sum2","");
00112 sprintf(temp,"%f",sumList[i].sum2);
00113 result[j++].value = strdup(temp);
00114
00115 if (sumList[i].count > 0)
00116 {
00117 Average = sumList[i].sum/sumList[i].count;
00118 StdDev = sqrt((sumList[i].sum2 - Average * sumList[i].sum)/sumList[i].count);
00119 StdError = StdDev/sqrt(sumList[i].count);
00120 }
00121 result[j].name = strdup3(sum[i].name,".average","");
00122 sprintf(temp,"%f",Average);
00123 result[j++].value = strdup(temp);
00124 result[j].name = strdup3(sum[i].name,".stddev","");
00125 sprintf(temp,"%f",StdDev);
00126 result[j++].value = strdup(temp);
00127 result[j].name = strdup3(sum[i].name,".stderr","");
00128 sprintf(temp,"%f",StdError);
00129 result[j++].value = strdup(temp);
00130 }
00131 return result;
00132 }
00133
00134 int CGImain(char * argv0,CGINameValue* Params,STREAM htmlout)
00135 {
00136 CGINameValue* count = 0;
00137 CGINameValue* sum = 0;
00138 counter* countList=0;
00139 counter* sumList= 0;
00140 char FileName[MAXPATH];
00141 int i, countLength=0, sumLength=0, printSummary = 1;
00142
00143 if (Params == 0)
00144 {
00145 HTMLWrite(htmlout,"Usage: summary setup_file data_file1 data_file2 ...\n");
00146 HTMLWrite(htmlout,"Usage: summary setup_file load=calc_file report=report_file...\n");
00147 return 1;
00148 }
00149
00150 ExpandLocalPath(argv0,FileName,Params[0].name,0);
00151 count = ReadINIFileSection(FileName,"COUNT",0);
00152 sum = ReadINIFileSection(FileName,"SUM",0);
00153
00154 if (count) countList = SetupList(count,0,&countLength);
00155
00156 if (sum) sumList = SetupList(sum,1,&sumLength);
00157
00158 for (i=1; Params[i].name; i++)
00159 {
00160 CGINameValue* data;
00161 FILE * db;
00162 int skip = 0;
00163 if (!stricmp(Params[i].name,"load") && *Params[i].value)
00164 {
00165 int j;
00166 FILE* report;
00167 ExpandLocalPath(argv0,FileName,Params[i].value,0);
00168 report = fopen(FileName,"rt");
00169 if (report)
00170 {
00171 char str[32768];
00172 str[fread(str,1,32767,report)]=0;
00173 data = ReadPairedString(str,'\n',0);
00174
00175 if (data && count) for (j=0; count[j].name; j++)
00176 {
00177 countList[j].count += atoi(GetFieldValue(data,count[j].name));
00178 }
00179 if (data && sum) for (j=0; sum[j].name; j++)
00180 {
00181 char * name = strdup3(sum[j].name,".sum","");
00182 sumList[j].count += atoi(GetFieldValue(data,count[j].name));
00183 sumList[j].sum += strtod(GetFieldValue(data,name),0);
00184 free(name);
00185 name = strdup3(sum[j].name,".sum2","");
00186 sumList[j].sum2 += strtod(GetFieldValue(data,name),0);
00187 free(name);
00188 }
00189 DeleteNVP(data);
00190 }
00191 }
00192 if (!stricmp(Params[i].name,"report") && *Params[i].value)
00193 {
00194 CGINameValue* total = GetTotal(count,sum,countList,sumList,countLength,sumLength);
00195 FILE* report;
00196 ExpandLocalPath(argv0,FileName,Params[i].value,0);
00197 report = fopen(FileName,"rt");
00198 if (report)
00199 {
00200 printSummary = 0;
00201 RunReport(argv0,htmlout,report,total,total,0,0,0);
00202 fclose(report);
00203 }
00204
00205 DeleteNVP(total);
00206 }
00207 else
00208 {
00209 ExpandLocalPath(argv0,FileName,Params[i].name,0);
00210 if (!DatabaseOpen(FileName,&db,&data,0))
00211 continue;
00212
00213 while (DatabaseReadRecord(db, data,&skip))
00214 {
00215 if (skip) continue;
00216 if (countList)
00217 UpdateCounts(data,countList,countLength);
00218 if (sumList)
00219 UpdateCounts(data,sumList,sumLength);
00220 }
00221
00222 DatabaseClose(db,data);
00223 }
00224 }
00225
00226 if (printSummary)
00227 {
00228 CGINameValue* total = GetTotal(count,sum,countList,sumList,countLength,sumLength);
00229 for (i=0; total[i].name; i++)
00230 {
00231 HTMLWrite(htmlout,total[i].name);
00232 HTMLWrite(htmlout,"=");
00233 HTMLWrite(htmlout,total[i].value);
00234 HTMLWrite(htmlout,"\n");
00235 }
00236 }
00237 return 0;
00238 }