From 41cf41120f087214483c49a079969c772ec1fe74 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 1 Mar 2020 14:24:21 +0100 Subject: [PATCH] Bug 2640: Fehler in LERNE AUTO bei teilweisen Lehrern. --- src/automate.c | 38 ++++++++++++++++++++++---------------- src/automate.test.c | 42 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 19 deletions(-) diff --git a/src/automate.c b/src/automate.c index 86deda3c0..ecb130fff 100644 --- a/src/automate.c +++ b/src/automate.c @@ -20,7 +20,8 @@ static int cmp_scholars(const void *lhs, const void *rhs) { const scholar *a = (const scholar *)lhs; const scholar *b = (const scholar *)rhs; - return b->level - a->level; + int diff = b->level - a->level; + return (diff != 0) ? diff : b->u->number - a->u->number; } int autostudy_init(scholar scholars[], int max_scholars, unit **units, skill_t *o_skill) @@ -78,7 +79,7 @@ int autostudy_init(scholar scholars[], int max_scholars, unit **units, skill_t * static void teaching(scholar *s, int n) { assert(n <= s->u->number); // doppelter Effekt mit Lehrer: - s->learn += n * 2; + s->learn += n; s->u->flags |= UFL_LONGACTION; } @@ -92,27 +93,31 @@ void autostudy_run(scholar scholars[], int nscholars) { int ti = 0; while (ti != nscholars) { - int t, se, ts = 0, tt = 0, si = ti; - for (se = ti; se != nscholars; ++se) { - int mint; - ts += scholars[se].u->number; /* count total scholars */ + int t, ts = 0, tt = 0, si = ti, mint = 0, ns = 0; + for (t = ti; t != nscholars; ++t) { + ts += scholars[t].u->number; /* count total scholars */ mint = (ts + 10) / 11; /* need a minimum of ceil(ts/11) teachers */ for (; mint > tt && si != nscholars; ++si) { tt += scholars[si].u->number; } } + if (mint < tt) { + /* die Einheit si-1 hat einen Mix aus Lehrer und Schüler */ + --si; + ns = tt - mint; + } /* now si splits the teachers and students 1:10 */ /* first student must be 2 levels below first teacher: */ - for (; si != se; ++si) { + for (; si != nscholars; ++si) { if (scholars[si].level + TEACHDIFFERENCE <= scholars[ti].level) { break; } - tt += scholars[si].u->number; + ns = 0; } /* now si is the first unit we can teach, if we can teach any */ - if (si == se) { + if (si == nscholars) { /* there are no students, so standard learning for everyone */ - for (t = ti; t != se; ++t) { + for (t = ti; t != nscholars; ++t) { learning(scholars + t, scholars[t].u->number); } } @@ -120,14 +125,15 @@ void autostudy_run(scholar scholars[], int nscholars) /* invariant: unit ti can still teach i students */ int i = scholars[ti].u->number * STUDENTS_PER_TEACHER; /* invariant: unit si has n students that can still be taught */ - int s, n = scholars[si].u->number; - for (t = ti, s = si; t != si && s != se; ) { + int s, n = (ns > 0) ? ns : scholars[si].u->number; + for (t = ti, s = si; t != si && s != nscholars; ) { if (i >= n) { /* t has more than enough teaching capacity for s */ i -= n; teaching(scholars + s, n); + learning(scholars + s, scholars[s].u->number); /* next student, please: */ - if (++s == se) { + if (++s == nscholars) { /* no more students */ break; } @@ -148,7 +154,7 @@ void autostudy_run(scholar scholars[], int nscholars) do { /* remaining students learn without a teacher: */ learning(scholars + s, n); - if (++s == se) { + if (++s == nscholars) { break; } n = scholars[s].u->number; @@ -167,12 +173,12 @@ void autostudy_run(scholar scholars[], int nscholars) /* teachers that did not teach */ learning(scholars + t, scholars[t].u->number); } - for (; s < se; ++s) { + for (; s < nscholars; ++s) { /* students that were not taught */ learning(scholars + s, scholars[s].u->number); } } - ti = se; + ti = nscholars; } } diff --git a/src/automate.test.c b/src/automate.test.c index 963cea4cd..1e38a7605 100644 --- a/src/automate.test.c +++ b/src/automate.test.c @@ -165,7 +165,7 @@ static void test_autostudy_run_few_teachers(CuTest *tc) { u2->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]); u3 = test_create_unit(f, r); set_number(u3, 100); - set_level(u3, SK_ENTERTAINMENT, 10); + set_level(u3, SK_ENTERTAINMENT, 9); u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]); ulist = r->units; @@ -174,8 +174,43 @@ static void test_autostudy_run_few_teachers(CuTest *tc) { autostudy_run(scholars, nscholars); CuAssertIntEquals(tc, SK_ENTERTAINMENT, skill); CuAssertIntEquals(tc, 0, scholars[0].learn); - CuAssertIntEquals(tc, 100, scholars[1].learn); - CuAssertIntEquals(tc, 700, scholars[2].learn); + CuAssertIntEquals(tc, 700, scholars[1].learn); + CuAssertIntEquals(tc, 100, scholars[2].learn); + + test_teardown(); +} + +static void test_autostudy_run_few_teachers_reverse(CuTest *tc) { + scholar scholars[4]; + int nscholars; + unit *u1, *u2, *u3, *ulist; + faction *f; + region *r; + skill_t skill; + + test_setup(); + r = test_create_plain(0, 0); + f = test_create_faction(NULL); + u1 = test_create_unit(f, r); + set_number(u1, 20); + set_level(u1, SK_ENTERTAINMENT, 16); + u1->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]); + u2 = test_create_unit(f, r); + set_number(u2, 100); + set_level(u2, SK_ENTERTAINMENT, 10); + u2->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]); + u3 = test_create_unit(f, r); + set_number(u3, 500); + set_level(u3, SK_ENTERTAINMENT, 9); + u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]); + + ulist = r->units; + CuAssertIntEquals(tc, 3, nscholars = autostudy_init(scholars, 4, &ulist, &skill)); + CuAssertPtrEquals(tc, NULL, ulist); + autostudy_run(scholars, nscholars); + CuAssertIntEquals(tc, SK_ENTERTAINMENT, skill); + CuAssertIntEquals(tc, 0, scholars[0].learn); + CuAssertIntEquals(tc, 800, scholars[1].learn + scholars[2].learn); test_teardown(); } @@ -397,6 +432,7 @@ CuSuite *get_automate_suite(void) SUITE_ADD_TEST(suite, test_autostudy_run_twoteachers); SUITE_ADD_TEST(suite, test_autostudy_run_bigunit); SUITE_ADD_TEST(suite, test_autostudy_run_few_teachers); + SUITE_ADD_TEST(suite, test_autostudy_run_few_teachers_reverse); SUITE_ADD_TEST(suite, test_autostudy_run_skilldiff); return suite; }