This repository has been archived on 2024-09-18. You can view files and clone it, but cannot push or open issues or pull requests.
sdp-scheduler/emulator.cpp

304 lines
8.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by Владислав Остапов on 27.10.2022.
//
#include <cstring>
#include <iostream>
#include <libc.h>
#include "emulator.h"
#include "robot.h"
struct barrel barrels[BARRELS_COUNT];
struct robot_regs robot1;
struct robot_regs robot2;
char _scheduler_software_timer = 0;
// кнопка загрузки в зоне 0, означает что барабан надо изъять из этой загрузки (а перед этим создать)
char button_load = 0;
char button_unload = 0;
char button_unload_end = 0;
char button_unload_remove = 0;
// времена операций для барабанов, устанавливается индивидуально каждому барабану
short hla_time_degreasing = 12;
short hla_time_washing_1a = 4;
short hla_time_washing_1b = 6;
short hla_time_etching = 25;
short hla_time_washing_2a = 6;
short hla_time_washing_2b = 8;
short hla_time_galvanizing = 60;
short hla_time_washing_3a = 8;
short hla_time_washing_3b = 10;
short hla_time_passivation = 3;
short hla_time_washing_4a = 12;
short hla_time_washing_4b = 14;
// времена скапывания, одинаковые для всех барабанов
short hla_time_digging = 8;
short hla_time_reagent = 30;
short hla_time_washing_1 = 3;
short hla_time_washing_2 = 20;
char hla_robot1_en = 1;
char hla_robot2_en = 1;
char one_robot_mode = (char)(hla_robot1_en ^ hla_robot2_en);
char scheduler_en = 1;
char scheduler_start_signal = 1;
char auto_mode_pause = 0;
short etching_zone = 0, galvanizing_zone = 0;
static const int ROWS = 10;
static const int COLS = 23 * 5 + 1;
static char buffer[ROWS][COLS];
static int current_tic = 0;
robot_code robot1_code{0, -1};
robot_code robot2_code{0, -1};
short robot1_lock_zone = 0;
short robot2_lock_zone = 0;
static int sock_fd;
static void send_str(const char* str) {
write(sock_fd, str, strlen(str));
}
static void image_init() {
// заполнение всего поля пробелами
memset(buffer, ' ', sizeof(buffer));
}
static void image_insert_sprite(int row, int col, const char* str, bool alpha = true) {
for (; row < ROWS; row++) {
for (int curr_col = col;; curr_col++) {
char src = *(str++);
// конец строки, заканчиваем рисовать
if (src == '\0') {
return;
}
// перевод строки, перевод на новую строку в этом спрайте
if (src == '\n') {
break;
}
// чтобы не рисовать мусор
if (src < ' ') {
src = ' ';
}
if (curr_col < COLS) {
// рисуем, остальные фрагменты будут отброшены
char frag = buffer[row][curr_col];
if (alpha) {
// этот режим позволяет пропускать изменение символа, если исходный символ пробел
if (src != ' ') {
frag = src;
}
} else {
frag = src;
}
buffer[row][curr_col] = frag;
}
}
}
}
static void image_draw_borders() {
// рамки ванн
// for (int i = 0; i < COLS; i += 5) {
// image_insert_sprite(5, i, "|\n|\n|");
// }
// рисование линий
for (int i = 0; i < ROWS - 1; i++) {
buffer[i][0] = '|';
buffer[i][COLS - 1] = '|';
}
memset(buffer[1], '=', sizeof(buffer[0]));
// рамки ванн
char tmp[24];
for (int i = 0, zone = 0; i < COLS; i += 5, zone++) {
sprintf(tmp, "|\n|\n+----+\n|\n|Z-%02d|", zone);
image_insert_sprite(5, i, tmp, false);
}
image_insert_sprite(8, 1, "LOAD LOAD DEFA W-1A W-1B ETCH ETCH W-2A W-2B "
" GAL GAL GAL GAL GAL GAL GAL GAL "
"W-3A W-3B PASS W-4A W-4B UNLD", true);
// счетчик тиков
sprintf(tmp, "tic: %d", current_tic);
image_insert_sprite(0, (int)(COLS - strlen(tmp) - 2), tmp, false);
}
static void showAll() {
// 10 строк, 10*(\sb%1d\s) = 40
// барабан хочу показывать так
//
// # Bx | Bx | Bx
// #time|time|time
//
image_init();
image_draw_borders();
char tmp[64];
sprintf(tmp, "Lock1=%02d Lock2=%02d", robot1_lock_zone, robot2_lock_zone);
image_insert_sprite(0, 2, tmp);
int barrels_count = 0, barrels_time = 0;
static int max_time = 0;
for (int i = 0; i < BARRELS_COUNT; i++) {
if (barrels[i].flags.is_exist) {
barrels_count++;
if (barrels[i].zone <= ZONE_LOAD_2 || barrels[i].zone == ZONE_PASSIVATION || barrels[i].zone == ZONE_UNLOAD) {
continue;
}
if (barrels[i].flags.robot == 0 && barrels[i].software_timer < 0) {
// время отрицательное, вычитаем его чтобы убрать минус
barrels_time -= barrels[i].software_timer;
}
}
}
if (max_time < barrels_time) {
max_time = barrels_time;
}
sprintf(tmp, "barrels=%02d time=%04d max_time=%04d", barrels_count, barrels_time, max_time);
image_insert_sprite(0, 25, tmp);
// рисование бочек
for (int i = 0; i < BARRELS_COUNT; i++) {
const auto& b = barrels[i];
if (b.flags.is_exist) {
if (b.flags.is_up) {
sprintf(tmp, " B%d", i);
image_insert_sprite(4, (b.zone * 5) + 1, tmp);
} else {
sprintf(tmp, " B%d\n%04d", i, b.software_timer);
image_insert_sprite(5, (b.zone * 5) + 1, tmp);
}
}
}
// рисуем роботов
if (hla_robot1_en) {
sprintf(tmp, "R1");
image_insert_sprite(2 + (robot1.mz.is_up ? 0 : 2),
(robot1.dx.current_zone * 5) + 2 + (robot1_offset_pos * 2),
tmp);
}
if (hla_robot2_en) {
sprintf(tmp, "R2");
image_insert_sprite(2 + (robot2.mz.is_up ? 0 : 2),
(robot2.dx.current_zone * 5) + 2 + (robot2_offset_pos * 2),
tmp);
}
for (const auto & r : buffer) {
write(sock_fd, r, COLS);
send_str("\n");
}
}
static void open_socket() {
sockaddr_in serv_addr{};
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0) {
printf("\n Socket creation error \n");
exit(-1);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(40000);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
printf("\nInvalid address/ Address not supported \n");
exit(-1);
}
if (connect(sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
printf("Connection Failed \n");
exit(-1);
}
}
int main() {
open_socket();
current_tic = 0;
const char* message = nullptr;
while (true) {
_scheduler_software_timer = 1;
button_load = 1;
robot_main();
scheduler_main();
send_str("\033c");
showAll();
if (message) {
std::cout << message << std::endl;
send_str(message);
send_str("\n");
}
send_str("cmd >> ");
std::string in;
while (true) {
char tmp[2] = {0, 0};
ssize_t res = read(sock_fd, tmp, 1);
if (res < 0) {
exit(-1);
}
if (res == 1) {
if (tmp[0] == '\n') {
break;
}
in.append(tmp);
}
}
if (in == "q") {
break;
}
if (in.empty()) {
// просто продолжаем циклы
message = "Continue...";
} else {
if (in == "u") {
button_unload = 1;
message = "Нажата кнопка выгрузки";
} else if (in == "1") {
button_unload_end = 1;
message = "Нажата кнопка загрузки 1";
} else if (in == "2") {
button_load = 1;
message = "Нажата кнопка загрузки 2";
} else {
message = "Неизвестная команда. q - выход, u - выгрузка, 1 - загрузка 1, 2 - загрузка 2";
}
}
current_tic++;
}
close(sock_fd);
return 0;
}