правки 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 поля, первое - внутреннее уникальное имя части, второе, кол-во баллов для добавления

Подсказка: части следуют в порядке добавления. Для правильной номерации можно добавить 0 баллов в функции setup в нужном порядке
`add_log_entry(log)` добавляет строчку в лог, полезно при отладке или для отображения более полной картины

`add_achievement(achievement)` добавляет достижение, они могут обозначать важные этапы решения задачи

## Примеры Скриптов
Проверяет стабилизацию в чекпоинтах
```
'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);
}
}
}
```