Commit c23a40c7 authored by David Gibson's avatar David Gibson

agar: Add static graph initializer

Sometimes it's not convenient to initialize an agar graph at runtime with
agar_init_graph().  This adds an AGAR_INIT_GRAPH() macro to do the same
thing as a static initializer.
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
parent bae7806a
...@@ -31,6 +31,9 @@ struct agar_graph { ...@@ -31,6 +31,9 @@ struct agar_graph {
agar_next_edge_fn next_edge; agar_next_edge_fn next_edge;
}; };
#define AGAR_INIT_GRAPH(fe, ne, ei) \
{ (ei), (fe), (ne), }
void agar_init_graph(struct agar_graph *gr, void agar_init_graph(struct agar_graph *gr,
agar_first_edge_fn first_edge, agar_first_edge_fn first_edge,
agar_next_edge_fn next_edge, agar_next_edge_fn next_edge,
......
...@@ -49,19 +49,14 @@ static void test_adjacency(const char *name, ...@@ -49,19 +49,14 @@ static void test_adjacency(const char *name,
int main(void) int main(void)
{ {
struct trivial_graphr tgr;
struct parallel_graphr pgr; struct parallel_graphr pgr;
struct full_graphr fgr; struct full_graphr fgr;
struct chain_graphr cgr; struct chain_graphr cgr;
struct grid_graphr ggr1, ggr2; struct grid_graphr ggr1, ggr2;
struct error_graphr egr;
struct shortcut1_graphr s1gr;
struct shortcut2_graphr s2gr;
plan_tests(1 + 5 + 30 + 22 + 21 + 33 + 6 + 6 + 6); plan_tests(1 + 5 + 30 + 22 + 21 + 33 + 6 + 6 + 6);
trivial_graphr_init(&tgr); test_adjacency("trivial", &trivial_graphr.gr, trivial_adjacencyr);
test_adjacency("trivial", &tgr.gr, trivial_adjacencyr);
parallel_graphr_init(&pgr, 3, 0); parallel_graphr_init(&pgr, 3, 0);
test_adjacency("parallel nlinks 3", &pgr.gr, test_adjacency("parallel nlinks 3", &pgr.gr,
...@@ -81,14 +76,13 @@ int main(void) ...@@ -81,14 +76,13 @@ int main(void)
test_adjacency("grid 3x3 all", &ggr2.gr, test_adjacency("grid 3x3 all", &ggr2.gr,
grid_adjacencyr_3x3_all); grid_adjacencyr_3x3_all);
error_graphr_init(&egr); test_adjacency("error graph", &error_graphr.gr, error_adjacencyr);
test_adjacency("error graph", &egr.gr, error_adjacencyr);
shortcut1_graphr_init(&s1gr); test_adjacency("shortcut1 graph", &shortcut1_graphr.gr,
test_adjacency("shortcut1 graph", &s1gr.gr, shortcut1_adjacencyr); shortcut1_adjacencyr);
shortcut2_graphr_init(&s2gr); test_adjacency("shortcut2 graph", &shortcut2_graphr.gr,
test_adjacency("shortcut2 graph", &s2gr.gr, shortcut2_adjacencyr); shortcut2_adjacencyr);
return exit_status(); return exit_status();
} }
...@@ -38,20 +38,16 @@ ...@@ -38,20 +38,16 @@
int main(void) int main(void)
{ {
struct trivial_graphr tgr;
struct parallel_graphr pgr; struct parallel_graphr pgr;
struct full_graphr fgr; struct full_graphr fgr;
struct chain_graphr cgr; struct chain_graphr cgr;
struct grid_graphr ggr1, ggr2; struct grid_graphr ggr1, ggr2;
struct error_graphr egr;
struct traversal1_graphr t1gr;
struct agar_state *sr; struct agar_state *sr;
const void *nr; const void *nr;
plan_tests(2 * 13 + 12 + 10); plan_tests(2 * 13 + 12 + 10);
trivial_graphr_init(&tgr); test_bfs(&trivial_graphr.gr, 1, 1);
test_bfs(&tgr.gr, 1, 1);
parallel_graphr_init(&pgr, 3, 0); parallel_graphr_init(&pgr, 3, 0);
test_bfs(&pgr.gr, 1, 1, 2); test_bfs(&pgr.gr, 1, 1, 2);
...@@ -75,9 +71,9 @@ int main(void) ...@@ -75,9 +71,9 @@ int main(void)
test_bfs(&ggr2.gr, 5, 5, 6, 8, 4, 2, 9, 3, 7, 1); test_bfs(&ggr2.gr, 5, 5, 6, 8, 4, 2, 9, 3, 7, 1);
test_bfs(&ggr2.gr, 9, 9, 8, 6, 7, 5, 3, 4, 2, 1); test_bfs(&ggr2.gr, 9, 9, 8, 6, 7, 5, 3, 4, 2, 1);
error_graphr_init(&egr); test_bfs(&error_graphr.gr, 1, 1, 2);
test_bfs(&egr.gr, 1, 1, 2); ok((sr = agar_bfs_new(NULL, &error_graphr.gr)),
ok((sr = agar_bfs_new(NULL, &egr.gr)), "started error traversal"); "started error traversal");
ok1(agar_bfs_explore(sr, int2ptr(3), &nr)); ok1(agar_bfs_explore(sr, int2ptr(3), &nr));
ok(ptr2int(nr) == 3, "Expected node #3, actually #%ld", ptr2int(nr)); ok(ptr2int(nr) == 3, "Expected node #3, actually #%ld", ptr2int(nr));
ok1(agar_bfs_explore(sr, nr, &nr)); ok1(agar_bfs_explore(sr, nr, &nr));
...@@ -86,18 +82,17 @@ int main(void) ...@@ -86,18 +82,17 @@ int main(void)
ok1(agar_error(sr) == -1); ok1(agar_error(sr) == -1);
ok1(!agar_bfs_explore(sr, nr, &nr)); ok1(!agar_bfs_explore(sr, nr, &nr));
tal_free(sr); tal_free(sr);
test_bfs(&egr.gr, 1, 1, 2); test_bfs(&error_graphr.gr, 1, 1, 2);
traversal1_graphr_init(&t1gr); test_bfs(&traversal1_graphr.gr, 1, 1, 2, 3, 4, 5, 6);
test_bfs(&t1gr.gr, 1, 1, 2, 3, 4, 5, 6); test_bfs(&traversal1_graphr.gr, 9, 9, 8, 7, 6, 5, 4);
test_bfs(&t1gr.gr, 9, 9, 8, 7, 6, 5, 4);
ok1((sr = agar_bfs_new(NULL, &t1gr.gr))); ok1((sr = agar_bfs_new(NULL, &traversal1_graphr.gr)));
test_bfs_partial(sr, 1, 1, 2, 3, 4, 5, 6); test_bfs_partial(sr, 1, 1, 2, 3, 4, 5, 6);
test_bfs_partial(sr, 9, 9, 8, 7); test_bfs_partial(sr, 9, 9, 8, 7);
tal_free(sr); tal_free(sr);
ok1((sr = agar_bfs_new(NULL, &t1gr.gr))); ok1((sr = agar_bfs_new(NULL, &traversal1_graphr.gr)));
test_bfs_partial(sr, 9, 9, 8, 7, 6, 5, 4); test_bfs_partial(sr, 9, 9, 8, 7, 6, 5, 4);
test_bfs_partial(sr, 1, 1, 2, 3); test_bfs_partial(sr, 1, 1, 2, 3);
tal_free(sr); tal_free(sr);
......
...@@ -38,20 +38,16 @@ ...@@ -38,20 +38,16 @@
int main(void) int main(void)
{ {
struct trivial_graphr tgr;
struct parallel_graphr pgr; struct parallel_graphr pgr;
struct full_graphr fgr; struct full_graphr fgr;
struct chain_graphr cgr; struct chain_graphr cgr;
struct grid_graphr ggr1, ggr2; struct grid_graphr ggr1, ggr2;
struct error_graphr egr;
struct traversal1_graphr t1gr;
struct agar_state *sr; struct agar_state *sr;
const void *nr; const void *nr;
plan_tests(2 * 13 + 12 + 10); plan_tests(2 * 13 + 12 + 10);
trivial_graphr_init(&tgr); test_dfs(&trivial_graphr.gr, 1, 1);
test_dfs(&tgr.gr, 1, 1);
parallel_graphr_init(&pgr, 3, 0); parallel_graphr_init(&pgr, 3, 0);
test_dfs(&pgr.gr, 1, 1, 2); test_dfs(&pgr.gr, 1, 1, 2);
...@@ -75,9 +71,9 @@ int main(void) ...@@ -75,9 +71,9 @@ int main(void)
test_dfs(&ggr2.gr, 5, 5, 6, 9, 8, 7, 4, 1, 2, 3); test_dfs(&ggr2.gr, 5, 5, 6, 9, 8, 7, 4, 1, 2, 3);
test_dfs(&ggr2.gr, 9, 9, 8, 7, 4, 5, 6, 3, 2, 1); test_dfs(&ggr2.gr, 9, 9, 8, 7, 4, 5, 6, 3, 2, 1);
error_graphr_init(&egr); test_dfs(&error_graphr.gr, 1, 1, 2);
test_dfs(&egr.gr, 1, 1, 2); ok((sr = agar_dfs_new(NULL, &error_graphr.gr)),
ok((sr = agar_dfs_new(NULL, &egr.gr)), "started error traversal"); "started error traversal");
ok1(agar_dfs_explore(sr, int2ptr(3), &nr)); ok1(agar_dfs_explore(sr, int2ptr(3), &nr));
ok(ptr2int(nr) == 3, "Expected node #3, actually #%ld", ptr2int(nr)); ok(ptr2int(nr) == 3, "Expected node #3, actually #%ld", ptr2int(nr));
ok1(agar_dfs_explore(sr, nr, &nr)); ok1(agar_dfs_explore(sr, nr, &nr));
...@@ -86,18 +82,17 @@ int main(void) ...@@ -86,18 +82,17 @@ int main(void)
ok(agar_error(sr) == -1, "Error is %d (expected -1)", agar_error(sr)); ok(agar_error(sr) == -1, "Error is %d (expected -1)", agar_error(sr));
ok1(!agar_dfs_explore(sr, nr, &nr)); ok1(!agar_dfs_explore(sr, nr, &nr));
tal_free(sr); tal_free(sr);
test_dfs(&egr.gr, 1, 1, 2); test_dfs(&error_graphr.gr, 1, 1, 2);
traversal1_graphr_init(&t1gr); test_dfs(&traversal1_graphr.gr, 1, 1, 2, 4, 5, 3, 6);
test_dfs(&t1gr.gr, 1, 1, 2, 4, 5, 3, 6); test_dfs(&traversal1_graphr.gr, 9, 9, 8, 6, 5, 7, 4);
test_dfs(&t1gr.gr, 9, 9, 8, 6, 5, 7, 4);
ok1((sr = agar_dfs_new(NULL, &t1gr.gr))); ok1((sr = agar_dfs_new(NULL, &traversal1_graphr.gr)));
test_dfs_partial(sr, 1, 1, 2, 4, 5, 3, 6); test_dfs_partial(sr, 1, 1, 2, 4, 5, 3, 6);
test_dfs_partial(sr, 9, 9, 8, 7); test_dfs_partial(sr, 9, 9, 8, 7);
tal_free(sr); tal_free(sr);
ok1((sr = agar_dfs_new(NULL, &t1gr.gr))); ok1((sr = agar_dfs_new(NULL, &traversal1_graphr.gr)));
test_dfs_partial(sr, 9, 9, 8, 6, 5, 7, 4); test_dfs_partial(sr, 9, 9, 8, 6, 5, 7, 4);
test_dfs_partial(sr, 1, 1, 2, 3); test_dfs_partial(sr, 1, 1, 2, 3);
tal_free(sr); tal_free(sr);
......
...@@ -14,14 +14,11 @@ ...@@ -14,14 +14,11 @@
static void test_trivial(void) static void test_trivial(void)
{ {
struct trivial_graphr tgr;
struct agar_state *sr; struct agar_state *sr;
aga_icost_t cost; aga_icost_t cost;
const void *node; const void *node;
trivial_graphr_init(&tgr); ok1(sr = agar_dijkstra_new(NULL, &trivial_graphr.gr, int2ptr(1)));
ok1(sr = agar_dijkstra_new(NULL, &tgr.gr, int2ptr(1)));
ok1(agar_dijkstra_step(sr, &node)); ok1(agar_dijkstra_step(sr, &node));
ok1(ptr2int(node) == 1); ok1(ptr2int(node) == 1);
ok1(!agar_dijkstra_step(sr, &node)); ok1(!agar_dijkstra_step(sr, &node));
...@@ -131,13 +128,10 @@ static void test_chain(void) ...@@ -131,13 +128,10 @@ static void test_chain(void)
static void test_error(void) static void test_error(void)
{ {
struct error_graphr egr;
struct agar_state *sr; struct agar_state *sr;
aga_icost_t cost; aga_icost_t cost;
error_graphr_init(&egr); ok1(sr = agar_dijkstra_new(NULL, &error_graphr.gr, int2ptr(1)));
ok1(sr = agar_dijkstra_new(NULL, &egr.gr, int2ptr(1)));
ok1(agar_dijkstra_path(sr, int2ptr(1), &cost, NULL, NULL)); ok1(agar_dijkstra_path(sr, int2ptr(1), &cost, NULL, NULL));
ok1(cost == 0); ok1(cost == 0);
ok1(agar_dijkstra_path(sr, int2ptr(2), &cost, NULL, NULL)); ok1(agar_dijkstra_path(sr, int2ptr(2), &cost, NULL, NULL));
...@@ -146,7 +140,7 @@ static void test_error(void) ...@@ -146,7 +140,7 @@ static void test_error(void)
ok1(!agar_dijkstra_path(sr, int2ptr(4), &cost, NULL, NULL)); ok1(!agar_dijkstra_path(sr, int2ptr(4), &cost, NULL, NULL));
tal_free(sr); tal_free(sr);
ok1(sr = agar_dijkstra_new(NULL, &egr.gr, int2ptr(3))); ok1(sr = agar_dijkstra_new(NULL, &error_graphr.gr, int2ptr(3)));
ok1(agar_dijkstra_path(sr, int2ptr(3), &cost, NULL, NULL)); ok1(agar_dijkstra_path(sr, int2ptr(3), &cost, NULL, NULL));
ok1(cost == 0); ok1(cost == 0);
ok1(!agar_dijkstra_path(sr, int2ptr(4), &cost, NULL, NULL)); ok1(!agar_dijkstra_path(sr, int2ptr(4), &cost, NULL, NULL));
...@@ -156,15 +150,12 @@ static void test_error(void) ...@@ -156,15 +150,12 @@ static void test_error(void)
static void test_traversal1(void) static void test_traversal1(void)
{ {
struct traversal1_graphr t1gr;
struct agar_state *sr; struct agar_state *sr;
aga_icost_t cost; aga_icost_t cost;
/* This is mostly about testing we correctly handle /* This is mostly about testing we correctly handle
* non-reachable nodes */ * non-reachable nodes */
traversal1_graphr_init(&t1gr); ok1(sr = agar_dijkstra_new(NULL, &traversal1_graphr.gr, int2ptr(1)));
ok1(sr = agar_dijkstra_new(NULL, &t1gr.gr, int2ptr(1)));
ok1(agar_dijkstra_path(sr, int2ptr(1), ok1(agar_dijkstra_path(sr, int2ptr(1),
&cost, NULL, NULL)); &cost, NULL, NULL));
ok1(cost == 0); ok1(cost == 0);
...@@ -191,7 +182,7 @@ static void test_traversal1(void) ...@@ -191,7 +182,7 @@ static void test_traversal1(void)
NULL, NULL, NULL)); NULL, NULL, NULL));
tal_free(sr); tal_free(sr);
ok1(sr = agar_dijkstra_new(NULL, &t1gr.gr, int2ptr(9))); ok1(sr = agar_dijkstra_new(NULL, &traversal1_graphr.gr, int2ptr(9)));
ok1(agar_dijkstra_path(sr, int2ptr(9), ok1(agar_dijkstra_path(sr, int2ptr(9),
&cost, NULL, NULL)); &cost, NULL, NULL));
ok1(cost == 0); ok1(cost == 0);
...@@ -221,14 +212,11 @@ static void test_traversal1(void) ...@@ -221,14 +212,11 @@ static void test_traversal1(void)
static void test_shortcut1(void) static void test_shortcut1(void)
{ {
struct shortcut1_graphr s1gr;
struct agar_state *sr; struct agar_state *sr;
aga_icost_t cost; aga_icost_t cost;
const void *node; const void *node;
shortcut1_graphr_init(&s1gr); ok1(sr = agar_dijkstra_new(NULL, &shortcut1_graphr.gr, int2ptr(1)));
ok1(sr = agar_dijkstra_new(NULL, &s1gr.gr, int2ptr(1)));
ok1(agar_dijkstra_path(sr, int2ptr(3), &cost, &node, NULL)); ok1(agar_dijkstra_path(sr, int2ptr(3), &cost, &node, NULL));
ok1(cost == 2); ok1(cost == 2);
ok1(node == int2ptr(2)); ok1(node == int2ptr(2));
...@@ -240,12 +228,9 @@ static void test_shortcut1(void) ...@@ -240,12 +228,9 @@ static void test_shortcut1(void)
static void test_shortcut2(void) static void test_shortcut2(void)
{ {
struct shortcut2_graphr s2gr;
struct agar_state *sr; struct agar_state *sr;
shortcut2_graphr_init(&s2gr); ok1(sr = agar_dijkstra_new(NULL, &shortcut2_graphr.gr, int2ptr(1)));
ok1(sr = agar_dijkstra_new(NULL, &s2gr.gr, int2ptr(1)));
agar_dijkstra_all_paths(sr); agar_dijkstra_all_paths(sr);
ok1(agar_error(sr) == AGA_ERR_NEGATIVE_COST); ok1(agar_error(sr) == AGA_ERR_NEGATIVE_COST);
tal_free(sr); tal_free(sr);
......
...@@ -48,8 +48,7 @@ static int error_edge_info_r(const struct agar_graph *gr, ...@@ -48,8 +48,7 @@ static int error_edge_info_r(const struct agar_graph *gr,
return 0; return 0;
} }
void error_graphr_init(struct error_graphr *egr) struct error_graphr error_graphr = {
{ AGAR_INIT_GRAPH(error_first_edge_r, error_next_edge_r,
agar_init_graph(&egr->gr, error_first_edge_r, error_next_edge_r, error_edge_info_r),
error_edge_info_r); };
}
...@@ -78,9 +78,8 @@ static int shortcut1_edge_info_r(const struct agar_graph *gr, ...@@ -78,9 +78,8 @@ static int shortcut1_edge_info_r(const struct agar_graph *gr,
return 0; return 0;
} }
void shortcut1_graphr_init(struct shortcut1_graphr *s1gr) struct shortcut1_graphr shortcut1_graphr = {
{ AGAR_INIT_GRAPH(shortcut1_first_edge_r,
agar_init_graph(&s1gr->gr, shortcut1_first_edge_r,
shortcut1_next_edge_r, shortcut1_next_edge_r,
shortcut1_edge_info_r); shortcut1_edge_info_r),
} };
...@@ -79,9 +79,8 @@ static int shortcut2_edge_info_r(const struct agar_graph *gr, ...@@ -79,9 +79,8 @@ static int shortcut2_edge_info_r(const struct agar_graph *gr,
return 0; return 0;
} }
void shortcut2_graphr_init(struct shortcut2_graphr *s1gr) struct shortcut2_graphr shortcut2_graphr = {
{ AGAR_INIT_GRAPH(shortcut2_first_edge_r,
agar_init_graph(&s1gr->gr, shortcut2_first_edge_r,
shortcut2_next_edge_r, shortcut2_next_edge_r,
shortcut2_edge_info_r); shortcut2_edge_info_r),
} };
...@@ -19,7 +19,7 @@ struct adjacency_listr { ...@@ -19,7 +19,7 @@ struct adjacency_listr {
struct trivial_graphr { struct trivial_graphr {
struct agar_graph gr; struct agar_graph gr;
}; };
void trivial_graphr_init(struct trivial_graphr *tgr); extern struct trivial_graphr trivial_graphr;
static const struct adjacency_listr trivial_adjacencyr[] = { static const struct adjacency_listr trivial_adjacencyr[] = {
{1, {}}, {1, {}},
{}, {},
...@@ -156,7 +156,7 @@ static const struct adjacency_listr grid_adjacencyr_3x3_all[] = { ...@@ -156,7 +156,7 @@ static const struct adjacency_listr grid_adjacencyr_3x3_all[] = {
struct error_graphr { struct error_graphr {
struct agar_graph gr; struct agar_graph gr;
}; };
void error_graphr_init(struct error_graphr *eg); extern struct error_graphr error_graphr;
static const struct adjacency_listr error_adjacencyr[] = { static const struct adjacency_listr error_adjacencyr[] = {
{1, {2}}, {1, {2}},
{2, {}}, {2, {}},
...@@ -185,7 +185,7 @@ static const struct adjacency_listr error_adjacencyr[] = { ...@@ -185,7 +185,7 @@ static const struct adjacency_listr error_adjacencyr[] = {
struct traversal1_graphr { struct traversal1_graphr {
struct agar_graph gr; struct agar_graph gr;
}; };
void traversal1_graphr_init(struct traversal1_graphr *t1gr); extern struct traversal1_graphr traversal1_graphr;
static const struct adjacency_listr traversal1_adjacency[] = { static const struct adjacency_listr traversal1_adjacency[] = {
{1, {2, 3}}, {1, {2, 3}},
{2, {4, 5}}, {2, {4, 5}},
...@@ -211,7 +211,7 @@ static const struct adjacency_listr traversal1_adjacency[] = { ...@@ -211,7 +211,7 @@ static const struct adjacency_listr traversal1_adjacency[] = {
struct shortcut1_graphr { struct shortcut1_graphr {
struct agar_graph gr; struct agar_graph gr;
}; };
void shortcut1_graphr_init(struct shortcut1_graphr *s1gr); extern struct shortcut1_graphr shortcut1_graphr;
static const struct adjacency_listr shortcut1_adjacencyr[] = { static const struct adjacency_listr shortcut1_adjacencyr[] = {
{1, {3, 2}}, {1, {3, 2}},
{2, {3}}, {2, {3}},
...@@ -232,7 +232,7 @@ static const struct adjacency_listr shortcut1_adjacencyr[] = { ...@@ -232,7 +232,7 @@ static const struct adjacency_listr shortcut1_adjacencyr[] = {
struct shortcut2_graphr { struct shortcut2_graphr {
struct agar_graph gr; struct agar_graph gr;
}; };
void shortcut2_graphr_init(struct shortcut2_graphr *s2gr); extern struct shortcut2_graphr shortcut2_graphr;
static const struct adjacency_listr shortcut2_adjacencyr[] = { static const struct adjacency_listr shortcut2_adjacencyr[] = {
{1, {3, 2}}, {1, {3, 2}},
{2, {3}}, {2, {3}},
......
...@@ -106,9 +106,7 @@ static int traversal1_edge_info_r(const struct agar_graph *gr, ...@@ -106,9 +106,7 @@ static int traversal1_edge_info_r(const struct agar_graph *gr,
return 0; return 0;
} }
void traversal1_graphr_init(struct traversal1_graphr *t1gr) struct traversal1_graphr traversal1_graphr = {
{ AGAR_INIT_GRAPH(traversal1_first_edge_r, traversal1_next_edge_r,
agar_init_graph(&t1gr->gr, traversal1_edge_info_r),
traversal1_first_edge_r, traversal1_next_edge_r, };
traversal1_edge_info_r);
}
...@@ -29,8 +29,7 @@ static int trivial_edge_info_r(const struct agar_graph *gr, ...@@ -29,8 +29,7 @@ static int trivial_edge_info_r(const struct agar_graph *gr,
assert(0); assert(0);
} }
void trivial_graphr_init(struct trivial_graphr *tgr) struct trivial_graphr trivial_graphr = {
{ AGAR_INIT_GRAPH(trivial_first_edge_r, trivial_next_edge_r,
agar_init_graph(&tgr->gr, trivial_first_edge_r, trivial_next_edge_r, trivial_edge_info_r),
trivial_edge_info_r); };
}
...@@ -18,6 +18,7 @@ int main(int argc, char *argv[]) ...@@ -18,6 +18,7 @@ int main(int argc, char *argv[])
if (strcmp(argv[1], "depends") == 0) { if (strcmp(argv[1], "depends") == 0) {
printf("ccan/tlist\n"); printf("ccan/tlist\n");
printf("ccan/typesafe_cb\n"); printf("ccan/typesafe_cb\n");
printf("ccan/agar\n");
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment