18 if (str == NULL || v == NULL || (!
isNumber(str)))
return false;
20 const size_t len = strlen(str);
21 char *mutableStr = (
char *)malloc(len + 1);
22 if (!mutableStr)
return false;
25 for (
size_t i = 0; i <= len; ++i) {
26 const char c = str[i];
27 mutableStr[i] = (c ==
',') ?
'.' : c;
31 *v = strtod(mutableStr, &endptr);
33 bool ok = (endptr != mutableStr);
40 double maxInRow, maxInCol;
44 for (
int c = 1; c < mat->
nCol; c += 1) {
45 if (mat->
t [0][c] < mat->
t[0][c-1]) {
46 snprintf (str,
sizeof str,
"Values in row 0 should progress, col: %d; ", c);
50 for (
int row = 1; row < mat->
nLine; row += 1) {
51 if ((mat->
t [row][0] < mat->
t[row-1] [0])) {
52 snprintf (str,
sizeof str,
"Values in col 0 should progress, row: %d; ", row);
56 for (
int row = 1; row < mat->
nLine; row += 1) {
59 for (
int c = 1; c < mat->
nCol; c += 1) {
60 if (mat->
t[row][c] > maxInRow) {
61 maxInRow = mat->
t[row][c];
65 for (
int c = 2; c <= cMax; c += 1) {
66 if (mat->
t [row][c] < mat->
t[row][c-1]) {
67 snprintf (str,
sizeof str,
"Values in row: %d should progress at col: %d up to maxInRow: %.2lf; ", row, c, maxInRow);
72 for (
int c = cMax + 1; c < mat->
nCol; c += 1) {
73 if ((mat->
t [row][c] > mat->
t[row][c-1])) {
74 snprintf (str,
sizeof str,
"Values in row: %d should regress at col: %d after maxInRow: %.2lf; ", row, c, maxInRow);
81 for (
int c = 1; c < mat->
nCol; c += 1) {
84 for (
int row = 1; row < mat->
nLine; row += 1) {
85 if (mat->
t[row][c] > maxInCol) {
86 maxInCol = mat->
t[row][c];
90 for (
int row = 2; row <= rowMax; row += 1) {
91 if (mat->
t [row][c] < mat->
t[row-1][c]) {
92 snprintf (str,
sizeof str,
"Values in col: %d should progress at row: %d up to maxInCol: %.2lf; ", c, row, maxInCol);
97 for (
int row = rowMax + 1; row < mat->
nLine; row += 1) {
98 if ((mat->
t [row][c] > mat->
t[row-1][c])) {
99 snprintf (str,
sizeof str,
"Values in col: %d should regress at row: %d after maxInCol: %.2lf; ", c, row, maxInCol);
105 return (report [0] ==
'\0');
113 char *pLine = &buffer [0];
115 double v = 0.0, max = 0.0;
118 errMessage [0] =
'\0';
121 if ((f = fopen (fileName,
"r")) == NULL) {
122 snprintf (errMessage, maxLen,
"Error in readPolarCsv: cannot open: %s\n", fileName);
127 if (pLine [0] ==
'#')
continue;
133 mat->
t [mat->
nLine][c] = v;
134 if ((mat->
nLine != 0) && (c != 0)) max = fmax (max, v);
137 if ((mat->
nLine == 0) && (c == 0))
141 if (c <= 2)
continue;
143 snprintf (errMessage, maxLen,
"Error in readPolarCsv: max number of colums: %d\n",
MAX_N_POL_MAT_COLS);
150 snprintf (errMessage, maxLen,
"Error in readPolarCsv: max number of line: %d\n",
MAX_N_POL_MAT_LINES);
167 for (
int i = 1; i < mat->
nLine; i++) {
168 if (mat->
t [i][0] > 90)
break;
170 if (vmg > *vmgSpeed) {
172 *vmgAngle = mat->
t [i][0];
182 for (
int i = 1; i < mat->
nLine; i++) {
183 if (mat->
t [i][0] < 90)
continue;
185 if (vmg > *vmgSpeed) {
187 *vmgAngle = mat->
t [i][0];
196 for (
int i = 0; i < mat->
nLine; i++) {
197 for (
int j = 0; j < mat->
nCol; j++) {
228 char *src = str, *dst = str;
230 if (!isspace((
unsigned char)*src)) *dst++ = *src;
238 double sailId, maxVal = 0.0;
239 int nTws = 0, maxNTws= 0, nTwa = 0;
241 char *pt = strstr (str,
"\"id\":");
242 if (pt == NULL)
return NULL;
244 sailId = strtod (pt, &endPtr);
245 if (endPtr == pt)
return NULL;
248 pt = strstr (str,
"\"name\":\"");
249 if (pt == NULL)
return NULL;
252 if (pt == NULL)
return NULL;
255 pt = strstr (pt + 1,
"\"speed\":[[");
256 if (pt == NULL)
return NULL;
261 while ((*pt ==
',') || (*pt ==
'[')) pt += 1;
263 double val = strtod (pt, &endPtr);
265 fprintf (stderr,
"In findSailPol, Error: No value at nTwa: %d, nTWs: %d\n", nTwa, nTws);
267 if ((val >=
polMat->
t [nTwa + 1][nTws + 1]) && (val > 0.0)) {
268 polMat->
t [nTwa + 1][nTws + 1] = val;
270 if (fabs (sailId - round (sailId)) > 0.2) {
271 fprintf (stderr,
"In findSail, Error: Strange Value for saiId: %.2lf\n", sailId);
273 maxVal = fmax (val, maxVal);
276 if (*endPtr ==
']')
break;
280 maxNTws = fmax (nTws, maxNTws);
282 if (*endPtr ==
']') {
284 if (*endPtr ==
']')
break;
288 snprintf (message, maxLen,
"nTws = %d and polMat->nCol-1 = %d should be equal\n", nTws,
polMat->
nCol-1);
292 snprintf (message, maxLen,
"nTwa = %d and polMat->nLine-1 = %d should be equal\n", nTwa,
polMat->
nLine-1);
301static char *
findListPol (
bool isTws,
int maxN,
char *str,
const char *startWith,
305 char *pt = strstr (str, startWith);
308 snprintf (message, maxLen,
"In findListPol, Error: %s not found.\n", startWith);
311 pt += strlen (startWith);
312 for (n = 1; pt != NULL && n < maxN; n += 1) {
313 const double val = strtod (pt, &endPtr);
314 if (endPtr == pt)
break;
318 if (*endPtr ==
']')
break;
322 snprintf (message, maxLen,
"In findListPol, Error: maxN reached for %s\n", startWith);
326 snprintf (message, maxLen,
"In findListPol, Error: ] end not found for %s\n", startWith);
340 errMessage [0] =
'\0';
341 char *buffer =
readTextFile (fileName, errMessage, maxLen);
342 if (buffer == NULL)
return false;
344 if (buffer [0] ==
'\0') {
351 begin = strstr (line,
"\"_id\"");
353 snprintf (errMessage, maxLen,
"[ _id: not found\n");
357 ptr = strstr (line,
"\"tws\":");
359 snprintf (errMessage, maxLen,
"\"tws\": not found\n");
363 strlcpy (start, begin, (ptr-begin));
364 const int len = strlen (start);
365 if (start [len - 1] ==
',') start [len - 1 ] =
'\0';
369 if (line == NULL)
return false;
371 if (line == NULL)
return false;
372 line = strstr (line,
"\"sail\":");
374 snprintf (errMessage, maxLen,
"\"sail\": not found\n");
378 line += strlen (
"sail") + 2;
384 return errMessage [0] ==
'\0';
392 if (!mat)
return false;
402 newFileNameSuffix (fileName,
"sailpol", sailPolFileName,
sizeof (sailPolFileName));
408 if (sailNameSize < mat->nSail) {
409 fprintf (stderr,
"in readPolar, Error: size of sailName: %zu not enough for nSail: %zu\n",
sailNameSize, mat->
nSail);
419char *
polToStrJson (
bool report,
const char *fileName,
const char *objName,
char *out,
size_t maxLen) {
427 if (!
readPolar (polarName, &mat, &sailMat, errMessage,
sizeof (errMessage))) {
428 fprintf (stderr,
"%s", errMessage);
429 snprintf (out, maxLen,
"{}\n");
433 fprintf (stderr,
"In polToStrJson Error: no value in: %s\n", polarName);
434 snprintf (out, maxLen,
"{}\n");
438 snprintf (out, maxLen,
439 "{\"header\": %s,\n\"%s\": \"%s\", \"nLine\": %d, \"nCol\": %d, \"nSail\": %zu, \"max\": %.2lf, \"fromJson\": %s, \n\"array\":\n[\n",
443 for (
int i = 0; i < mat.
nLine ; i++) {
445 for (
int j = 0; j < mat.
nCol - 1; j++) {
446 snprintf (str,
sizeof str,
"%.4f, ", mat.
t [i][j]);
449 snprintf (str,
sizeof (str),
"%.4f]%s\n", mat.
t [i][mat.
nCol -1], (i < mat.
nLine - 1) ?
"," :
"");
456 g_strlcat (out,
",\n\"arraySail\":\n[\n", maxLen);
458 for (
int i = 0; i < mat.
nLine ; i++) {
460 for (
int j = 0; j < mat.
nCol - 1; j++) {
461 snprintf (str,
sizeof str,
"%.0f, ", sailMat.
t [i][j]);
464 snprintf (str,
sizeof (str),
"%.0f]%s\n", sailMat.
t [i][mat.
nCol -1], (i < mat.
nLine - 1) ?
"," :
"");
470 g_strlcat (out,
"\"legend\": [", maxLen);
472 for (
size_t i = 0; i < mat.
nSail; i += 1) {
473 snprintf (str,
sizeof str,
"\"%s\"%s", mat.
tSail [i].
name, (i < mat.
nSail -1) ?
", " :
"");
481 g_strlcat (out,
",\n\"report\": \"", maxLen);
#define g_strlcat(dest, src, size)
static bool g_str_has_suffix(const char *s, const char *suffix)
Equivalent to Glib g_str_has_suffix.
static double findPolar(double twa, double w, const PolMat *mat, const PolMat *sailMat, int *sail)
find in polar boat speed or wave coeff
char * polToStrJson(bool report, const char *fileName, const char *objName, char *out, size_t maxLen)
write polar information in string Json format
void bestVmgBack(double tws, PolMat *mat, double *vmgAngle, double *vmgSpeed)
return VMG back: angle and speed at TWS: vent arriere
void bestVmg(double tws, PolMat *mat, double *vmgAngle, double *vmgSpeed)
return VMG: angle and speed at TWS: pres
static bool addSail(PolMat *polMat, int id, char *name, double max)
add a new sail in PoMat object
void wipeSpace(char *str)
wipe all spaces within str
static bool readPolarCsv(const char *fileName, PolMat *mat, char *errMessage, size_t maxLen)
read polar file and fill poLMat matrix if check then polarCheck
bool readPolar(const char *fileName, PolMat *mat, PolMat *sailPolMat, char *errMessage, size_t maxLen)
Launch readPolarCsv or readPolarJson according to type.
static char * findSailPol(char *str, PolMat *polMat, PolMat *sailPolMat, char *message, size_t maxLen)
update polMat and sailPolMat with new sail found in Json str
static bool readPolarJson(const char *fileName, PolMat *polMat, PolMat *sailPolMat, char *errMessage, size_t maxLen)
read polar in json format (eg.
static bool polarCheck(PolMat *mat, char *report, size_t maxLen)
Check polar and return false and a report if something to say.
char * polToStr(const PolMat *mat, char *str, size_t maxLen)
write polar information in string
static char * findListPol(bool isTws, int maxN, char *str, const char *startWith, PolMat *polMat, PolMat *sailPolMat, char *message, size_t maxLen)
update polMat and sailPolMat this tws ans twa lists found in Json str
static bool strtodNew(const char *str, double *v)
compilation: gcc -c polar.c
#define MAX_N_POL_MAT_COLS
#define MAX_N_POL_MAT_LINES
#define MAX_SIZE_FILE_NAME
bool isNumber(const char *name)
true if name contains a number
const size_t sailNameSize
sail attributes
char * buildRootName(const char *fileName, char *rootName, size_t maxLen)
Build root name if not already a root name.
PolMat polMat
polar matrix description
PolMat sailPolMat
polar matrix for sails
char * readTextFile(const char *fileName, char *errMessage, size_t maxLen)
read all text file in buffer.
char * newFileNameSuffix(const char *fileName, const char *suffix, char *newFileName, size_t maxLen)
replace former suffix (after last dot) by suffix example : "pol/bibi.toto.csv" with suffix "sailpol" ...
char jsonHeader[MAX_SIZE_JSON_HEADER]
struct PolMat::@9 tSail[MAX_N_SAIL]
double t[MAX_N_POL_MAT_LINES][MAX_N_POL_MAT_COLS]