From d8fee17444ee1aca688e21772ef8f1bca3927d92 Mon Sep 17 00:00:00 2001 From: VladislavOstapov Date: Sat, 28 Jan 2023 12:12:01 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D0=B0=D1=8F=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=B8=D1=80=D1=83=D0=B5=D0=BC=D0=B0=D1=8F=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=9F=D0=9B=D0=9A=20=D0=B2=D0=B5=D1=80=D1=81?= =?UTF-8?q?=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- emulator.cpp | 6 +- robot.cpp | 4 +- scheduler.c | 35 ++++++- utils.c | 264 +++++++++++++++++++++++++++++++-------------------- 4 files changed, 198 insertions(+), 111 deletions(-) diff --git a/emulator.cpp b/emulator.cpp index 0664b20..4d1ec73 100644 --- a/emulator.cpp +++ b/emulator.cpp @@ -344,9 +344,9 @@ int main() { } robot_main(); -// scheduler_main(); - increment_zone(ROBOT_ZONE_GAL); - increment_zone(ROBOT_ZONE_ETCH); + scheduler_main(); +// increment_zone(ROBOT_ZONE_GAL); +// increment_zone(ROBOT_ZONE_ETCH); send_str("\033c"); showAll(); diff --git a/robot.cpp b/robot.cpp index c90bed4..675db8d 100644 --- a/robot.cpp +++ b/robot.cpp @@ -101,8 +101,8 @@ static void emulate_robot(robot_code &code, robot_regs& r, char robot_id) { case ROBOT_CMD_UP_code: if (code.barrel_id >= 0 && cmd_arg) { - // не давать ехать перед тем как истечет таймер - if (barrels[code.barrel_id].software_timer > 0) { + // не давать ехать перед тем как истечет таймер (только для не пустых барабанов) + if (!barrels[code.barrel_id].flags.is_empty && barrels[code.barrel_id].software_timer > 0) { break; } barrels[code.barrel_id].flags.is_up = true; diff --git a/scheduler.c b/scheduler.c index 544f3d5..40198f1 100644 --- a/scheduler.c +++ b/scheduler.c @@ -122,6 +122,14 @@ void scheduler_main() } } + // автоматический инкремент зон травления и цинкования + if (etching_zone < 0) { + increment_zone(ROBOT_ZONE_ETCH); + } + if (galvanizing_zone < 0) { + increment_zone(ROBOT_ZONE_GAL); + } + // кнопки на линии // кнопка загрузки барабана @@ -222,21 +230,28 @@ void scheduler_main() // для каждого робота нужно получить свой список задач // и надо еще сделать так, чтобы роботы не столкнулись + // суть этого предела в том, чтобы робот всегда был свободен ЗА зоной gal8, + // но при этом если зоной обмена выбрана промывка 3а, то за ней тоже, получается max(ZONE_G8, exchange_zone) + const short robot1_border = ZONE_GALVANIZING_8 > hla_exchange_zone ? ZONE_GALVANIZING_8 : hla_exchange_zone; + + // суть этого предела в том, чтобы робот всегда держал свободной зону gal1, + // но при этом если зоной обмена выбрана промывка 2б, то за ней тоже, получается min(ZONE_G1, exchange_zone) + const short robot2_border = ZONE_GALVANIZING_1 < hla_exchange_zone ? ZONE_GALVANIZING_1 : hla_exchange_zone; + // логика для того, чтобы роботы не столкнулись в начале - if (robot1.dx.current_zone < ZONE_GALVANIZING_1) { - // начальная позиция робота 1 - промывка 3Б + if (robot1.dx.current_zone < robot1_border) { robot2_lock_zone = -1; - robot1_lock_zone = ZONE_WASHING_3B; + robot1_lock_zone = robot1_border; if (robot1_code.PC < 0) { robot1_code.barrel_id = -1; robot1_code.code[0] = ROBOT_CMD_DOWN(); - robot1_code.code[1] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_WASHING_3B); + robot1_code.code[1] = ROBOT_CMD_MOVE_TO_ZONE(robot1_border + 2); robot1_code.code[2] = ROBOT_CMD_END(); robot1_code.PC = 0; } } else if (robot2.dx.current_zone < ZONE_DEGREASING) { // начальная позиция робота 1 - обезжир - robot2_lock_zone = ZONE_WASHING_2A; + robot2_lock_zone = ZONE_DEGREASING; if (robot2_code.PC < 0) { robot2_code.barrel_id = -1; robot2_code.code[0] = ROBOT_CMD_DOWN(); @@ -244,6 +259,16 @@ void scheduler_main() robot2_code.code[2] = ROBOT_CMD_END(); robot2_code.PC = 0; } + } else if (robot2.dx.current_zone > robot2_border) { + // это уже граница робота 2 + robot2_lock_zone = robot2_border - 2; + if (robot2_code.PC < 0) { + robot2_code.barrel_id = -1; + robot2_code.code[0] = ROBOT_CMD_DOWN(); + robot2_code.code[1] = ROBOT_CMD_MOVE_TO_ZONE(robot2_border - 2); + robot2_code.code[2] = ROBOT_CMD_END(); + robot2_code.PC = 0; + } } else { // отдельно просчитаем все для первого робота if (robot1_code.PC < 0) { diff --git a/utils.c b/utils.c index 3b5168b..67db110 100644 --- a/utils.c +++ b/utils.c @@ -33,10 +33,18 @@ char zone_is_busy(short zone) { short get_first_night_zone() { + // TODO сделать корректное вычисление ночной зоны // всего зон, куда можно сныкать барабаны (всего 9 мест: 8 промывок и выгрузка) - for (short i = 0; i < 9; i++) { - if (!zone_is_busy(NIGHT_ZONES[i])) { - return NIGHT_ZONES[i]; + for (short nz = 0; nz < 9; nz++) { + char found = 0; + for (short i = 0; i < BARRELS_COUNT; i++) { + if (barrels[i].flags.is_exist && barrels[i].zone == NIGHT_ZONES[nz] && !barrels[i].flags.is_night) { + found = 1; + } + } + + if (found == 0) { + return NIGHT_ZONES[nz]; } } @@ -47,108 +55,121 @@ short get_first_night_zone() { short _get_dest_zone(struct barrel *bar) { if (bar->flags.is_night) { return ZONE_LOAD_1; - } else { - switch (bar->zone) { - case ZONE_LOAD_2: - // загрузка 2, только в нее можно грузить новые барабаны, нужно обезжиривание - return ZONE_DEGREASING; + } - case ZONE_DEGREASING: - // обезжиривание, нужна промывка 1А - return ZONE_WASHING_1A; + // если это зона обмена и барабан пустой + if (bar->zone == hla_exchange_zone && bar->flags.is_empty) { + return ZONE_LOAD_1; + } - case ZONE_WASHING_1A: - // промывка 1А, нужна промывка 1Б - return ZONE_WASHING_1B; + switch (bar->zone) { + case ZONE_LOAD_2: + // загрузка 2, только в нее можно грузить новые барабаны, нужно обезжиривание + return ZONE_DEGREASING; - case ZONE_WASHING_1B: - // промывка 1Б, нужно травление (зоны 5-6) - if (etching_zone < 0) { - return -1; - } - return (short)(ZONE_ETCHING_1 + etching_zone); + case ZONE_DEGREASING: + // обезжиривание, нужна промывка 1А + return ZONE_WASHING_1A; - case ZONE_ETCHING_1: - case ZONE_ETCHING_2: - // травление, нужна промывка 2А - return ZONE_WASHING_2A; + case ZONE_WASHING_1A: + // промывка 1А, нужна промывка 1Б + return ZONE_WASHING_1B; - case ZONE_WASHING_2A: - // промывка 2А, нужна промывка 2Б - return ZONE_WASHING_2B; + case ZONE_WASHING_1B: + // промывка 1Б, нужно травление (зоны 5-6) + if (etching_zone < 0) { + return -1; + } + return (short)(ZONE_ETCHING_1 + etching_zone); - case ZONE_WASHING_2B: - // промывка 2Б, нужно цинкование (зоны 9-16) - if (galvanizing_zone < 0) { - return -1; - } - return (short)(ZONE_GALVANIZING_1 + galvanizing_zone); + case ZONE_ETCHING_1: + case ZONE_ETCHING_2: + // травление, нужна промывка 2А + return ZONE_WASHING_2A; - case ZONE_GALVANIZING_1: - case ZONE_GALVANIZING_2: - case ZONE_GALVANIZING_3: - case ZONE_GALVANIZING_4: - case ZONE_GALVANIZING_5: - case ZONE_GALVANIZING_6: - case ZONE_GALVANIZING_7: - case ZONE_GALVANIZING_8: - // TODO перенести эту логику в функцию can_move - // цинкование, требуется чтобы в зонах 17-22 было максимум 2 барабана (3 барабана для этой части линии - максимум) - if (!zone_is_busy(ZONE_WASHING_3A)) { - short count = 0; - // если зона 17 свободна, то диапазон начнется с 3Б - for (short i = ZONE_WASHING_3B; i <= (short)ZONE_UNLOAD; i++) { - if (zone_is_busy(i)) { - count++; - } - } - if (count < 3) { - return ZONE_WASHING_3A; + case ZONE_WASHING_2A: + // промывка 2А, нужна промывка 2Б + return ZONE_WASHING_2B; + + case ZONE_WASHING_2B: + // промывка 2Б, нужно цинкование (зоны 9-16) + if (galvanizing_zone < 0) { + return -1; + } + return (short)(ZONE_GALVANIZING_1 + galvanizing_zone); + + case ZONE_GALVANIZING_1: + case ZONE_GALVANIZING_2: + case ZONE_GALVANIZING_3: + case ZONE_GALVANIZING_4: + case ZONE_GALVANIZING_5: + case ZONE_GALVANIZING_6: + case ZONE_GALVANIZING_7: + case ZONE_GALVANIZING_8: + // цинкование, требуется чтобы в зонах 17-22 было максимум 2 барабана (3 барабана для этой части линии - максимум) + if (!zone_is_busy(ZONE_WASHING_3A)) { + short count = 0; + // если зона 17 свободна, то диапазон начнется с 3Б + for (short i = ZONE_WASHING_3B; i <= (short)ZONE_UNLOAD; i++) { + if (zone_is_busy(i)) { + count++; } } - return -1; - - case ZONE_WASHING_3A: - // промывка 3А, перекладываем в промывку 3Б - return ZONE_WASHING_3B; - - case ZONE_WASHING_3B: - // это перед пассивацией, требует свободную промывку 4А и на всякий случай свободную пассивацию - if (!zone_is_busy(ZONE_WASHING_4A)) { - return ZONE_PASSIVATION; + if (count < 3) { + return ZONE_WASHING_3A; } - // это атомарная операция, по идее вносить барабан в пассивацию нельзя + } + return -1; + + case ZONE_WASHING_3A: + // промывка 3А, перекладываем в промывку 3Б + return ZONE_WASHING_3B; + + case ZONE_WASHING_3B: + // это перед пассивацией, требует свободную промывку 4А и на всякий случай свободную пассивацию + if (!zone_is_busy(ZONE_WASHING_4A)) { + return ZONE_PASSIVATION; + } + // это атомарная операция, по идее вносить барабан в пассивацию нельзя + return -1; + + case ZONE_PASSIVATION: + // процесс пассивации, нужна промывка 4A + // чисто теоретически сюда никогда не попадем, но если вдруг выстрелит пусть будет + return ZONE_WASHING_4A; + + case ZONE_WASHING_4A: + // промывка 4А, перекладываем в промывку 4Б + return ZONE_WASHING_4B; + + case ZONE_WASHING_4B: + // последняя промывка в процессе + if (hla_night_mode) { + // TODO изменить логику для ночного режима return -1; + } else { + return ZONE_UNLOAD; + } - case ZONE_PASSIVATION: - // процесс пассивации, нужна промывка 4A - // чисто теоретически сюда никогда не попадем, но если вдруг выстрелит пусть будет - return ZONE_WASHING_4A; - - case ZONE_WASHING_4A: - // промывка 4А, перекладываем в промывку 4Б - return ZONE_WASHING_4B; - - case ZONE_WASHING_4B: - // последняя промывка в процессе + case ZONE_UNLOAD: + // последняя промывка, нужно разрешение на выгрузку + if (button_unload) { if (hla_night_mode) { - // TODO изменить логику для ночного режима - return -1; - } else { - return ZONE_UNLOAD; - } - - case ZONE_UNLOAD: - // последняя промывка, нужно разрешение на выгрузку - if (button_unload) { if (one_robot_mode) { return ZONE_LOAD_1; } else { return hla_exchange_zone; } + } else { + short nz = get_first_night_zone(); + if (nz < hla_exchange_zone) { + return hla_exchange_zone; + } else { + return nz; + } } - break; - } + } + break; } return -1; @@ -160,38 +181,64 @@ short can_move(struct barrel *bar, char robot_id) { if (robot_id != 1 && robot_id != 2) { return -3; } - // сразу отсекаем варианты, при которых невозможно переместить барабан if (!bar->flags.is_exist) { return -3; } - if (bar->software_timer > 0) { - return -2; - } - if (bar->flags.robot != 0) { return -3; } // проверка ночного режима if (hla_night_mode) { - if (bar->flags.is_night && !bar->flags.is_empty) { + if (bar->flags.is_night) { return -1; } } + // тут просчет примерного времени, в течении которого можно доехать до барабана + if (!bar->flags.is_empty) { + short approximate_time; + if (robot_id == 1) { + approximate_time = bar->zone - robot1.dx.current_zone; + } else { + approximate_time = bar->zone - robot1.dx.current_zone; + } + + // abs(approximate_time) + if (approximate_time < 0) { + approximate_time = -approximate_time; + } + +#ifndef EMULATOR + approximate_time *= 4; +#endif + + if (bar->software_timer > -approximate_time) { + return -2; + } + } + // дальше нужно проверить, что можно передвигать бочку short dest_zone = _get_dest_zone(bar); + if (zone_is_busy(dest_zone)) { + return -1; + } + if (!one_robot_mode && dest_zone >= 0) { if (robot_id == 1) { // если робот 1, то это старый, который ближе к концу линнии. // Ему нельзя ехать если хоть одна из зон <= max(r2_pos, r2_lock) + кол-во пограничных зон short border = robot2.dx.current_zone; - if (robot2_lock_zone > border) { + if (border < robot2_lock_zone) { border = robot2_lock_zone; } + if (border < ZONE_WASHING_2A) { + border = ZONE_WASHING_2A; + } + border += LOCK_ZONE_BORDER; if (bar->zone <= border || dest_zone <= border) { @@ -201,9 +248,13 @@ short can_move(struct barrel *bar, char robot_id) { // если робот 2, то это новый, который ближе к началу линнии. // Ему нельзя ехать если хоть одна из зон >= max(r2_pos, r2_lock) - кол-во пограничных зон short border = robot1.dx.current_zone; - if (robot1_lock_zone < border) { + if (border > robot1_lock_zone) { border = robot1_lock_zone; } + if (border > ZONE_WASHING_3B) { + border = ZONE_WASHING_3B; + } + border -= LOCK_ZONE_BORDER; if (bar->zone >= border || dest_zone >= border) { @@ -435,6 +486,9 @@ void create_operation(struct robot_code *code, short barrel_id, const short star if (barrel_id >= 0) { barrels[barrel_id].flags.robot = robot_id; + if (hla_night_mode && barrels[barrel_id].flags.is_empty && dest_zone == get_first_night_zone()) { + barrels[barrel_id].flags.is_night = -1; + } } short cmd_index = 0; @@ -653,19 +707,27 @@ void create_operation(struct robot_code *code, short barrel_id, const short star if (!one_robot_mode && !hla_night_mode) { if (robot_id == 2) { - if (dest_zone >= ZONE_GALVANIZING_1) { + // суть этого предела в том, чтобы робот всегда держал свободной зону gal1, + // но при этом если зоной обмена выбрана промывка 2б, то за ней тоже, получается min(ZONE_G1, exchange_zone) + const short robot2_border = (ZONE_GALVANIZING_1 < hla_exchange_zone ? ZONE_GALVANIZING_1 : hla_exchange_zone) - 1; + + if (dest_zone >= robot2_border) { // из промывки 2б он перекладывал, пусть едет в промывку 2а - code->code[cmd_index++] = ROBOT_CMD_SET_LOCK_ZONE(ZONE_WASHING_2A); - code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_WASHING_2A); + code->code[cmd_index++] = ROBOT_CMD_SET_LOCK_ZONE(robot2_border - 1); + code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(robot2_border - 1); } else if (dest_zone < ZONE_DEGREASING) { - code->code[cmd_index++] = ROBOT_CMD_SET_LOCK_ZONE(ZONE_DEGREASING); +// code->code[cmd_index++] = ROBOT_CMD_SET_LOCK_ZONE(ZONE_DEGREASING); code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_DEGREASING); } } else if (robot_id == 1) { - if (dest_zone <= ZONE_WASHING_3A) { + // суть этого предела в том, чтобы робот всегда был свободен ЗА зоной gal8, + // но при этом если зоной обмена выбрана промывка 3а, то за ней тоже, получается max(ZONE_G8, exchange_zone) + const short robot1_border = (ZONE_GALVANIZING_8 > hla_exchange_zone ? ZONE_GALVANIZING_8 : hla_exchange_zone) + 1; + + if (dest_zone <= robot1_border) { // чтобы из этой зоны можно было переложить барабан первому роботу - code->code[cmd_index++] = ROBOT_CMD_SET_LOCK_ZONE(ZONE_WASHING_4A); - code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_WASHING_4A); +// code->code[cmd_index++] = ROBOT_CMD_SET_LOCK_ZONE(robot1_border + 1); + code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(robot1_border + 1); } } }