правки nti ===== > Добавить в api про Producer Consumer accumulator Receiver Transmitter > `accumulator.failed` `accumulator.charge` `accumulator.capacity` `accumulator.empty` `accumulator.full` > все данные есть library/monitor/challengemonitorruntime.cpp > добавить в API аппарата или Редактирование сценария типа “Симуляция”: Скрипт проверки очень схож со скриптами которые пишут в качестве решения. Структура программы так-же состоит из setup() и loop(), и есть доступ ко всему API аппарата `spacecraft` и характеристикам аппарата, в независимости от наличия сенсоров. `spacecraft.motion.angular_velocity` `spacecraft.motion.position` `spacecraft.motion.linear_velocity` `spacecraft.motion.orientation` `spacecraft.motion.location` `spacecraft.thermodynamics.temperature` `spacecraft.electrics.accumulator_charge` `spacecraft.electrics.accumulator_capacity` `spacecraft.electrics.power_production` `spacecraft.electrics.power_consumption` `spacecraft.electrics.power_balance` Помимо этого есть объект `runtime` который имеет методы: `add_score(name, amount)` добавляет турнирные баллы. 2 поля, первое - внутреннее уникальное имя части, второе, кол-во баллов для добавления ![](https://i.imgur.com/4Bhgzq7.png) Подсказка: части следуют в порядке добавления. Для правильной номерации можно добавить 0 баллов в функции setup в нужном порядке `add_log_entry(log)` добавляет строчку в лог, полезно при отладке или для отображения более полной картины ![](https://i.imgur.com/aBpmo9x.png) `add_achievement(achievement)` добавляет достижение, они могут обозначать важные этапы решения задачи ![](https://i.imgur.com/2liXVhe.png) ## Примеры Скриптов Проверяет стабилизацию в чекпоинтах ``` 'use strict'; let first_checkpoint = false; let second_checkpoint = false; function radians(angle) { return angle * Math.PI / 180; } function setup() { runtime.add_score("default", 0.0); runtime.add_score("v", 0.0); } var end_speed = 0.2; function loop() { let spacecraft = world.spacecrafts[0]; if (!spacecraft.active) { return; } let flight_time = world.flight_time; // let angular_velocity = spacecraft.motion.angular_velocity; let angular_velocity = [spacecraft.devices[1].functions[0].angular_velocity, spacecraft.devices[1].functions[1].angular_velocity, spacecraft.devices[1].functions[2].angular_velocity]; if (!first_checkpoint) { if (flight_time >= 660.0) { let maximum = Math.max(Math.abs(angular_velocity[0]), Math.abs(angular_velocity[1])); if (maximum <= radians(1.0)) { runtime.add_score("default", 1.0); if (maximum <= radians(0.1)) { runtime.add_score("default", 1.0); if (maximum <= radians(0.01)) { runtime.add_score("default", 3.0); } } } let vel_2 = Math.abs(angular_velocity[2] - end_speed); if (vel_2 <= radians(1.0)) { runtime.add_score("v", 2.0); if (vel_2 <= radians(0.1)) { runtime.add_score("v", 2.0); if (vel_2 <= radians(0.01)) { runtime.add_score("v", 6.0); } } } first_checkpoint = true; } } if (!second_checkpoint) { if (flight_time >= 3600.0) { let maximum = Math.max(Math.abs(angular_velocity[0]), Math.abs(angular_velocity[1])); if (maximum <= radians(1.0)) { runtime.add_score("default", 1.0); if (maximum <= radians(0.1)) { runtime.add_score("default", 1.0); if (maximum <= radians(0.01)) { runtime.add_score("default", 3.0); } } } let vel_2 = Math.abs(angular_velocity[2] - end_speed); if (vel_2 <= radians(1.0)) { runtime.add_score("v", 2.0); if (vel_2 <= radians(0.1)) { runtime.add_score("v", 2.0); if (vel_2 <= radians(0.01)) { runtime.add_score("v", 6.0); } } } second_checkpoint = true; } } } ``` Работа с Producer, Consumer, Receiver, Transmitter ``` 'use strict'; let MAX_HEIGHT = 3000000.0; let PACKET_SIZE = 100; let MAX_CHUNK_SIZE = Math.round(3600 * runtime.tick); let PREAMBLE = [0xde, 0xad, 0xbe, 0xef]; let produced_storage = new Map(); let produced_index = -1; let consumed_queue = []; let score = 0.0; function radians(angle) { return angle * Math.PI / 180; } function make_coords(latitude, longitude) { return {latitude: radians(latitude), longitude: radians(longitude)}; } function calculate_elevation(station_location, spacecraft_location) { let height = spacecraft_location[2]; let radius = world.environment.earth.radius; let coords_1 = make_coords(station_location[0], station_location[1]); let coords_2 = make_coords(spacecraft_location[0], spacecraft_location[1]); let cos_angle = Math.cos(coords_1.latitude) * Math.cos(coords_2.latitude); cos_angle *= Math.cos(coords_1.longitude - coords_2.longitude); cos_angle += Math.sin(coords_1.latitude) * Math.sin(coords_2.latitude); let sin_angle = Math.sqrt(1.0 - cos_angle * cos_angle); let x = radius * sin_angle; let y = radius * (1.0 - cos_angle) + height; return [Math.atan2(y, x) - Math.acos(cos_angle), Math.sqrt(x * x + y * y)]; } function check_visibility(station_location, spacecraft_location) { let height = spacecraft_location[2]; if (height > MAX_HEIGHT) { return false; } let elevation = calculate_elevation(station_location,spacecraft_location); if (elevation[0] < Math.PI / 9) { return false; } return true; } function setup() { runtime.add_score("default", 0.0); } function loop() { let produced_packet = null; let flight_time = world.flight_time; if (Math.floor(flight_time) > produced_index) { produced_index = Math.floor(flight_time); produced_packet = new Uint8Array(PACKET_SIZE); produced_packet.set(PREAMBLE, 0); produced_packet.set([(produced_index >> 0) & 0xff, (produced_index >> 8) & 0xff, (produced_index >> 16) & 0xff, (produced_index >> 24) & 0xff], 4); produced_packet.set(runtime.random(92), 8); produced_storage.set(produced_index, Array.from(produced_packet)); } let chunk_in_flight = null; let spacecraft = world.spacecrafts[0]; if (spacecraft.active) { let producer = spacecraft.devices[1].functions[0]; if (producer.active && (produced_packet !== null)) { producer.push_queue(0, produced_packet); } let transmitter = spacecraft.devices[0].functions[0]; if (transmitter.active) { chunk_in_flight = transmitter.pull_queue(0, MAX_CHUNK_SIZE); } } if (chunk_in_flight !== null) { for (let i = 0; i < chunk_in_flight.length; i++) { let rolls = runtime.random(8); for (let j = 0; j < 8; j++) { if (rolls[j] < 3) { chunk_in_flight[i] ^= 1 << j; } } } } let consumed_chunk = null; let station = world.stations[0]; if (station.active) { let visible = false; if (spacecraft.active) { visible = check_visibility(station.motion.location, spacecraft.motion.location); } let receiver = station.devices[0].functions[0]; if (receiver.active && visible && (chunk_in_flight !== null)) { receiver.push_queue(0, chunk_in_flight); } let consumer = station.devices[1].functions[0]; if (consumer.active) { consumed_chunk = consumer.pull_queue(0, MAX_CHUNK_SIZE); } } if (consumed_chunk !== null) { consumed_queue.push(...consumed_chunk); while (consumed_queue.length >= PACKET_SIZE) { if ((consumed_queue[0] != PREAMBLE[0]) || (consumed_queue[1] != PREAMBLE[1]) || (consumed_queue[2] != PREAMBLE[2]) || (consumed_queue[3] != PREAMBLE[3])) { consumed_queue.shift(); continue; } let consumed_index = (consumed_queue[4] << 0) + (consumed_queue[5] << 8) + (consumed_queue[6] << 16) + (consumed_queue[7] << 24); if (!produced_storage.has(consumed_index)) { consumed_queue.splice(0, 4); continue; } let produced_content = produced_storage.get(consumed_index); let consumed_content = consumed_queue.slice(0, PACKET_SIZE); if (consumed_content.toString() != produced_content.toString()) { consumed_queue.splice(0, 4); continue; } score += 0.00048828125; if (score <= 30.0) { runtime.add_score("default", 0.00048828125); } produced_storage.delete(consumed_index); consumed_queue.splice(0, PACKET_SIZE); } } } ```