flight
This commit is contained in:
parent
a1896b97fc
commit
1bba902145
|
@ -36,6 +36,10 @@ int main(void) {
|
|||
if(!freopen(intent, "w", stdout)) goto catch;
|
||||
scan_glider_graph(&scn);
|
||||
|
||||
intent = "derived/flight.gnu";
|
||||
if(!freopen(intent, "w", stdout)) goto catch;
|
||||
scan_flight_graph(&scn);
|
||||
|
||||
intent = 0;
|
||||
goto finally;
|
||||
catch:
|
||||
|
|
15
src/scan.h
15
src/scan.h
|
@ -51,6 +51,19 @@ struct glider {
|
|||
#include "../src/tree.h"
|
||||
|
||||
|
||||
/* Flight array. */
|
||||
struct flight {
|
||||
struct pair type, reg, launch, landing, pilot, copilot;
|
||||
unsigned dual_min, pilot_min, ifrsim_min, ifr_min;
|
||||
struct pair remarks;
|
||||
};
|
||||
#define TREE_NAME flight
|
||||
#define TREE_KEY union line64
|
||||
#define TREE_VALUE struct flight
|
||||
#define TREE_HEAD
|
||||
#include "../src/tree.h"
|
||||
|
||||
|
||||
struct scan {
|
||||
struct {
|
||||
struct source_array array;
|
||||
|
@ -63,9 +76,11 @@ struct scan {
|
|||
struct linemap_tree dates;
|
||||
} scores;
|
||||
struct glider_tree gliders;
|
||||
struct flight_tree flights;
|
||||
};
|
||||
|
||||
void scan_(struct scan *);
|
||||
struct scan scan(struct journal *);
|
||||
void scan_score_graph(struct scan *);
|
||||
void scan_glider_graph(struct scan *);
|
||||
void scan_flight_graph(struct scan *);
|
||||
|
|
181
src/scan.re.c
181
src/scan.re.c
|
@ -66,6 +66,19 @@ static int glider_compare(const union line64 a, const union line64 b)
|
|||
#include "../src/tree.h"
|
||||
|
||||
|
||||
/* Flight tree. */
|
||||
static void flight_to_string(const union line64 line, const struct flight *f,
|
||||
char (*const a)[12]) { (void)f; date32_to_string(line.date, a); }
|
||||
static int flight_compare(const union line64 a, const union line64 b)
|
||||
{ return a.u64 > b.u64; }
|
||||
#define TREE_NAME flight
|
||||
#define TREE_KEY union line64
|
||||
#define TREE_VALUE struct flight
|
||||
#define TREE_COMPARE
|
||||
#define TREE_TO_STRING
|
||||
#define TREE_BODY
|
||||
#include "../src/tree.h"
|
||||
|
||||
|
||||
/*!conditions:re2c*/
|
||||
|
||||
|
@ -78,6 +91,7 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||
const char *fail = "perhaps a bat?";
|
||||
struct score *new_score = 0;
|
||||
struct glider *new_glider = 0;
|
||||
struct flight *new_flight = 0;
|
||||
assert(scan && date.u32 && buffer);
|
||||
YYCURSOR = YYMARKER = yyt1 = buffer;
|
||||
/*!re2c /**/
|
||||
|
@ -109,6 +123,7 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||
<line> "--" / [^-] :=> source
|
||||
<line> "::" / [^:] :=> score
|
||||
<line> "[glider]" :=> glider_type
|
||||
<line> "[flight]" :=> flight_type
|
||||
|
||||
|
||||
<source> * { fail = "source unrecognized"; goto catch; }
|
||||
|
@ -219,8 +234,7 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||
eg, [glider] 2-33A; C-GCLK; CYQQ; A; 2000'; CYQQ; ;:13;; Peters D1 */
|
||||
<glider_type> * { fail = "glider type"; goto catch; }
|
||||
<glider_type> ws* @s0 semitext+ @s1 ws* ";" => glider_reg {
|
||||
const union line64 key
|
||||
= {{ (uint32_t)line, {{ date.day, date.month, date.year }} }};
|
||||
const union line64 key = {{ (uint32_t)line, date }};
|
||||
assert(!new_glider);
|
||||
if(line > UINT32_MAX) { fail = "line overflow"; goto catch; }
|
||||
switch(glider_tree_bulk_assign(&scan->gliders, key, &new_glider)) {
|
||||
|
@ -234,8 +248,15 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||
<glider_reg> ws* @s0 semitext+ @s1 ws* ";" => glider_launch
|
||||
{ new_glider->reg.a = s0, new_glider->reg.b = s1; continue; }
|
||||
<glider_launch> * { fail = "glider launch"; goto catch; }
|
||||
<glider_launch> ws* @s0 airport @s1 ws* ";" => glider_how
|
||||
{ new_glider->launch.a = s0, new_glider->launch.b = s1; continue; }
|
||||
<glider_launch> ws* @s0 airport @s1 ws* ";" => glider_how {
|
||||
new_glider->launch.a = s0, new_glider->launch.b = s1;
|
||||
date32_to_string(date, &datestr);
|
||||
fprintf(stderr, "%s: glider <%.*s> at <%.*s>\n", datestr,
|
||||
(int)(new_glider->reg.b - new_glider->reg.a),
|
||||
new_glider->reg.a,
|
||||
(int)(s1 - s0), s0);
|
||||
continue;
|
||||
}
|
||||
<glider_how> * { fail = "glider how"; goto catch; }
|
||||
<glider_how> ws* @s0 [MWA] ws* ";" => glider_height {
|
||||
switch(*s0) {
|
||||
|
@ -250,27 +271,27 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||
{ if(!pair_to_natural(s0, s1, &new_glider->height_ft)); continue; }
|
||||
<glider_landing> * { fail = "glider landing"; goto catch; }
|
||||
<glider_landing> ws* @s0 airport @s1 ws* ";" => glider_pilot
|
||||
{ new_glider->landing.a = s0, new_glider->landing.b = s1; continue; }
|
||||
<glider_pilot> * { fail = "glider pilot"; goto catch; }
|
||||
{ new_glider->landing.a = s0, new_glider->landing.b = s1; continue;}
|
||||
<glider_pilot> * { fail = "glider pilot time"; goto catch; }
|
||||
<glider_pilot> ws* ";" => glider_dual /* not PIC */
|
||||
{ new_glider->pilot_min = 0; continue; }
|
||||
<glider_pilot> ws* @s0 natural? @s1 ":" @t0 minutes @t1 ws* ";"
|
||||
=> glider_dual { if(!pair_colon_to_minutes(s0, s1, t0, t1,
|
||||
&new_glider->pilot_min)) { fail = "pilot time"; goto catch; }
|
||||
&new_glider->pilot_min)) { fail = "glider pilot time"; goto catch; }
|
||||
continue; }
|
||||
<glider_dual> * { fail = "glider dual"; goto catch; }
|
||||
<glider_dual> * { fail = "glider dual time"; goto catch; }
|
||||
<glider_dual> ws* ";" => glider_instr
|
||||
{ new_glider->dual_min = 0; continue; }
|
||||
<glider_dual> ws* @s0 natural? @s1 ":" @t0 minutes @t1 ws* ";"
|
||||
=> glider_instr { if(!pair_colon_to_minutes(s0, s1, t0, t1,
|
||||
&new_glider->dual_min)) { fail = "dual time"; goto catch; }
|
||||
&new_glider->dual_min)) { fail = "glider dual time"; goto catch; }
|
||||
continue; }
|
||||
<glider_instr> * { fail = "glider instr"; goto catch; }
|
||||
<glider_instr> * { fail = "glider instr time"; goto catch; }
|
||||
<glider_instr> ws* ";" => glider_remarks
|
||||
{ new_glider->instr_min = 0; continue; }
|
||||
<glider_instr> ws* @s0 natural? @s1 ":" @t0 minutes @t1 ws* ";"
|
||||
=> glider_remarks { if(!pair_hours_to_minutes(s0, s1, t0, t1,
|
||||
&new_glider->instr_min)) { fail = "instr time"; goto catch; }
|
||||
&new_glider->instr_min)) { fail = "glider instr time"; goto catch; }
|
||||
continue; }
|
||||
<glider_remarks> * { fail = "glider remarks"; goto catch; }
|
||||
<glider_remarks> ws* "\n" => line
|
||||
|
@ -280,6 +301,84 @@ static int scan_day(struct scan *const scan, union date32 date,
|
|||
{ new_glider->remarks.a = s0, new_glider->remarks.b = s1;
|
||||
new_glider = 0; line++; continue; }
|
||||
|
||||
|
||||
/* type; registration; launch -- landing; pic; sic;
|
||||
single engine day dual; pilot; instrument simulated; actual; remarks */
|
||||
<flight_type> * { fail = "flight type"; goto catch; }
|
||||
<flight_type> ws* @s0 semitext+ @s1 ws* ";" => flight_reg {
|
||||
const union line64 key
|
||||
= {{ (uint32_t)line, {{ date.day, date.month, date.year }} }};
|
||||
assert(!new_flight);
|
||||
if(line > UINT32_MAX) { fail = "line overflow"; goto catch; }
|
||||
switch(flight_tree_bulk_assign(&scan->flights, key, &new_flight)) {
|
||||
case TREE_PRESENT: fail = "duplicate key";
|
||||
case TREE_ERROR: goto catch;
|
||||
case TREE_ABSENT: break;
|
||||
}
|
||||
new_flight->type.a = s0, new_flight->type.b = s1;
|
||||
continue;
|
||||
}
|
||||
<flight_reg> * { fail = "flight reg"; goto catch; }
|
||||
<flight_reg> ws* @s0 semitext+ @s1 ws* ";" => flight_airports
|
||||
{ new_flight->reg.a = s0, new_flight->reg.b = s1; continue; }
|
||||
<flight_airports> * { fail = "flight airports"; goto catch; }
|
||||
<flight_airports> ws* @s0 airport @s1 ws* "--"
|
||||
ws* @t0 airport @t1 ws* ";" => flight_pic {
|
||||
new_flight->launch.a = s0, new_flight->launch.b = s1;
|
||||
new_flight->landing.a = t0, new_flight->landing.b = t1;
|
||||
date32_to_string(date, &datestr);
|
||||
fprintf(stderr, "%s: flight <%.*s> at <%.*s>\n", datestr,
|
||||
(int)(new_flight->reg.b - new_flight->reg.a),
|
||||
new_flight->reg.a,
|
||||
(int)(s1 - s0), s0);
|
||||
continue;
|
||||
}
|
||||
<flight_pic> * { fail = "flight pic"; goto catch; }
|
||||
<flight_pic> ws* @s0 semitext+ (ws+ semitext+)* @s1 /* ws*? */";"
|
||||
=> flight_sic
|
||||
{ new_flight->pilot.a = s0, new_flight->pilot.b = s1; continue; }
|
||||
<flight_sic> * { fail = "flight sic"; goto catch; }
|
||||
<flight_sic> ws* ";" => flight_dual
|
||||
{ new_flight->copilot.a = new_flight->copilot.b = 0; continue; }
|
||||
<flight_sic> ws* @s0 semitext+ (ws+ semitext+)* @s1 ";"
|
||||
=> flight_dual
|
||||
{ new_flight->copilot.a = s0, new_flight->copilot.b = s1; continue; }
|
||||
<flight_dual> * { fail = "flight dual time"; goto catch; }
|
||||
<flight_dual> ws* ";" => flight_pilot
|
||||
{ new_flight->dual_min = 0; continue; }
|
||||
<flight_dual> ws* @s0 zero_natural? @s1 "." @t0 [0-9] @t1 "h" ws* ";"
|
||||
=> flight_pilot { if(!pair_hours_to_minutes(s0, s1, t0, t1,
|
||||
&new_flight->dual_min)) { fail = "flight dual time"; goto catch; }
|
||||
continue; }
|
||||
<flight_pilot> * { fail = "flight pilot time"; goto catch; }
|
||||
<flight_pilot> ws* ";" => flight_ifrsim
|
||||
{ new_flight->pilot_min = 0; continue; }
|
||||
<flight_pilot> ws* @s0 zero_natural? @s1 "." @t0 [0-9] @t1 "h" ws* ";"
|
||||
=> flight_ifrsim { if(!pair_hours_to_minutes(s0, s1, t0, t1,
|
||||
&new_flight->pilot_min)) { fail = "flight pilot time";
|
||||
goto catch; } continue; }
|
||||
<flight_ifrsim> * { fail = "flight simulated ifr time"; goto catch; }
|
||||
<flight_ifrsim> ws* ";" => flight_ifr
|
||||
{ new_flight->ifrsim_min = 0; continue; }
|
||||
<flight_ifrsim> ws* @s0 zero_natural? @s1 "." @t0 [0-9] @t1 "h" ws* ";"
|
||||
=> flight_ifr { if(!pair_hours_to_minutes(s0, s1, t0, t1,
|
||||
&new_flight->ifrsim_min)) { fail = "flight simulated ifr time";
|
||||
goto catch; } continue; }
|
||||
<flight_ifr> * { fail = "flight ifr time"; goto catch; }
|
||||
<flight_ifr> ws* ";" => flight_remarks
|
||||
{ new_flight->ifr_min = 0; continue; }
|
||||
<flight_ifr> ws* @s0 zero_natural? @s1 "." @t0 [0-9] @t1 "h" ws* ";"
|
||||
=> flight_remarks { if(!pair_hours_to_minutes(s0, s1, t0, t1,
|
||||
&new_flight->ifr_min)) { fail = "flight ifr time"; goto catch; }
|
||||
continue; }
|
||||
<flight_remarks> * { fail = "flight remarks"; goto catch; }
|
||||
<flight_remarks> ws* "\n" => line
|
||||
{ new_flight->remarks.a = new_flight->remarks.b = 0;
|
||||
new_flight = 0; line++; continue; }
|
||||
<flight_remarks> ws* @s0 glyph+ (ws+ glyph+)* @s1 "\n" => line
|
||||
{ new_flight->remarks.a = s0, new_flight->remarks.b = s1;
|
||||
new_flight = 0; line++; continue; }
|
||||
|
||||
*/ }
|
||||
assert(0); /* Never gets here. */
|
||||
catch:
|
||||
|
@ -323,7 +422,9 @@ struct scan scan(struct journal *const jrnl) {
|
|||
|
||||
/* Scans make trees bulk-loaded; fix to real tree. */
|
||||
if(!linemap_tree_bulk_finish(&scan.sources.dates)
|
||||
|| !linemap_tree_bulk_finish(&scan.scores.dates)) goto catch;
|
||||
|| !linemap_tree_bulk_finish(&scan.scores.dates)
|
||||
|| !glider_tree_bulk_finish(&scan.gliders)
|
||||
|| !flight_tree_bulk_finish(&scan.flights)) goto catch;
|
||||
|
||||
fprintf(stderr, "List of scores: %s.\n"
|
||||
"Mapped to indices: %s.\n"
|
||||
|
@ -495,3 +596,59 @@ void scan_glider_graph(struct scan *const scan) {
|
|||
/*"#set style fill solid 0.1 #pattern 5 (better, but restarts)\n"
|
||||
"plot $Data using 1:($6/60) with fillsteps lw 2\n"*/);
|
||||
}
|
||||
|
||||
void scan_flight_graph(struct scan *const scan) {
|
||||
assert(scan);
|
||||
fprintf(stderr, "Flight: %s.\n", flight_tree_to_string(&scan->flights));
|
||||
printf("set terminal pngcairo dashed transparent truecolor"
|
||||
" size 840, 480 fontscale 1\n"
|
||||
"set output \"glider.png\"\n");
|
||||
printf("$Data <<EOD\n"
|
||||
"# date, reg, sic, pic, source\n");
|
||||
struct flight_tree_iterator it = flight_tree_iterator(&scan->flights);
|
||||
while(flight_tree_next(&it)) {
|
||||
const union line64 line = flight_tree_key(&it);
|
||||
const struct flight *flight = flight_tree_value(&it);
|
||||
char datestr[12];
|
||||
date32_to_string(line.date, &datestr);
|
||||
const struct source *src = source_lookup(scan, line);
|
||||
assert(src);
|
||||
if(!src->name.a) { fprintf(stderr,
|
||||
"Source has no source at %s; ignoring.\n", datestr); continue; }
|
||||
printf("%s, ", datestr);
|
||||
printf("%.*s, %" PRIu32 ", %" PRIu32,
|
||||
(int)(flight->reg.b - flight->reg.a), flight->reg.a,
|
||||
flight->dual_min, flight->pilot_min);
|
||||
printf(", %.*s\n", (int)(src->name.b - src->name.a), src->name.a);
|
||||
}
|
||||
printf("EOD\n"
|
||||
"# theozh https://stackoverflow.com/a/75466214/2472827\n"
|
||||
"# get a unique list from datablock\n"
|
||||
"addToList(list,col) = list.( strstrt(list,'\"'.strcol(col).'\"') \\\n"
|
||||
" > 0 ? '' : ' \"'.strcol(col).'\"')\n"
|
||||
"Uniqs = ''\n"
|
||||
"stats $Data u (Uniqs=addToList(Uniqs,2)) nooutput\n"
|
||||
"Uniq(i) = word(Uniqs,i)\n"
|
||||
"getIndex(s) = sum [_i=1:words(Uniqs)] s eq word(Uniqs,_i) ? _i : 0\n"
|
||||
"\n"
|
||||
"stats $Data u 3 nooutput\n"
|
||||
"sicsum = STATS_sum\n"
|
||||
"stats $Data u 4 nooutput\n"
|
||||
"picsum = STATS_sum\n"
|
||||
"\n"
|
||||
"myTimeFmt = \"%%Y-%%m-%%d\"\n"
|
||||
"set format x myTimeFmt timedate\n"
|
||||
"set xtics format myTimeFmt rotate by -30\n"
|
||||
"set format y \"%%tH:%%tM\" timedate\n"
|
||||
"set grid\n"
|
||||
"set key out reverse Left noautotitle\n"
|
||||
"set style fill solid 0.5\n"
|
||||
"unset border\n"
|
||||
"plot total=0 $Data u"
|
||||
" (timecolumn(1,myTimeFmt)):(dy=($3+$4)*60,total=total+dy)"
|
||||
" w steps lc \"black\" dt 3, \\\n"
|
||||
" total=0 '' u (timecolumn(1,myTimeFmt)):"
|
||||
"(dy=($3+$4)*60,total=total+dy,total/2.): \\\n"
|
||||
" (43200):(total/2.):(getIndex(strcol(2))) w boxxy lc var, \\\n"
|
||||
" for [i=1:words(Uniqs)] keyentry w boxxy lc i ti Uniq(i)\n");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue