From fc23926559df033a565873a4ed08f8c322ba3d93 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 1 Dec 2018 10:29:48 +0100 Subject: [PATCH] BUG 2520: LERNE AUTO multi-teacher assignment --- src/automate.c | 22 +++++------- src/automate.test.c | 86 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 21 deletions(-) diff --git a/src/automate.c b/src/automate.c index 04230096d..4332dc8e8 100644 --- a/src/automate.c +++ b/src/automate.c @@ -46,7 +46,7 @@ int autostudy_init(scholar scholars[], int max_scholars, unit **units) st->level = effskill_study(u, st->sk); st->learn = 0; st->u = u; - if (++nscholars == max_scholars) { + if (++nscholars > max_scholars) { log_fatal("you must increase MAXSCHOLARS"); } } @@ -59,7 +59,6 @@ int autostudy_init(scholar scholars[], int max_scholars, unit **units) u = u->next; } *units = unext; - scholars[nscholars].u = NULL; if (nscholars > 0) { qsort(scholars, nscholars, sizeof(scholar), cmp_scholars); } @@ -125,25 +124,20 @@ void autostudy_run(scholar scholars[], int nscholars) n = scholars[s].u->number; } else { - /* s gets partial credit and we need a new teacher */ + /* a part of s gets credited and we need a new teacher: */ teaching(scholars + s, i); - - /* we are done with this teacher. any remaining people are regular learners: */ - if (scholars[t].u->number > 1) { - /* remain = number - ceil(taught/10); */ - int remain = (STUDENTS_PER_TEACHER * scholars[t].u->number - i + STUDENTS_PER_TEACHER - 1) / STUDENTS_PER_TEACHER; - learning(scholars + t, remain); - } - + /* we still need to teach n students in this unit: */ + n -= i; + i = 0; /* we want a new teacher for s. if any exists, it's next in the sequence. */ if (++t == si) { continue; } if (scholars[t].level - TEACHDIFFERENCE < scholars[s].level) { - /* next teacher cannot teach, we must skip students. */ + /* no remaining teacher can teach this student, so we skip ahead */ do { - learning(scholars + s, (n - i)); - i = 0; + /* remaining students learn without a teacher: */ + learning(scholars + s, n); if (++s == se) { break; } diff --git a/src/automate.test.c b/src/automate.test.c index 0da88ac69..698cda6be 100644 --- a/src/automate.test.c +++ b/src/automate.test.c @@ -62,13 +62,52 @@ static void test_autostudy_init(CuTest *tc) { CuAssertIntEquals(tc, 0, scholars[0].level); CuAssertIntEquals(tc, 0, scholars[0].learn); CuAssertIntEquals(tc, SK_PERCEPTION, scholars[0].sk); - CuAssertPtrEquals(tc, NULL, scholars[1].u); CuAssertPtrEquals(tc, NULL, ulist); test_teardown(); } +/** + * Reproduce Bug 2520 + */ +static void test_autostudy_run_twoteachers(CuTest *tc) { + scholar scholars[4]; + int nscholars; + unit *u1, *u2, *u3, *u4, *ulist; + faction *f; + region *r; + + test_setup(); + r = test_create_plain(0, 0); + f = test_create_faction(NULL); + u1 = test_create_unit(f, r); + set_level(u1, SK_ENTERTAINMENT, 2); + u1->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]); + u2 = test_create_unit(f, r); + set_level(u2, SK_ENTERTAINMENT, 2); + u2->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]); + + u3 = test_create_unit(f, r); + u3->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]); + set_number(u3, 8); + u4 = test_create_unit(f, r); + u4->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]); + set_number(u4, 12); + + ulist = r->units; + CuAssertIntEquals(tc, 4, nscholars = autostudy_init(scholars, 4, &ulist)); + CuAssertPtrEquals(tc, NULL, ulist); + autostudy_run(scholars, nscholars); + CuAssertIntEquals(tc, 0, scholars[0].learn); + CuAssertIntEquals(tc, 0, scholars[1].learn); + CuAssertIntEquals(tc, scholars[2].u->number * 2, scholars[2].learn); + CuAssertIntEquals(tc, scholars[3].u->number * 2, scholars[3].learn); + + test_teardown(); +} + static void test_autostudy_run(CuTest *tc) { scholar scholars[4]; + int nscholars; unit *u1, *u2, *u3, *ulist; faction *f; region *r; @@ -88,9 +127,9 @@ static void test_autostudy_run(CuTest *tc) { set_number(u3, 15); scholars[3].u = NULL; ulist = r->units; - CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, &ulist)); + CuAssertIntEquals(tc, 3, nscholars = autostudy_init(scholars, 4, &ulist)); CuAssertPtrEquals(tc, NULL, ulist); - autostudy_run(scholars, 3); + autostudy_run(scholars, nscholars); CuAssertIntEquals(tc, 1, scholars[0].learn); CuAssertIntEquals(tc, 20, scholars[1].learn); CuAssertIntEquals(tc, 15, scholars[2].learn); @@ -99,6 +138,7 @@ static void test_autostudy_run(CuTest *tc) { static void test_autostudy_run_noteachers(CuTest *tc) { scholar scholars[4]; + int nscholars; unit *u1, *u2, *u3, *ulist; faction *f; region *r; @@ -118,20 +158,50 @@ static void test_autostudy_run_noteachers(CuTest *tc) { set_number(u3, 15); scholars[3].u = NULL; ulist = r->units; - CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, &ulist)); + CuAssertIntEquals(tc, 3, nscholars = autostudy_init(scholars, 4, &ulist)); CuAssertPtrEquals(tc, NULL, ulist); - autostudy_run(scholars, 3); + autostudy_run(scholars, nscholars); CuAssertIntEquals(tc, 2, scholars[0].learn); CuAssertIntEquals(tc, 10, scholars[1].learn); CuAssertIntEquals(tc, 15, scholars[2].learn); test_teardown(); } +/** + * If a teacher unit doesn't have enough students, the remaining members study. + */ +static void test_autostudy_run_teachers_learn(CuTest *tc) { + scholar scholars[4]; + int nscholars; + unit *u1, *u2, *ulist; + faction *f; + region *r; + + test_setup(); + r = test_create_plain(0, 0); + f = test_create_faction(NULL); + u1 = test_create_unit(f, r); + u1->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]); + set_number(u1, 2); + set_level(u1, SK_ENTERTAINMENT, 2); + u2 = test_create_unit(f, r); + u2->thisorder = create_order(K_AUTOSTUDY, f->locale, skillnames[SK_ENTERTAINMENT]); + set_number(u2, 10); + ulist = r->units; + CuAssertIntEquals(tc, 2, nscholars = autostudy_init(scholars, 4, &ulist)); + CuAssertPtrEquals(tc, NULL, ulist); + autostudy_run(scholars, nscholars); + CuAssertIntEquals(tc, 1, scholars[0].learn); + CuAssertIntEquals(tc, 20, scholars[1].learn); + test_teardown(); +} + /** * Reproduce Bug 2514 */ static void test_autostudy_run_skilldiff(CuTest *tc) { scholar scholars[4]; + int nscholars; unit *u1, *u2, *u3, *ulist; faction *f; region *r; @@ -152,9 +222,9 @@ static void test_autostudy_run_skilldiff(CuTest *tc) { set_number(u3, 10); scholars[3].u = NULL; ulist = r->units; - CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, &ulist)); + CuAssertIntEquals(tc, 3, nscholars = autostudy_init(scholars, 4, &ulist)); CuAssertPtrEquals(tc, NULL, ulist); - autostudy_run(scholars, 3); + autostudy_run(scholars, nscholars); CuAssertIntEquals(tc, 0, scholars[0].learn); CuAssertIntEquals(tc, 20, scholars[2].learn); CuAssertIntEquals(tc, 10, scholars[1].learn); @@ -167,6 +237,8 @@ CuSuite *get_automate_suite(void) SUITE_ADD_TEST(suite, test_autostudy_init); SUITE_ADD_TEST(suite, test_autostudy_run); SUITE_ADD_TEST(suite, test_autostudy_run_noteachers); + SUITE_ADD_TEST(suite, test_autostudy_run_teachers_learn); + SUITE_ADD_TEST(suite, test_autostudy_run_twoteachers); SUITE_ADD_TEST(suite, test_autostudy_run_skilldiff); return suite; }