Merge pull request #822 from ennorehling/master

Bufix LERNE AUTO
This commit is contained in:
Enno Rehling 2018-12-01 10:45:36 +01:00 committed by GitHub
commit 0710fb796d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 25 deletions

View File

@ -46,7 +46,7 @@ int autostudy_init(scholar scholars[], int max_scholars, unit **units)
st->level = effskill_study(u, st->sk); st->level = effskill_study(u, st->sk);
st->learn = 0; st->learn = 0;
st->u = u; st->u = u;
if (++nscholars == max_scholars) { if (++nscholars > max_scholars) {
log_fatal("you must increase MAXSCHOLARS"); log_fatal("you must increase MAXSCHOLARS");
} }
} }
@ -59,7 +59,6 @@ int autostudy_init(scholar scholars[], int max_scholars, unit **units)
u = u->next; u = u->next;
} }
*units = unext; *units = unext;
scholars[nscholars].u = NULL;
if (nscholars > 0) { if (nscholars > 0) {
qsort(scholars, nscholars, sizeof(scholar), cmp_scholars); qsort(scholars, nscholars, sizeof(scholar), cmp_scholars);
} }
@ -125,25 +124,20 @@ void autostudy_run(scholar scholars[], int nscholars)
n = scholars[s].u->number; n = scholars[s].u->number;
} }
else { 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); teaching(scholars + s, i);
/* we still need to teach n students in this unit: */
/* we are done with this teacher. any remaining people are regular learners: */ n -= i;
if (scholars[t].u->number > 1) { i = 0;
/* 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 want a new teacher for s. if any exists, it's next in the sequence. */ /* we want a new teacher for s. if any exists, it's next in the sequence. */
if (++t == si) { if (++t == si) {
continue; continue;
} }
if (scholars[t].level - TEACHDIFFERENCE < scholars[s].level) { 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 { do {
learning(scholars + s, (n - i)); /* remaining students learn without a teacher: */
i = 0; learning(scholars + s, n);
if (++s == se) { if (++s == se) {
break; break;
} }

View File

@ -62,13 +62,52 @@ static void test_autostudy_init(CuTest *tc) {
CuAssertIntEquals(tc, 0, scholars[0].level); CuAssertIntEquals(tc, 0, scholars[0].level);
CuAssertIntEquals(tc, 0, scholars[0].learn); CuAssertIntEquals(tc, 0, scholars[0].learn);
CuAssertIntEquals(tc, SK_PERCEPTION, scholars[0].sk); CuAssertIntEquals(tc, SK_PERCEPTION, scholars[0].sk);
CuAssertPtrEquals(tc, NULL, scholars[1].u);
CuAssertPtrEquals(tc, NULL, ulist); CuAssertPtrEquals(tc, NULL, ulist);
test_teardown(); 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) { static void test_autostudy_run(CuTest *tc) {
scholar scholars[4]; scholar scholars[4];
int nscholars;
unit *u1, *u2, *u3, *ulist; unit *u1, *u2, *u3, *ulist;
faction *f; faction *f;
region *r; region *r;
@ -88,9 +127,9 @@ static void test_autostudy_run(CuTest *tc) {
set_number(u3, 15); set_number(u3, 15);
scholars[3].u = NULL; scholars[3].u = NULL;
ulist = r->units; ulist = r->units;
CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, &ulist)); CuAssertIntEquals(tc, 3, nscholars = autostudy_init(scholars, 4, &ulist));
CuAssertPtrEquals(tc, NULL, ulist); CuAssertPtrEquals(tc, NULL, ulist);
autostudy_run(scholars, 3); autostudy_run(scholars, nscholars);
CuAssertIntEquals(tc, 1, scholars[0].learn); CuAssertIntEquals(tc, 1, scholars[0].learn);
CuAssertIntEquals(tc, 20, scholars[1].learn); CuAssertIntEquals(tc, 20, scholars[1].learn);
CuAssertIntEquals(tc, 15, scholars[2].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) { static void test_autostudy_run_noteachers(CuTest *tc) {
scholar scholars[4]; scholar scholars[4];
int nscholars;
unit *u1, *u2, *u3, *ulist; unit *u1, *u2, *u3, *ulist;
faction *f; faction *f;
region *r; region *r;
@ -118,20 +158,50 @@ static void test_autostudy_run_noteachers(CuTest *tc) {
set_number(u3, 15); set_number(u3, 15);
scholars[3].u = NULL; scholars[3].u = NULL;
ulist = r->units; ulist = r->units;
CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, &ulist)); CuAssertIntEquals(tc, 3, nscholars = autostudy_init(scholars, 4, &ulist));
CuAssertPtrEquals(tc, NULL, ulist); CuAssertPtrEquals(tc, NULL, ulist);
autostudy_run(scholars, 3); autostudy_run(scholars, nscholars);
CuAssertIntEquals(tc, 2, scholars[0].learn); CuAssertIntEquals(tc, 2, scholars[0].learn);
CuAssertIntEquals(tc, 10, scholars[1].learn); CuAssertIntEquals(tc, 10, scholars[1].learn);
CuAssertIntEquals(tc, 15, scholars[2].learn); CuAssertIntEquals(tc, 15, scholars[2].learn);
test_teardown(); 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 * Reproduce Bug 2514
*/ */
static void test_autostudy_run_skilldiff(CuTest *tc) { static void test_autostudy_run_skilldiff(CuTest *tc) {
scholar scholars[4]; scholar scholars[4];
int nscholars;
unit *u1, *u2, *u3, *ulist; unit *u1, *u2, *u3, *ulist;
faction *f; faction *f;
region *r; region *r;
@ -152,9 +222,9 @@ static void test_autostudy_run_skilldiff(CuTest *tc) {
set_number(u3, 10); set_number(u3, 10);
scholars[3].u = NULL; scholars[3].u = NULL;
ulist = r->units; ulist = r->units;
CuAssertIntEquals(tc, 3, autostudy_init(scholars, 4, &ulist)); CuAssertIntEquals(tc, 3, nscholars = autostudy_init(scholars, 4, &ulist));
CuAssertPtrEquals(tc, NULL, ulist); CuAssertPtrEquals(tc, NULL, ulist);
autostudy_run(scholars, 3); autostudy_run(scholars, nscholars);
CuAssertIntEquals(tc, 0, scholars[0].learn); CuAssertIntEquals(tc, 0, scholars[0].learn);
CuAssertIntEquals(tc, 20, scholars[2].learn); CuAssertIntEquals(tc, 20, scholars[2].learn);
CuAssertIntEquals(tc, 10, scholars[1].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_init);
SUITE_ADD_TEST(suite, test_autostudy_run); SUITE_ADD_TEST(suite, test_autostudy_run);
SUITE_ADD_TEST(suite, test_autostudy_run_noteachers); 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); SUITE_ADD_TEST(suite, test_autostudy_run_skilldiff);
return suite; return suite;
} }

View File

@ -28,6 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/language.h> #include <util/language.h>
#include <util/log.h> #include <util/log.h>
#include <util/path.h> #include <util/path.h>
#include <util/password.h>
#include "eressea.h" #include "eressea.h"
#ifdef USE_CURSES #ifdef USE_CURSES
@ -231,6 +232,10 @@ static int parse_args(int argc, char **argv)
i = get_arg(argc, argv, 2, i, &arg, 0); i = get_arg(argc, argv, 2, i, &arg, 0);
turn = atoi(arg); turn = atoi(arg);
break; break;
case 'w':
i = get_arg(argc, argv, 2, i, &arg, 0);
bcrypt_workfactor = arg ? atoi(arg) : 0xff;
break;
case 'q': case 'q':
verbosity = 0; verbosity = 0;
break; break;

View File

@ -17,7 +17,7 @@ bool password_is_implemented(cryptalgo_t algo) {
} }
const char * password_hash(const char * passwd, cryptalgo_t algo) { const char * password_hash(const char * passwd, cryptalgo_t algo) {
if (algo == PASSWORD_BCRYPT) { if (algo == PASSWORD_BCRYPT && bcrypt_workfactor != 0) {
char salt[BCRYPT_HASHSIZE]; char salt[BCRYPT_HASHSIZE];
static char hash[BCRYPT_HASHSIZE]; static char hash[BCRYPT_HASHSIZE];
int ret; int ret;
@ -32,9 +32,12 @@ const char * password_hash(const char * passwd, cryptalgo_t algo) {
int password_verify(const char * pwhash, const char * passwd) { int password_verify(const char * pwhash, const char * passwd) {
if (pwhash[0] == '$') { if (pwhash[0] == '$') {
if (pwhash[1] == '2') { if (pwhash[1] == '2') {
int ret = bcrypt_checkpw(passwd, pwhash); if (bcrypt_workfactor > 0) {
assert(ret != -1); int ret = bcrypt_checkpw(passwd, pwhash);
return (ret == 0) ? VERIFY_OK : VERIFY_FAIL; assert(ret != -1);
return (ret == 0) ? VERIFY_OK : VERIFY_FAIL;
}
return VERIFY_OK;
} }
} }
return (strcmp(passwd, pwhash) == 0) ? VERIFY_OK : VERIFY_FAIL; return (strcmp(passwd, pwhash) == 0) ? VERIFY_OK : VERIFY_FAIL;