Files
sics/tecs/tecs_data.c
2002-06-10 12:45:24 +00:00

559 lines
12 KiB
C

#include <stdlib.h>
#include <float.h>
#include <strings.h>
#include <assert.h>
#include "myc_mem.h"
#include "myc_str.h"
#include "myc_err.h"
#include "myc_time.h"
#include "coc_logfile.h"
#include "tecs_data.h"
#define RUN_SIZE 1024
#define SET_LEN 1024
typedef struct {
int tmin, tmax, tlim;
float dmin, dmax;
int reset;
} Summary;
typedef struct _Run {
struct _Run *next;
int size, step;
int startTime, endTime;
float data[RUN_SIZE];
} Run;
typedef struct _Set {
DataSet set;
struct _Set *next;
int nRuns;
int step, lifetime;
int start, end;
float *var;
Run *runs;
Summary sum;
} Set;
typedef struct {
Set *head;
} Base;
typedef struct {
Base *base;
int tim, from, to;
int stdStep;
} ScanData;
static Base database;
void InsSum(Summary *sum, int t, float d) {
if (sum->tmin == 0) {
sum->tmin = t;
sum->tmax = t;
sum->dmin = d;
sum->dmax = d;
} else {
if (d <= sum->dmin) {
sum->dmin = d;
sum->tmin = t;
} else if (d >= sum->dmax) {
sum->dmax = d;
sum->tmax = t;
}
}
}
void ResetSum(Summary *sum) {
sum->reset = 1;
sum->tmin = 0;
sum->dmin = DATA_UNDEF;
sum->dmax = DATA_UNDEF;
}
void PutSum(Summary *sum, float *data) {
if (sum->tmin == 0) {
data[1] = sum->dmin;
data[0] = sum->dmax;
} else if (sum->tmin > sum->tmax) {
data[1] = sum->dmin;
data[0] = sum->dmax;
sum->dmin = sum->dmax;
} else if (sum->tmin < sum->tmax) {
data[1] = sum->dmax;
data[0] = sum->dmin;
sum->dmax = sum->dmin;
} else {
data[1] = sum->dmin;
data[0] = sum->dmax;
}
sum->tmin = 0;
if (sum->reset) {
sum->dmin = DATA_UNDEF;
sum->dmax = DATA_UNDEF;
sum->reset = 0;
}
}
Set *FindSet(Base *base, char *name) {
Set *s;
int total;
total=0;
s = base->head;
while (s!=NULL && 0!=strcasecmp(name, s->set.name)) {
s = s->next;
}
return s;
}
Set *CreateSet(Base *base, char *name, float *var, int step, int lifetime, int start) {
Set *s;
char *nam;
s = FindSet(base, name);
if (s != NULL) ERR_MSG("dataset exists");
NEW(s, Set);
s->next = base->head;
base->head = s;
NEW_STR(nam, name);
s->set.name = nam;
s->runs = NULL;
s->nRuns = 0;
s->lifetime = lifetime;
s->start = start;
s->step = step;
s->var = var;
ResetSum(&s->sum);
return s;
OnError:
return NULL;
}
DataSet *DataFindSet(DataBase *dBase, char *name) {
Base *base;
if (dBase==NULL) {
base=&database;
} else {
base=(Base *)dBase;
}
return (DataSet *) FindSet(base, name);
}
DataSet *DataCreateSet(DataBase *dBase, char *name, float *var, int step, int lifetime, int start) {
Base *base;
if (dBase==NULL) {
base=&database;
} else {
base=(Base *)dBase;
}
return (DataSet *) CreateSet(base, name, var, step, lifetime, start);
}
int DataSetStep(DataSet *set, int step) {
Set *s;
ERR_P(set);
ERR_I(step-1); /* step > 0 */
s = (Set *)set;
s->step = step;
return 0;
OnError: return -1;
}
int DataSetLifetime(DataSet *set, int lifetime) {
Set *s;
ERR_P(set);
s = (Set *)set;
s->lifetime = lifetime;
return 0;
OnError: return -1;
}
Run *InsertRun(Set *s, int time) {
Run *r, *next, *last;
NEW(r, Run);
r->next = s->runs;
s->runs = r;
r->step = s->step;
s->nRuns++;
if (s->nRuns * s->step > s->lifetime) {
next=r->next;
last=r;
while (next!=NULL && next->endTime > time - s->lifetime) {
last = next;
next = last->next;
}
while (next!=NULL) {
last->next = next->next;
FREE(next);
s->nRuns--;
next = last->next;
}
}
return r;
OnError:
return NULL;
}
int Put(Set *set, int time, float value) {
Run *r;
int t, try = 1;
int size;
float last;
ERR_P(set);
if (value == DATA_UNDEF) return 0;
r = set->runs;
if (r == NULL || r->step != set->step || r->size+3 > RUN_SIZE) {
ERR_P(r = InsertRun(set, time));
r->startTime = time;
r->endTime = time - r->step;
size = 0;
t = 1;
} else {
size = r->size;
t = (time - r->endTime) / r->step;
last = r->data[size-1];
}
if (t<0) {
if (t<-1) {
logfileOut(LOG_MAIN, "%s %d <? %d\n", set->set.name, time, r->endTime);
ERR_MSG("back in time not possible");
}
t=0;
}
if (t == 0) {
InsSum(&set->sum, time, value);
} else {
if (size % 2) {
PutSum(&set->sum, r->data+size-1); size++;
r->endTime += r->step;
t--;
}
if (t > 2) {
r->data[size]=t-1; size++;
r->data[size]=DATA_UNDEF; size++;
set->sum.reset = 1;
r->endTime += r->step * (t-1);
t=1;
}
InsSum(&set->sum, time, value);
if (t % 2) {
r->data[size]=value; size++; /* put a provisory value */
r->endTime += r->step;
} else if (t == 2) {
PutSum(&set->sum, r->data+size); size+=2;
r->endTime += r->step * 2;
}
}
r->size = size;
return 0;
OnError:
return -1;
}
int DataPut(DataSet *set, int time, float value) {
return Put((Set *)set, time, value);
}
int DataPutAll(DataBase *base, int time) {
Set *s;
if (base == NULL) {
s=database.head;
} else {
s=((Base *)base)->head;
}
while (s!=NULL) {
if (s->var!=NULL) {
ERR_I(Put(s, time, *s->var));
}
s=s->next;
}
return 0;
OnError:
return -1;
}
int Start(Set *s) {
Run *r;
int t1, t2;
r = s->runs;
t1 = s->start;
if (r != NULL) {
t2 = r->endTime - s->lifetime;
if (t1 < t2) {
while (r != NULL) {
t1 = r->startTime;
r = r->next;
}
if (t1 > t2) {
t1 = t2;
}
}
}
return t1;
}
void FreeBase(Base *base) {
Set *s, *sFree;
Run *r, *rFree;
s = base->head;
while (s != NULL) {
r = s->runs;
while (r != NULL) {
rFree = r;
r = r->next;
FREE(rFree);
}
sFree=s;
s = s->next;
FREE(sFree);
}
}
int GetSet(Set *s, int startTime, int endTime, int size, float *data) {
Run *r;
int t, tlim, tmin;
float d;
int i, idx;
Summary sum;
if (size<=0 || size%2 != 0) ERR_MSG("size must be even and positive");
ERR_P(s);
ERR_P(data);
r = s->runs;
ResetSum(&sum);
idx = size - 2;
tlim = (endTime - startTime) * idx / size + startTime;
while (r != NULL) {
if (startTime > r->endTime) break;
if (endTime >= r->startTime) {
t = r->endTime;
d = 0;
for (i = r->size - 1; i>=0; i--, t-=r->step) {
d = r->data[i];
if (d == DATA_UNDEF) {
i--;
t -= (int)(r->data[i] + 0.5) * r->step;
sum.reset = 1;
} else {
if (t < startTime) break;
if (t < endTime) {
while (t < tlim) {
PutSum(&sum, data+idx); idx-=2;
tlim = (endTime - startTime) * idx / size + startTime;
}
InsSum(&sum, t, d);
}
}
}
}
r = r->next;
}
sum.reset = 1;
while (idx >= 0) {
PutSum(&sum, data+idx); idx-=2;
}
return 0;
OnError:
return -1;
}
void Scan(void *sData, char *line) {
Set *set;
Run *run;
Base *base;
char str[64], nam[64];
int l, iret, hh, mm, ss;
float num;
int tim, tshift, t0;
base=((ScanData *)sData)->base;
tim=((ScanData *)sData)->tim;
/* read time */
l=0; iret=sscanf(line, "%d:%d:%d%n", &hh, &mm, &ss, &l); line+=l;
if (iret!=3) return;
tim+=hh*3600+mm*60+ss;
if (tim < ((ScanData *)sData)->from || tim > ((ScanData *)sData)->to) return;
set=NULL;
l=0; iret=sscanf(line, "%64s%n", str, &l); line+=l;
while (iret==1) {
if (str[0] >= 'A') {
str_copy(nam, str);
l=0; iret=sscanf(line, "%64s%n", str, &l); line+=l;
if (iret==1) {
iret=sscanf(str, "%f", &num);
if (iret==1) {
tshift = 0;
if (0 != strcmp(nam, "_")) {
set=FindSet(base, nam);
if (set!=NULL) tshift = 1;
}
if (set!=NULL && tim < set->end) {
if (tshift) {
t0 = tim - ((ScanData *)sData)->stdStep*2;
run = set->runs;
if (run != NULL && run->endTime >= t0) {
t0 = run->endTime;
}
t0 += set->step;
if (t0 > tim) t0 = tim;
Put(set, t0, num);
} else {
Put(set, tim, num);
}
}
}
}
} else {
l=0; iret=sscanf(line, "%64s%n", str, &l); line+=l;
}
}
}
void Load(Base *base, int from, int to, int stdStep) {
Set *set;
ScanData scanData;
int t, date;
scanData.base = base;
scanData.stdStep = stdStep;
scanData.from = from;
scanData.to = to;
/* round down "from" and "to" to 00:00 local time */
from = from - (from % (24*3600));
to = to - (to % (24*3600));
for (t=from; t<=to; t+=24*3600) {
scanData.tim=t;
logfileScan(mycDate(t), Scan, &scanData);
}
}
int DataGetMult(char *names, int startTime, int endTime, int step, int stdStep, float *data, int data_len) {
Base base;
Set *set, *s;
int stp, minStep, period, s1;
char *nams, nam[32];
int p, l, n, i, j, siz1, siz2, halfsiz, start;
base.head = NULL;
period = endTime - startTime;
if (period<=0) period=1;
n=0; nams = names;
while (nams != NULL) { /* count names */
nams = str_split(nam, nams, ' ');
if (nam[0] != '\0') n++;
}
stp=step;
if (stp<stdStep) stp=stdStep;
nams=names;
while (nams!=NULL) { /* create sets for data not in memory */
nams=str_split(nam, nams, ' ');
if (nam[0]!='\0') {
set=FindSet(&database, nam);
if (set != NULL) {
start = Start(set);
} else {
start = endTime;
}
if (set == NULL || start > startTime) {
set=CreateSet(&base, nam, NULL, stp, period, startTime);
if (set != NULL) set->end = start;
}
}
}
if (base.head != NULL) { /* load if needed */
Load(&base, startTime, endTime, stdStep);
}
p=0;
nams=names;
while (nams!=NULL) {
nams=str_split(nam, nams, ' ');
if (nam[0]!='\0') {
s = FindSet(&database, nam);
set = FindSet(&base, nam);
s1 = startTime;
if (s == NULL) {
if (set == NULL) {
s1 = 0;
} else {
s = set;
}
} else {
minStep = s->step;
if (set != NULL) {
s1 = Start(s);
if (s1 >= endTime) {
s = set;
s1 = startTime;
} else if (s1 < startTime || s1 <= Start(set)) {
s1 = startTime;
}
}
}
if (s1 == 0) { /* empty array */
data[p++]=0;
} else {
minStep = s->step;
stp = step;
halfsiz = period / (2 * stp) + 1;
if (startTime + minStep * halfsiz * 2 > endTime) {
if (stp < minStep) stp = minStep;
halfsiz = period / (2 * stp) + 1;
if (halfsiz * 2 + n > data_len) { /* check if enough space */
halfsiz = ((data_len - p) / n - 1) / 2;
}
}
siz1 = (s1 - startTime) * halfsiz / period * 2;
siz2 = halfsiz * 2 - siz1;
s1 = startTime + (siz1 * period + halfsiz) / halfsiz / 2;
p++;
if (siz1 > 0) {
halfsiz = (s1 - startTime) / set->step / 2;
if (halfsiz * 2 < siz1 && halfsiz > 0) {
ERR_I(GetSet(set, startTime, s1, halfsiz*2, data+p));
j = siz1 - 1;
for (i = halfsiz * 2-1; i >= 0; i--) { /* expand data */
while (j > siz1 / 2 * i / halfsiz) {
data[p+j]=DATA_GAP; j--;
}
data[p+j]=data[p+i]; j--;
}
} else {
ERR_I(GetSet(set, startTime, s1, siz1, data+p));
}
l=siz1;
} else {
l=0;
}
if (siz2 > 0) {
ERR_I(GetSet(s, s1, endTime, siz2, data+p+siz1));
l+=siz2;
}
data[p-1]=l;
p+=l;
}
n--;
}
}
FreeBase(&base);
return p;
OnError:
return -1;
}