Machine is working, working on task1
This commit is contained in:
parent
b51da57b7b
commit
db63517f57
@ -37,8 +37,8 @@ ADD_EXECUTABLE(ovmjit
|
||||
|
||||
ADD_EXECUTABLE(task1
|
||||
bin1.c
|
||||
task.c
|
||||
task1.c
|
||||
task.c trace.c
|
||||
)
|
||||
|
||||
SET(WARN_FLAGS "-g -O2 -g2 -Wall -Wmissing-declarations -Wdeclaration-after-statement -Wcast-align -Wsign-compare -Wnested-externs -Wpointer-arith -Wl,--as-needed")
|
||||
|
52
ovm/ovm.c
52
ovm/ovm.c
@ -2,6 +2,8 @@
|
||||
#include "ovm.h"
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#undef CMPEPS
|
||||
|
||||
void ovm_free(ovm_t *ovm) {
|
||||
if (!ovm) return;
|
||||
g_slice_free1(ovm->limit * sizeof(instruction_t), ovm->instructions);
|
||||
@ -23,7 +25,7 @@ ovm_t* ovm_load(const gchar *filename) {
|
||||
ovm->values = g_slice_alloc0(ovm->limit * sizeof(gdouble));
|
||||
|
||||
if (!g_file_get_contents(filename, &buf, &len, &err)) {
|
||||
fprintf (stderr, "Unable to read file: %s\n", err->message);
|
||||
fprintf (stderr, "Unable to read file %s: %s\n", filename, err->message);
|
||||
g_error_free (err);
|
||||
exit(1);
|
||||
}
|
||||
@ -50,7 +52,7 @@ ovm_t* ovm_load(const gchar *filename) {
|
||||
}
|
||||
|
||||
void ovm_print_c(ovm_t *ovm, const gchar *filename) {
|
||||
guint i;
|
||||
guint i, max_in=0, max_out=0;
|
||||
instruction_t *oi = ovm->instructions;
|
||||
gdouble *vi = ovm->values;
|
||||
guint64 *uvi = (guint64*) ovm->values;
|
||||
@ -64,9 +66,11 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) {
|
||||
}
|
||||
|
||||
g_string_append_len(buf, CONST_STR_LEN(
|
||||
"void ovm_step(gdouble scenario, gdouble *in, gdouble *out) {\n"
|
||||
"void ovm_step(guint scenario, gdouble *in, gdouble *out) {\n"
|
||||
));
|
||||
#define USED(i) (usedv[i] = TRUE, i)
|
||||
#define USED_IN(i) (max_in = max_in > i ? max_in : i, i)
|
||||
#define USED_OUT(i) (max_out = max_out > i ? max_out : i, i)
|
||||
for (i = 0; i < ovm->used; i++) {
|
||||
g_string_printf(str, "\t/* Invalid command: 0x%X */\n", (guint) oi[i]);
|
||||
switch (instr_dop(oi[i])) {
|
||||
@ -78,6 +82,7 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) {
|
||||
break;
|
||||
case SOP_CMPZ:
|
||||
switch (instr_sop_cmp(oi[i])) {
|
||||
#if CMPEPS /* cmp with eps */
|
||||
case CMP_LTZ:
|
||||
g_string_printf(str, "\tovm_status = (v%u.d < -eps);\n", USED(instr_sop_r1(oi[i])));
|
||||
break;
|
||||
@ -88,11 +93,28 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) {
|
||||
g_string_printf(str, "\tovm_status = (fabs(v%u.d) <= eps);\n", USED(instr_sop_r1(oi[i])));
|
||||
break;
|
||||
case CMP_GEZ:
|
||||
g_string_printf(str, "\tovm_status = (v%u.d > eps);\n", USED(instr_sop_r1(oi[i])));
|
||||
break;
|
||||
case CMP_GTZ:
|
||||
g_string_printf(str, "\tovm_status = (v%u.d >= -eps);\n", USED(instr_sop_r1(oi[i])));
|
||||
break;
|
||||
case CMP_GTZ:
|
||||
g_string_printf(str, "\tovm_status = (v%u.d > eps);\n", USED(instr_sop_r1(oi[i])));
|
||||
break;
|
||||
#else
|
||||
case CMP_LTZ:
|
||||
g_string_printf(str, "\tovm_status = (v%u.d < 0);\n", USED(instr_sop_r1(oi[i])));
|
||||
break;
|
||||
case CMP_LEZ:
|
||||
g_string_printf(str, "\tovm_status = (v%u.d <= 0);\n", USED(instr_sop_r1(oi[i])));
|
||||
break;
|
||||
case CMP_EQZ:
|
||||
g_string_printf(str, "\tovm_status = (v%u.d == 0);\n", USED(instr_sop_r1(oi[i])));
|
||||
break;
|
||||
case CMP_GEZ:
|
||||
g_string_printf(str, "\tovm_status = (v%u.d >= 0);\n", USED(instr_sop_r1(oi[i])));
|
||||
break;
|
||||
case CMP_GTZ:
|
||||
g_string_printf(str, "\tovm_status = (v%u.d > 0);\n", USED(instr_sop_r1(oi[i])));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case SOP_SQRT:
|
||||
@ -105,7 +127,7 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) {
|
||||
if (0x3e80 == instr_sop_r1(oi[i])) {
|
||||
g_string_printf(str, "\tv%u.d = scenario;\n", USED(i));
|
||||
} else {
|
||||
g_string_printf(str, "\tv%u.d = in[%u];\n", USED(i), instr_sop_r1(oi[i]));
|
||||
g_string_printf(str, "\tv%u.d = in[%u];\n", USED(i), USED_IN(instr_sop_r1(oi[i])));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -120,10 +142,14 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) {
|
||||
g_string_printf(str, "\tv%u.d = v%u.d * v%u.d;\n", USED(i), USED(instr_dop_r1(oi[i])), USED(instr_dop_r2(oi[i])));
|
||||
break;
|
||||
case OP_DIV:
|
||||
#if CMPEPS
|
||||
g_string_printf(str, "\tv%u.d = (fabs(v%u.d) < eps) ? 0.0 : v%u.d / v%u.d;\n", USED(i), USED(instr_dop_r2(oi[i])), USED(instr_dop_r1(oi[i])), instr_dop_r2(oi[i]));
|
||||
#else
|
||||
g_string_printf(str, "\tv%u.d = (v%u.d == 0) ? 0.0 : v%u.d / v%u.d;\n", USED(i), USED(instr_dop_r2(oi[i])), USED(instr_dop_r1(oi[i])), instr_dop_r2(oi[i]));
|
||||
#endif
|
||||
break;
|
||||
case OP_OUT:
|
||||
g_string_printf(str, "\tout[%u] = v%u.d;\n", instr_dop_r1(oi[i]), USED(instr_dop_r2(oi[i])));
|
||||
g_string_printf(str, "\tout[%u] = v%u.d;\n", USED_OUT(instr_dop_r1(oi[i])), USED(instr_dop_r2(oi[i])));
|
||||
break;
|
||||
case OP_PHI:
|
||||
g_string_printf(str, "\tv%u.d = ovm_status ? v%u.d : v%u.d;\n", USED(i), USED(instr_dop_r1(oi[i])), USED(instr_dop_r2(oi[i])));
|
||||
@ -145,8 +171,18 @@ void ovm_print_c(ovm_t *ovm, const gchar *filename) {
|
||||
"typedef union { gdouble d; guint64 i; } double_int;\n"
|
||||
"\n"
|
||||
"static gboolean ovm_status;\n"
|
||||
"\n"
|
||||
));
|
||||
#if CMPEPS
|
||||
write(f, CONST_STR_LEN(
|
||||
"static const gdouble eps = 1e-300;\n"
|
||||
"\n"
|
||||
));
|
||||
#endif
|
||||
g_string_printf(str, "const guint ovm_outs = %u, ovm_ins = %u;\n", max_out+1, max_in+1);
|
||||
write(f, GSTR_LEN(str));
|
||||
write(f, CONST_STR_LEN(
|
||||
"\n"
|
||||
"static double_int v0"
|
||||
));
|
||||
for (i = 1; i < ovm->used; i++) {
|
||||
|
@ -45,7 +45,7 @@ static inline guint instr_dop_r2(instruction_t i) {
|
||||
}
|
||||
|
||||
static inline cmp_t instr_sop_cmp(instruction_t i) {
|
||||
return (i >> 20) & 0xF;
|
||||
return (i >> 21) & 0x7;
|
||||
}
|
||||
|
||||
static inline guint instr_sop_r1(instruction_t i) {
|
||||
|
13
ovm/physics.h
Normal file
13
ovm/physics.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef OVM_PHYSICS_H
|
||||
#define OVM_PHYSICS_H
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define G 6.67428e-11
|
||||
#define Me 6.0e24
|
||||
#define Re 6.357e6
|
||||
|
||||
|
||||
#endif
|
64
ovm/task.c
64
ovm/task.c
@ -1,20 +1,78 @@
|
||||
|
||||
#include "task.h"
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
void task_free(task_t *task) {
|
||||
if (!task) return;
|
||||
g_slice_free1(task->in_size * sizeof(gdouble), task->in_old);
|
||||
g_slice_free1(task->in_size * sizeof(gdouble), task->in);
|
||||
g_slice_free1(task->out_size * sizeof(gdouble), task->out);
|
||||
g_slice_free(task_t, task);
|
||||
}
|
||||
|
||||
task_t* task_new(gdouble scenario, guint in_size, guint out_size) {
|
||||
task_t* task_new(guint scenario) {
|
||||
task_t *task = g_slice_new(task_t);
|
||||
task->scenario = scenario;
|
||||
task->timestamp = 0;
|
||||
task->in_size = in_size;
|
||||
task->out_size = out_size;
|
||||
task->in_size = ovm_ins;
|
||||
task->out_size = ovm_outs;
|
||||
task->in = g_slice_alloc0(task->in_size * sizeof(gdouble));
|
||||
task->in_old = g_slice_alloc0(task->in_size * sizeof(gdouble));
|
||||
task->out = g_slice_alloc0(task->out_size * sizeof(gdouble));
|
||||
return task;
|
||||
}
|
||||
|
||||
void task_trace_start(task_t *task, const gchar *tracefile) {
|
||||
guint32 buf[3];
|
||||
task->tracefd = g_open(tracefile, O_CREAT | O_TRUNC | O_WRONLY, 0644);
|
||||
|
||||
if (-1 == task->tracefd) {
|
||||
fprintf(stderr, "Couldn't open file %s: %s\n", tracefile, g_strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
buf[0] = 0xCAFEBABE;
|
||||
buf[1] = 439;
|
||||
buf[2] = (guint32) task->scenario;
|
||||
write(task->tracefd, buf, 12);
|
||||
}
|
||||
|
||||
void task_trace_end(task_t *task) {
|
||||
guint32 buf[2];
|
||||
buf[0] = task->timestamp;
|
||||
buf[1] = 0;
|
||||
write(task->tracefd, buf, 8);
|
||||
}
|
||||
|
||||
void task_trace_step(task_t *task) {
|
||||
gboolean ch2 = task->in_old[2] != task->in[2], ch3 = task->in_old[3] != task->in[3];
|
||||
if ((0 == task->timestamp) || ch2 || ch3) {
|
||||
guint32 buf[2+3*3], *cur = buf;
|
||||
buf[0] = task->timestamp;
|
||||
buf[1] = 0;
|
||||
cur = &buf[2];
|
||||
|
||||
if (ch2) {
|
||||
buf[1]++;
|
||||
*cur++ = 2;
|
||||
memcpy(cur, &task->in[2], sizeof(gdouble));
|
||||
task->in_old[2] = task->in[2];
|
||||
cur += 2;
|
||||
}
|
||||
if (ch3) {
|
||||
buf[1]++;
|
||||
*cur++ = 3;
|
||||
memcpy(cur, &task->in[3], sizeof(gdouble));
|
||||
task->in_old[3] = task->in[3];
|
||||
cur += 2;
|
||||
}
|
||||
if (0 == task->timestamp) {
|
||||
gdouble s = task->scenario;
|
||||
buf[1]++;
|
||||
*cur++ = 0x3e80;
|
||||
memcpy(cur, &s, sizeof(gdouble));
|
||||
cur += 2;
|
||||
}
|
||||
write(task->tracefd, buf, (cur-buf)*4);
|
||||
}
|
||||
}
|
||||
|
25
ovm/task.h
25
ovm/task.h
@ -4,27 +4,22 @@
|
||||
#include "base.h"
|
||||
|
||||
typedef struct {
|
||||
gdouble scenario;
|
||||
guint scenario;
|
||||
guint64 timestamp;
|
||||
guint in_size, out_size;
|
||||
gdouble *in, *out;
|
||||
gdouble *in, *out, *in_old;
|
||||
int tracefd;
|
||||
} task_t;
|
||||
|
||||
typedef void (*task_app_t)(task_t *task);
|
||||
|
||||
task_t* task_new(gdouble scenario, guint in_size, guint out_size);
|
||||
task_t* task_new(guint scenario);
|
||||
void task_free(task_t *task);
|
||||
|
||||
void ovm_init();
|
||||
void ovm_step(gdouble scenario, gdouble *in, gdouble *out);
|
||||
void task_trace_start(task_t *task, const gchar *tracefile);
|
||||
void task_trace_end(task_t *task);
|
||||
void task_trace_step(task_t *task);
|
||||
|
||||
static inline gdouble task_run(task_t *task, task_app_t app) {
|
||||
ovm_init();
|
||||
for ( ; task->out[0] == 0.0 && task->timestamp < 3000000; task->timestamp++) {
|
||||
app(task);
|
||||
ovm_step(task->scenario, task->in, task->out);
|
||||
}
|
||||
return task->out[0];
|
||||
}
|
||||
void ovm_init();
|
||||
void ovm_step(guint scenario, gdouble *in, gdouble *out);
|
||||
extern const guint ovm_outs, ovm_ins;
|
||||
|
||||
#endif
|
83
ovm/task1.c
83
ovm/task1.c
@ -1,26 +1,81 @@
|
||||
|
||||
#include "task.h"
|
||||
#include "task_main.h"
|
||||
#include "physics.h"
|
||||
|
||||
/*
|
||||
Output Ports:
|
||||
Address Sensor
|
||||
0x0 Score
|
||||
0x1 Fuel Remaining
|
||||
0x2 s_x Relative to Earth
|
||||
0x3 s_y Relative to Earth
|
||||
0x4 Target Orbit Radius
|
||||
*/
|
||||
|
||||
#define SCORE (task->out[0])
|
||||
#define FUEL (task->out[1])
|
||||
#define S_X (task->out[2])
|
||||
#define S_Y (task->out[3])
|
||||
#define RADIUS (task->out[4])
|
||||
|
||||
#define DV_X (task->in[2])
|
||||
#define DV_Y (task->in[3])
|
||||
|
||||
static const gdouble mu = G * Me;
|
||||
|
||||
static void debug(task_t * task) {
|
||||
gdouble *o = task->out;
|
||||
gdouble rad = sqrt(S_X*S_X+S_Y*S_Y);
|
||||
printf(
|
||||
"Step: %9"G_GUINT64_FORMAT" Score: %5f Fuel: %5f x: %5f y: %5f r: %5f\n",
|
||||
task->timestamp, o[0], o[1], o[2], o[3], o[4]);
|
||||
"Step: %9"G_GUINT64_FORMAT" Score: %5f Fuel: %5f x: %5f y: %5f r: %5f (cur: %5f)\n",
|
||||
task->timestamp, SCORE, FUEL, S_X, S_Y, RADIUS, rad);
|
||||
}
|
||||
|
||||
static void run(task_t *task) {
|
||||
gdouble init_rad, last_x, last_y;
|
||||
gboolean running = FALSE, started = FALSE;
|
||||
gdouble dv, dv_tic;
|
||||
|
||||
static void run(task_t *task, gpointer userdata) {
|
||||
gdouble cur_rad;
|
||||
UNUSED(userdata);
|
||||
|
||||
if (0 == task->timestamp) return;
|
||||
|
||||
cur_rad = sqrt(S_X*S_X+S_Y*S_Y);
|
||||
DV_X = DV_Y = 0.0;
|
||||
|
||||
if (!running) {
|
||||
running = TRUE;
|
||||
started = TRUE;
|
||||
init_rad = cur_rad;
|
||||
dv = sqrt(mu/init_rad)*(sqrt(2*RADIUS/(init_rad + RADIUS))-1);
|
||||
dv_tic = sqrt(mu/RADIUS)*(1-sqrt(2*init_rad/(init_rad + RADIUS)));
|
||||
printf("Orbit: %f -> %f; dv = %f, dv' = %f\n", init_rad, RADIUS, dv, dv_tic);
|
||||
} else if (started) {
|
||||
gdouble vx = S_X - last_x, vy = S_Y - last_y, v = sqrt(vx*vx+vy*vy);
|
||||
started = FALSE;
|
||||
DV_X = -vx * (dv / v);
|
||||
DV_Y = -vy * (dv / v);
|
||||
// printf("v: %f / %f\n", vx, vy);
|
||||
printf("Dv: %f / %f\n", DV_X, DV_Y);
|
||||
} else if (fabs(cur_rad - RADIUS) < 1000.0) {
|
||||
gdouble vx = S_X - last_x, vy = S_Y - last_y, v = sqrt(vx*vx+vy*vy);
|
||||
running = FALSE;
|
||||
printf("Reached target radius\n");
|
||||
DV_X = -vx * (dv_tic / v);
|
||||
DV_Y = -vy * (dv_tic / v);
|
||||
printf("Dv: %f / %f\n", DV_X, DV_Y);
|
||||
}
|
||||
|
||||
last_x = S_X;
|
||||
last_y = S_Y;
|
||||
}
|
||||
|
||||
static void run_debug(task_t *task, gpointer userdata) {
|
||||
debug(task);
|
||||
run(task, userdata);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
task_t *task;
|
||||
gdouble score;
|
||||
|
||||
UNUSED(argc);
|
||||
UNUSED(argv);
|
||||
|
||||
task = task_new(1002.0, 4, 5);
|
||||
score = task_run(task, run);
|
||||
printf("Final Score: %f\n", score);
|
||||
task_main(argc, argv, run, run_debug, NULL, 1001);
|
||||
return 0;
|
||||
}
|
92
ovm/task_main.h
Normal file
92
ovm/task_main.h
Normal file
@ -0,0 +1,92 @@
|
||||
#ifndef OVM_TASK_MAIN_H
|
||||
#define OVM_TASK_MAIN_H
|
||||
|
||||
#include "task.h"
|
||||
#include "trace.h"
|
||||
|
||||
typedef void (*task_app_t)(task_t *task, gpointer userdata);
|
||||
|
||||
static inline void trace_simulate(task_t *task, gpointer userdata) {
|
||||
trace_t *trace = (trace_t*) userdata;
|
||||
trace_entry_t *te;
|
||||
|
||||
if (trace->pos > trace->data->len) {
|
||||
fprintf(stderr, "Unexpected end of solution\n");
|
||||
exit(11);
|
||||
}
|
||||
|
||||
te = g_ptr_array_index(trace->data, trace->pos);
|
||||
if (te->timestamp == task->timestamp) {
|
||||
guint32 i;
|
||||
trace->pos++;
|
||||
for (i = 0; i < te->count; i++) {
|
||||
task->in[te->data[i].addr] = te->data[i].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline gdouble task_run(task_t *task, task_app_t app, gpointer userdata, const gchar *tracefile) {
|
||||
gboolean dotrace = (NULL != tracefile);
|
||||
ovm_init();
|
||||
if (dotrace) {
|
||||
task_trace_start(task, tracefile);
|
||||
}
|
||||
for ( ; task->out[0] == 0.0 && task->timestamp < 3000000; task->timestamp++) {
|
||||
app(task, userdata);
|
||||
if (dotrace) task_trace_step(task);
|
||||
ovm_step(task->scenario, task->in, task->out);
|
||||
}
|
||||
if (dotrace) task_trace_end(task);
|
||||
return task->out[0];
|
||||
}
|
||||
|
||||
static inline void task_main(int argc, char **argv, task_app_t app, task_app_t debug_app, gpointer userdata, guint default_scenario) {
|
||||
GError *error = NULL;
|
||||
GOptionContext *context;
|
||||
gboolean res;
|
||||
gdouble score;
|
||||
task_t *task;
|
||||
|
||||
guint scenario = default_scenario;
|
||||
const gchar *tracefile = NULL;
|
||||
const gchar *simulate_file = NULL;
|
||||
gboolean debug = FALSE;
|
||||
|
||||
GOptionEntry entries[] = {
|
||||
{ "scenario", 's', 0, G_OPTION_ARG_INT, &scenario, "run scenario", "number" },
|
||||
{ "simulate", 'm', 0, G_OPTION_ARG_FILENAME, &simulate_file, "Save trace in file", "PATH" },
|
||||
{ "trace", 't', 0, G_OPTION_ARG_FILENAME, &tracefile, "Run input data (trace from another run)", "PATH" },
|
||||
{ "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Show debug", NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
context = g_option_context_new("- ovm task runner");
|
||||
g_option_context_add_main_entries(context, entries, NULL);
|
||||
|
||||
res = g_option_context_parse(context, &argc, &argv, &error);
|
||||
|
||||
g_option_context_free(context);
|
||||
|
||||
if (!res) {
|
||||
g_printerr("failed to parse command line arguments: %s\n", error->message);
|
||||
g_error_free(error);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (simulate_file) {
|
||||
trace_t *trace = trace_load(simulate_file);
|
||||
userdata = trace;
|
||||
app = trace_simulate;
|
||||
scenario = trace->scenario;
|
||||
fprintf(stderr, "Simulating solution: Team #%u, Scenario %u\n\n", (guint) trace->team, (guint) trace->scenario);
|
||||
} else if (debug) {
|
||||
app = debug_app;
|
||||
}
|
||||
|
||||
task = task_new(scenario);
|
||||
score = task_run(task, app, userdata, tracefile);
|
||||
fprintf(stderr, "Finale score: %f\n", score);
|
||||
task_free(task);
|
||||
}
|
||||
|
||||
#endif
|
82
ovm/trace.c
Normal file
82
ovm/trace.c
Normal file
@ -0,0 +1,82 @@
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
static void trace_entry_free(trace_entry_t *te) {
|
||||
g_slice_free1(te->count*12 + 8, te);
|
||||
}
|
||||
|
||||
static void _trace_entry_free(gpointer p, gpointer x) {
|
||||
UNUSED(x);
|
||||
trace_entry_free(p);
|
||||
}
|
||||
|
||||
|
||||
static trace_entry_t *trace_entry_new(guint32 timestamp, guint32 count) {
|
||||
trace_entry_t *te = g_slice_alloc(count*12 + 8);
|
||||
te->timestamp = timestamp;
|
||||
te->count = count;
|
||||
return te;
|
||||
}
|
||||
|
||||
trace_t *trace_load(const gchar *filename) {
|
||||
GError *err = NULL;
|
||||
guint32 *buf = NULL;
|
||||
gsize len = 0, i;
|
||||
trace_t *trace = g_slice_new0(trace_t);
|
||||
trace->data = g_ptr_array_new();
|
||||
|
||||
if (!g_file_get_contents(filename, (gchar**) &buf, &len, &err)) {
|
||||
fprintf (stderr, "Unable to read file %s: %s\n", filename, err->message);
|
||||
g_error_free (err);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (len % 4 > 0) {
|
||||
fprintf (stderr, "Solution: length not aligned\n");
|
||||
exit(10);
|
||||
}
|
||||
|
||||
len /= 4;
|
||||
|
||||
if (len < 10) {
|
||||
fprintf (stderr, "Solution too short\n");
|
||||
exit(10);
|
||||
}
|
||||
|
||||
if (buf[0] != 0xCAFEBABE) {
|
||||
fprintf (stderr, "Wrong magic in solution: 0x%X\n", (guint) buf[0]);
|
||||
exit(10);
|
||||
}
|
||||
|
||||
trace->magic = buf[0];
|
||||
trace->team = buf[1];
|
||||
trace->scenario = buf[2];
|
||||
|
||||
for (i = 3; i < len; ) {
|
||||
guint32 timestamp, count;
|
||||
trace_entry_t *te;
|
||||
if (i+1 >= len) {
|
||||
fprintf(stderr, "Solution: unexpected end of file (%i+1 >= %i)\n", (guint) i, (guint) len);
|
||||
exit(10);
|
||||
}
|
||||
timestamp = buf[i++];
|
||||
count = buf[i++];
|
||||
if (i+count*3 > len) {
|
||||
fprintf(stderr, "Solution: unexpected end of file (%i+%i*3 >= %i\n", (guint) i, (guint) count, (guint) len);
|
||||
exit(10);
|
||||
}
|
||||
te = trace_entry_new(timestamp, count);
|
||||
if (count > 0) memcpy(te->data, &buf[i], count * 12);
|
||||
i += 3*count;
|
||||
g_ptr_array_add(trace->data, te);
|
||||
if (count == 0 && i < len) {
|
||||
fprintf (stderr, "Solution: expected end of file (count = 0)\n");
|
||||
}
|
||||
}
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
void trace_free(trace_t *trace) {
|
||||
g_ptr_array_foreach(trace->data, _trace_entry_free, NULL);
|
||||
}
|
24
ovm/trace.h
Normal file
24
ovm/trace.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef OVM_TRACE_H
|
||||
#define OVM_TRACE_H
|
||||
|
||||
#include "base.h"
|
||||
|
||||
typedef struct {
|
||||
guint32 timestamp;
|
||||
guint32 count;
|
||||
struct {
|
||||
guint32 addr;
|
||||
gdouble value;
|
||||
} data[];
|
||||
} trace_entry_t;
|
||||
|
||||
typedef struct {
|
||||
guint32 magic, team, scenario;
|
||||
GPtrArray *data;
|
||||
gsize pos;
|
||||
} trace_t;
|
||||
|
||||
trace_t *trace_load(const gchar *filename);
|
||||
void trace_free(trace_t *trace);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user