/** * @file ProductionOrder.cpp * @author The ARTIS Development Team * See the AUTHORS or Authors.txt file */ /* * ARTIS - the multimodeling and simulation environment * This file is a part of the ARTIS environment * * Copyright (C) 2013-2023 ULCO http://www.univ-littoral.fr * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ProductionOrder.hpp" #include #include #include #include namespace artis::factory { void put_bits(uint8_t *buffer, ProductionOrder::Reference &reference, uint8_t data, uint8_t bit_number) { if (8 - reference._bit_index >= bit_number) { buffer[reference._byte_index] |= data << (8 - bit_number - reference._bit_index); reference._bit_index += bit_number; if (reference._bit_index == 8) { ++reference._byte_index; reference._bit_index = 0; } } else { buffer[reference._byte_index] |= data >> (bit_number - (8 - reference._bit_index)); ++reference._byte_index; reference._bit_index = bit_number - (8 - reference._bit_index); data &= 0xFF >> (8 - reference._bit_index); buffer[reference._byte_index] |= data << (8 - reference._bit_index); } } uint8_t get_bits(uint8_t const *buffer, const ProductionOrder::Reference &reference, uint8_t bit_number) { uint8_t data = 0; if (8 - reference._bit_index >= bit_number) { data = (uint8_t) (buffer[reference._byte_index] << reference._bit_index) >> (8 - bit_number); } else { uint8_t mask = ~(uint8_t) (0xFF << (8 - reference._bit_index)); data = (uint8_t) (buffer[reference._byte_index] & mask); data <<= bit_number - (8 - reference._bit_index); data |= (uint8_t) (buffer[reference._byte_index + 1] >> (8 - (bit_number - (8 - reference._bit_index)))); } return data; } void ProductionOrder::Reference::operator+=(uint8_t p) { _byte_index += (_bit_index + p) / 8; _bit_index += p; _bit_index %= 8; } ProductionOrder::ProductionOrder(uint8_t *buffer, std::size_t size) : _buffer(nullptr), _size(size), _bsize(0), _current_operation(nullptr) { _buffer = new uint8_t[size]; std::memcpy(_buffer, buffer, size); _bsize = (_buffer[BIT_NUMBER_POSITION] << 8) + _buffer[BIT_NUMBER_POSITION + 1]; update_operation(_buffer[INDEX_POSITION]); _is_finish = _buffer[INDEX_POSITION] + 1 >= _buffer[OPERATION_NUMBER_POSITION]; } ProductionOrder::ProductionOrder(uint16_t ID, uint16_t parent_ID, uint32_t due_date, uint16_t product_ID, const Program &program) : _is_finish(false) { Reference reference{0, 0}; std::size_t operation_number = 0; _bsize = HEADER_SIZE * 8; // size + index + operation number std::for_each(program.cbegin(), program.cend(), [this, &operation_number](const PoolMachineSequence &sequence) { _bsize += sequence._machines.size() * (MACHINE_SIZE + TYPE_SIZE); _bsize += POOL_SIZE + TYPE_SIZE; operation_number += sequence._machines.size() + 1; }); _size = _bsize / 8 + 1; _buffer = new uint8_t[_size]; memset(_buffer, 0, _size); // bit number _buffer[reference._byte_index++] = (uint8_t) (_bsize >> 8); _buffer[reference._byte_index++] = (uint8_t) (_bsize & 0xFF); // ID _buffer[reference._byte_index++] = (uint8_t) (ID >> 8); _buffer[reference._byte_index++] = (uint8_t) (ID & 0xFF); // parent ID _buffer[reference._byte_index++] = (uint8_t) (parent_ID >> 8); _buffer[reference._byte_index++] = (uint8_t) (parent_ID & 0xFF); // due date _buffer[reference._byte_index++] = (uint8_t) (due_date >> 24); _buffer[reference._byte_index++] = (uint8_t) ((due_date >> 16) & 0xFF); _buffer[reference._byte_index++] = (uint8_t) ((due_date >> 8) & 0xFF); _buffer[reference._byte_index++] = (uint8_t) (due_date & 0xFF); // product ID _buffer[reference._byte_index++] = (uint8_t) (product_ID >> 8); _buffer[reference._byte_index++] = (uint8_t) (product_ID & 0xFF); // index _buffer[reference._byte_index++] = (uint8_t) (0); assert(operation_number < 256); // operation number _buffer[reference._byte_index++] = (int8_t) (operation_number); // operations {change pool ; N change machine} * M std::for_each(program.cbegin(), program.cend(), [this, &reference](const PoolMachineSequence &sequence) { const ChangePool &operation = sequence._pool; assert(operation._pool_id < (1 << POOL_SIZE)); put_bits(_buffer, reference, CHANGE_POOL_TYPE, TYPE_SIZE); put_bits(_buffer, reference, operation._pool_id, POOL_SIZE); std::for_each(sequence._machines.cbegin(), sequence._machines.cend(), [this, &reference](const ChangeMachine &operation) { assert(operation._machine_id < (1 << MACHINE_SIZE)); put_bits(_buffer, reference, CHANGE_MACHINE_TYPE, TYPE_SIZE); put_bits(_buffer, reference, operation._machine_id, MACHINE_SIZE); }); }); // current operation _current_operation = std::make_unique(program.begin()->_pool); } std::unique_ptr ProductionOrder::get_operation(uint8_t index) const { Reference reference{HEADER_SIZE, 0}; uint8_t operation_type = get_bits(_buffer, reference, TYPE_SIZE); reference += TYPE_SIZE; while (index > 0) { switch (operation_type) { case CHANGE_POOL_TYPE: { reference += POOL_SIZE; break; } case CHANGE_MACHINE_TYPE: { reference += MACHINE_SIZE; break; } default: assert(false); } operation_type = get_bits(_buffer, reference, TYPE_SIZE); reference += TYPE_SIZE; --index; } switch (operation_type) { case CHANGE_POOL_TYPE: { return std::make_unique(get_bits(_buffer, reference, POOL_SIZE)); } case CHANGE_MACHINE_TYPE: { return std::make_unique(get_bits(_buffer, reference, MACHINE_SIZE)); } } assert(false); return {}; } std::unique_ptr ProductionOrder::last_operation() const { return get_operation(operation_number() - 1); } void ProductionOrder::update_operation(uint8_t index) { _current_operation = get_operation(index); } void ProductionOrder::next() { if (_buffer[INDEX_POSITION] + 1 < _buffer[OPERATION_NUMBER_POSITION]) { update_operation(++_buffer[INDEX_POSITION]); } else { _current_operation.reset(nullptr); _is_finish = true; } } std::unique_ptr ProductionOrder::previous_operation() const { return get_operation(_buffer[INDEX_POSITION] - 1); } std::string ProductionOrder::to_string() const { std::string str = "[ "; uint16_t ID = (_buffer[ID_POSITION] << 8) + _buffer[ID_POSITION + 1]; uint16_t parentID = (_buffer[PARENT_ID_POSITION] << 8) + _buffer[PARENT_ID_POSITION + 1]; str += std::to_string(ID); if (ID != parentID) { str += + "/" + std::to_string(parentID) +" ][ "; } str += " ][ "; for (uint8_t i = 0; i < _buffer[OPERATION_NUMBER_POSITION]; ++i) { if (_buffer[INDEX_POSITION] == i) { str += "<"; } str += get_operation(i)->to_string(); if (_buffer[INDEX_POSITION] == i) { str += ">"; } str += " "; } str += "]"; return str; } } // namespace artis::factory