All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.ericmedvet.mrsim2d.buildable.builders.Miscs Maven / Gradle / Ivy

The newest version!
/*-
 * ========================LICENSE_START=================================
 * mrsim2d-buildable
 * %%
 * Copyright (C) 2020 - 2024 Eric Medvet
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =========================LICENSE_END==================================
 */

package io.github.ericmedvet.mrsim2d.buildable.builders;

import io.github.ericmedvet.jnb.core.Discoverable;
import io.github.ericmedvet.jnb.core.Param;
import io.github.ericmedvet.mrsim2d.core.Snapshot;
import io.github.ericmedvet.mrsim2d.core.engine.Engine;
import io.github.ericmedvet.mrsim2d.core.geometry.BoundingBox;
import io.github.ericmedvet.mrsim2d.core.geometry.Point;
import io.github.ericmedvet.mrsim2d.core.tasks.AgentsObservation;
import io.github.ericmedvet.mrsim2d.core.tasks.AgentsOutcome;
import io.github.ericmedvet.mrsim2d.core.tasks.Task;
import io.github.ericmedvet.mrsim2d.viewer.ComponentDrawer;
import io.github.ericmedvet.mrsim2d.viewer.Drawer;
import io.github.ericmedvet.mrsim2d.viewer.Drawers;
import io.github.ericmedvet.mrsim2d.viewer.EmbodiedAgentsExtractor;
import io.github.ericmedvet.mrsim2d.viewer.Framer;
import io.github.ericmedvet.mrsim2d.viewer.TaskVideoBuilder;
import io.github.ericmedvet.mrsim2d.viewer.drawers.ComponentsDrawer;
import io.github.ericmedvet.mrsim2d.viewer.drawers.EngineProfilingDrawer;
import io.github.ericmedvet.mrsim2d.viewer.drawers.InfoDrawer;
import io.github.ericmedvet.mrsim2d.viewer.drawers.NFCDrawer;
import io.github.ericmedvet.mrsim2d.viewer.drawers.StackedMultipliedDrawer;
import io.github.ericmedvet.mrsim2d.viewer.drawers.actions.AttractAnchor;
import io.github.ericmedvet.mrsim2d.viewer.drawers.actions.SenseDistanceToBody;
import io.github.ericmedvet.mrsim2d.viewer.drawers.actions.SenseRotatedVelocity;
import io.github.ericmedvet.mrsim2d.viewer.drawers.bodies.AnchorableBodyDrawer;
import io.github.ericmedvet.mrsim2d.viewer.drawers.bodies.RigidBodyDrawer;
import io.github.ericmedvet.mrsim2d.viewer.drawers.bodies.RotationalJointDrawer;
import io.github.ericmedvet.mrsim2d.viewer.drawers.bodies.SoftBodyDrawer;
import io.github.ericmedvet.mrsim2d.viewer.drawers.bodies.UnmovableBodyDrawer;
import io.github.ericmedvet.mrsim2d.viewer.framers.AllAgentsFramer;
import io.github.ericmedvet.mrsim2d.viewer.framers.StaticFramer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ServiceLoader;
import java.util.function.Function;
import java.util.function.Supplier;

@Discoverable(prefixTemplate = "sim|s")
public class Miscs {

  private Miscs() {}

  public enum MiniAgentInfo {
    NONE,
    VELOCITY,
    BRAINS
  }

  @SuppressWarnings("unused")
  public static Framer allAgentsFramer(
      @Param(value = "enlargement", dD = 1.5) double enlargement,
      @Param(value = "followTime", dD = 2) double followTime) {
    return new AllAgentsFramer(enlargement).largest(followTime);
  }

  @SuppressWarnings("unused")
  public static Function drawer(
      @Param(value = "framer", dNPM = "s.allAgentsFramer()") Framer framer,
      @Param(value = "profilingTime", dD = 1) double profilingTime,
      @Param(value = "miniWorldEnlargement", dD = 10) double miniWorldEnlargement,
      @Param(value = "miniWorld") boolean miniWorld,
      @Param(
              value = "components",
              dSs = {"unmovable_bodies", "soft_bodies", "rigid_bodies", "rotational_joints"})
          List components,
      @Param(value = "miniAgents", dS = "brains") MiniAgentInfo miniAgentInfo,
      @Param(value = "engineProfiling") boolean engineProfiling,
      @Param(value = "actions") boolean actions,
      @Param(value = "info", dB = true) boolean info,
      @Param(value = "nfc") boolean nfc) {
    return s -> {
      List componentDrawers = components.stream()
          .map(c -> switch (c) {
            case SOFT_BODIES -> new SoftBodyDrawer().andThen(new AnchorableBodyDrawer());
            case RIGID_BODIES -> new RigidBodyDrawer().andThen(new AnchorableBodyDrawer());
            case UNMOVABLE_BODIES -> new UnmovableBodyDrawer().andThen(new AnchorableBodyDrawer());
            case ROTATIONAL_JOINTS -> new RotationalJointDrawer().andThen(new AnchorableBodyDrawer());
          })
          .toList();
      Drawer baseDrawer = new ComponentsDrawer(componentDrawers, Snapshot::bodies).onLastSnapshot();
      Drawer nfcDrawer = new NFCDrawer();
      Drawer actionsDrawer = new ComponentsDrawer(
          List.of(new AttractAnchor(), new SenseDistanceToBody(), new SenseRotatedVelocity()),
          Snapshot::actionOutcomes);
      List thingsDrawers = new ArrayList<>();
      thingsDrawers.add(baseDrawer);
      if (actions) {
        thingsDrawers.add(actionsDrawer);
      }
      if (nfc) {
        thingsDrawers.add(nfcDrawer);
      }
      Drawer worldDrawer = Drawer.transform(framer, Drawer.of(Collections.unmodifiableList(thingsDrawers)));
      List drawers = new ArrayList<>(List.of(Drawer.clear(), worldDrawer));
      if (!miniAgentInfo.equals(MiniAgentInfo.NONE)) {
        drawers.add(new StackedMultipliedDrawer<>(
            switch (miniAgentInfo) {
              case BRAINS -> Drawers::simpleAgentWithBrainsIO;
              case VELOCITY -> Drawers::simpleAgentWithVelocities;
              default -> throw new IllegalStateException("Unexpected value: " + miniAgentInfo);
            },
            new EmbodiedAgentsExtractor(),
            0.25,
            0.05,
            StackedMultipliedDrawer.Direction.VERTICAL,
            Drawer.VerticalPosition.TOP,
            Drawer.HorizontalPosition.RIGHT));
      }
      if (miniWorld) {
        drawers.add(Drawer.clip(
            new BoundingBox(new Point(0.5d, 0.85d), new Point(0.99d, 0.99d)),
            Drawer.of(
                Drawer.clear(),
                Drawer.transform(
                    new AllAgentsFramer(miniWorldEnlargement).largest(2),
                    Drawer.of(new ComponentsDrawer(
                            List.of(
                                new UnmovableBodyDrawer(),
                                new RotationalJointDrawer(),
                                new SoftBodyDrawer(),
                                new RigidBodyDrawer()),
                            Snapshot::bodies)
                        .onLastSnapshot())))));
      }
      if (engineProfiling) {
        drawers.add(new EngineProfilingDrawer(
            profilingTime, Drawer.VerticalPosition.BOTTOM, Drawer.HorizontalPosition.LEFT));
      }
      if (info) {
        drawers.add(new InfoDrawer(s));
      }
      return Drawer.of(Collections.unmodifiableList(drawers));
    };
  }

  @SuppressWarnings("unused")
  public static Supplier engine() {
    return () -> ServiceLoader.load(Engine.class).findFirst().orElseThrow();
  }

  @SuppressWarnings("unused")
  public static Framer staticFramer(
      @Param("minX") double minX,
      @Param("maxX") double maxX,
      @Param("minY") double minY,
      @Param("maxY") double maxY) {
    return new StaticFramer(new BoundingBox(new Point(minX, minY), new Point(maxX, maxY)));
  }

  @SuppressWarnings("unused")
  public static > Function taskRunner(
      @Param("task") Task task,
      @Param(value = "engine", dNPM = "sim.engine()") Supplier engineSupplier) {
    return a -> task.run(a, engineSupplier.get());
  }

  @SuppressWarnings("unused")
  public static  TaskVideoBuilder taskVideoBuilder(
      @Param("task") Task task,
      @Param(value = "title", dS = "") String title,
      @Param(value = "drawer", dNPM = "sim.drawer()") Function drawerBuilder,
      @Param(value = "engine", dNPM = "sim.engine()") Supplier engineSupplier,
      @Param(value = "startTime", dD = 0) double startTime,
      @Param(value = "endTime", dD = Double.POSITIVE_INFINITY) double endTime,
      @Param(value = "frameRate", dD = 30) double frameRate) {
    return new TaskVideoBuilder<>(task, drawerBuilder, engineSupplier, title, startTime, endTime, frameRate);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy