You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
6.4 KiB
Ragel
217 lines
6.4 KiB
Ragel
|
|
#include "control_parser.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <sys/socket.h>
|
|
|
|
typedef control_parser_ctx context;
|
|
|
|
static void extract(context *ctx, char *fpc) {
|
|
gssize curpos = (fpc - ctx->buffer->str);
|
|
gssize len = curpos - ctx->mark;
|
|
g_string_truncate(ctx->tmp, 0);
|
|
g_string_append_len(ctx->tmp, ctx->buffer->str + ctx->mark, len);
|
|
ctx->mark = -1;
|
|
/* printf("Read chunk '%s'\n", ctx->tmp->str); */
|
|
}
|
|
|
|
static double extract_double(context *ctx, char *fpc) {
|
|
extract(ctx, fpc);
|
|
return strtod(ctx->tmp->str, NULL);
|
|
}
|
|
|
|
static timestamp extract_ts(context *ctx, char *fpc) {
|
|
extract(ctx, fpc);
|
|
return atoi(ctx->tmp->str);
|
|
}
|
|
|
|
%%{
|
|
|
|
machine control_parser;
|
|
variable cs ctx->cs;
|
|
|
|
action done {
|
|
t->alive = 0;
|
|
/* fprintf(stderr, "Run finished\n"); */
|
|
fbreak;
|
|
}
|
|
action mark { ctx->mark = fpc - ctx->buffer->str; }
|
|
action telemetrystart { ctx->tm = telemetry_new(); }
|
|
action telemetrystop {
|
|
g_queue_push_tail(&t->telemetry, ctx->tm);
|
|
if (!t->alive) {
|
|
t->vehicle.accel = ctx->tm->vehicle.accel;
|
|
t->vehicle.turn = ctx->tm->vehicle.turn;
|
|
gettimeofday(&t->started, NULL);
|
|
/* fprintf(stderr, "New run\n"); */
|
|
} else {
|
|
dgl(t, &t->sim.tm.vehicle, &t->sim.tm.vehicle, ctx->tm->ts - t->sim.tm.ts);
|
|
ctx->tm->vehicle.w = t->sim.tm.vehicle.w;
|
|
/* fprintf(stderr, "time difference [ms]: %i\n", getcurts(t) - ctx->tm->ts); */
|
|
fprintf(stderr, "Miss predict: dx=%f, dy=%f, ddir=%f, steps=%u\n",
|
|
t->sim.tm.vehicle.x - t->vehicle.x,
|
|
t->sim.tm.vehicle.y - t->vehicle.y,
|
|
t->sim.tm.vehicle.dir - t->vehicle.dir,
|
|
t->sim.steps);
|
|
}
|
|
/* Reset simulation */
|
|
t->sim.tm.ts = ctx->tm->ts;
|
|
t->sim.tm.vehicle = ctx->tm->vehicle;
|
|
g_array_set_size(t->sim.tm.objects, 0);
|
|
g_array_append_vals(t->sim.tm.objects, ctx->tm->objects->data, ctx->tm->objects->len);
|
|
t->sim.steps = 0;
|
|
|
|
t->last_ts = ctx->tm->ts;
|
|
ctx->tm = NULL;
|
|
t->alive = 1;
|
|
}
|
|
action vehicle {
|
|
ctx->tm->ts = ctx->ts;
|
|
ctx->tm->vehicle.x = ctx->x;
|
|
ctx->tm->vehicle.y = ctx->y;
|
|
ctx->tm->vehicle.dir = ctx->dir;
|
|
ctx->tm->vehicle.speed = ctx->speed;
|
|
t->vehicle.x = ctx->x;
|
|
t->vehicle.y = ctx->y;
|
|
t->vehicle.dir = ctx->dir;
|
|
t->vehicle.speed = ctx->speed;
|
|
/* printf("Vehicle at %f / %f\n", ctx->x, ctx->y); */
|
|
}
|
|
|
|
SP = " ";
|
|
|
|
double = '-'? (digit | '.')*;
|
|
|
|
dx = double >mark % { t->map.dx = extract_double(ctx, fpc); };
|
|
dy = double >mark % { t->map.dy = extract_double(ctx, fpc); };
|
|
min_sensor = double >mark % { t->map.min_sensor = extract_double(ctx, fpc); };
|
|
max_sensor = double >mark % { t->map.max_sensor = extract_double(ctx, fpc); };
|
|
max_speed = double >mark % { t->map.max_speed = extract_double(ctx, fpc); };
|
|
max_turn = double >mark % { t->map.max_turn = extract_double(ctx, fpc); };
|
|
max_hard_turn = double >mark % { t->map.max_hard_turn = extract_double(ctx, fpc); };
|
|
|
|
init = "I" SP dx SP dy SP double SP min_sensor SP max_sensor SP max_speed SP max_turn SP max_hard_turn SP ";";
|
|
|
|
x = double >mark % { ctx->x = extract_double(ctx, fpc); };
|
|
y = double >mark % { ctx->y = extract_double(ctx, fpc); };
|
|
r = double >mark % { ctx->r = extract_double(ctx, fpc); };
|
|
dir = double >mark % { ctx->dir = extract_double(ctx, fpc); };
|
|
speed = double >mark % { ctx->speed = extract_double(ctx, fpc); };
|
|
ctl = (
|
|
"a" @ { ctx->tm->vehicle.accel = ACCEL; }
|
|
| "-" @ { ctx->tm->vehicle.accel = ROLL; }
|
|
| "b" @ { ctx->tm->vehicle.accel = BRAKE; }
|
|
) (
|
|
"L" @ { ctx->tm->vehicle.turn = TURN_HARD_LEFT; }
|
|
| "l" @ { ctx->tm->vehicle.turn = TURN_LEFT; }
|
|
| "-" @ { ctx->tm->vehicle.turn = TURN_STRAIGHT; }
|
|
| "r" @ { ctx->tm->vehicle.turn = TURN_RIGHT; }
|
|
| "R" @ { ctx->tm->vehicle.turn = TURN_HARD_RIGHT; }
|
|
);
|
|
timestamp = (digit*) >mark % { ctx->ts = extract_ts(ctx, fpc); };
|
|
score = (digit*) >mark % { printf("Score %u\n", extract_ts(ctx, fpc)); };
|
|
|
|
boulder = "b" SP x SP y SP r SP % {
|
|
object *o = object_new(BOLDER, ctx->x, ctx->y, ctx->r, 0, 0);
|
|
/* g_array_append_vals(ctx->tm->objects, o, 1); */
|
|
g_hash_table_replace(t->map.solid_objects, o, o);
|
|
};
|
|
crater = "c" SP x SP y SP r SP % {
|
|
object *o = object_new(CRATER, ctx->x, ctx->y, ctx->r, 0, 0);
|
|
/* g_array_append_vals(ctx->tm->objects, o, 1); */
|
|
g_hash_table_replace(t->map.solid_objects, o, o);
|
|
};
|
|
homebase = "h" SP x SP y SP r SP; # ignore it
|
|
martian = "m" SP x SP y SP dir SP speed SP % {
|
|
object o = { MARTIAN, ctx->x, ctx->y, MARTIAN_RADIUS, ctx->dir, ctx->speed };
|
|
g_array_append_val(ctx->tm->objects, o);
|
|
};
|
|
object = boulder | crater | homebase | martian;
|
|
objects = object*;
|
|
telemetry = ( ("T" SP timestamp SP ctl SP x SP y SP dir SP speed SP) %vehicle objects) >telemetrystart ";" % telemetrystop;
|
|
|
|
# crash
|
|
Boulder = "B" SP timestamp SP ";";
|
|
# fell
|
|
Crater = "C" SP timestamp SP ";";
|
|
# killed by martian
|
|
Kill = "K" SP timestamp SP ";";
|
|
|
|
Success = "S" SP timestamp SP ";";
|
|
|
|
End = "E" SP timestamp SP score SP ";";
|
|
|
|
main := init? (telemetry | Boulder)* (Crater | Kill | Success)? End @ done;
|
|
}%%
|
|
|
|
%% write data;
|
|
|
|
static int control_parser_has_error(context *ctx) {
|
|
return ctx->cs == control_parser_error;
|
|
}
|
|
|
|
static int control_parser_is_finished(context *ctx) {
|
|
return ctx->cs >= control_parser_first_final;
|
|
}
|
|
|
|
void control_parser_new(trial *t) {
|
|
context *ctx = t->parse_ctx = g_slice_new(context);
|
|
%% write init;
|
|
ctx->buffer = g_string_sized_new(0);
|
|
ctx->tmp = g_string_sized_new(0);
|
|
ctx->mark = -1;
|
|
ctx->pos = 0;
|
|
}
|
|
|
|
void control_parser_reset(trial *t) {
|
|
context *ctx = t->parse_ctx;
|
|
%% write init;
|
|
g_string_truncate(ctx->tmp, 0);
|
|
ctx->mark = -1;
|
|
/* fprintf(stderr, "Parser reset\n"); */
|
|
}
|
|
|
|
void control_parser_free(trial *t) {
|
|
g_string_free(t->parse_ctx->buffer, TRUE);
|
|
g_string_free(t->parse_ctx->tmp, TRUE);
|
|
g_slice_free(context, t->parse_ctx);
|
|
}
|
|
|
|
run_t control_parse(trial *t) {
|
|
context *ctx = t->parse_ctx;
|
|
gsize wehave;
|
|
|
|
if (0 < (wehave = ctx->buffer->len - ctx->pos)) {
|
|
char *p, *pe;
|
|
|
|
p = ctx->buffer->str + ctx->pos;
|
|
pe = p + wehave;
|
|
/* fprintf(stderr, "Parsing '%s' (len=%zu)\n", p, wehave); */
|
|
|
|
%% write exec;
|
|
|
|
ctx->pos = p - ctx->buffer->str;
|
|
if (ctx->mark == -1) {
|
|
g_string_erase(ctx->buffer, 0, ctx->pos);
|
|
ctx->pos = 0;
|
|
} else if (ctx->mark) {
|
|
g_string_erase(ctx->buffer, 0, ctx->mark);
|
|
ctx->pos -= ctx->mark;
|
|
ctx->mark = 0;
|
|
}
|
|
} else {
|
|
fprintf(stderr, "No data to parse\n");
|
|
}
|
|
|
|
if (control_parser_has_error(ctx)) {
|
|
fprintf(stderr, "Parse error: '%s'\n", ctx->buffer->str + ctx->pos);
|
|
shutdown(t->socket, SHUT_RDWR);
|
|
close(t->socket);
|
|
exit(126);
|
|
return RUN_ERROR;
|
|
}
|
|
if (control_parser_is_finished(ctx)) return RUN_DONE;
|
|
return RUN_GO_ON;
|
|
}
|