// Path: src/main/java/com/codegame/codeseries/notreal2d/listener/PositionListener.java
// public interface PositionListener {
//     /**
//      * Physics engine iterates over all registered position listeners in some order and invokes this method before
//      * changing position. If any listener returns {@code false}, it cancels all remaining method calls and the change
//      * itself.
//      * <p>
//      * Any {@code oldPosition} changes in the method will be ignored.
//      * Any {@code newPosition} changes in the method will be saved and used to update associated object after last
//      * iteration (all listeners should return {@code true}).
//      *
//      * @param oldPosition current position
//      * @param newPosition next position
//      * @return {@code true} iff physics engine should continue to change position
//      */
//     boolean beforeChangePosition(@Nonnull Point2D oldPosition, @Nonnull Point2D newPosition);
// 
//     /**
//      * Physics engine iterates over all registered position listeners in some order and invokes this method after
//      * changing position.
//      * <p>
//      * Any {@code oldPosition} changes in the method will be ignored.
//      * Any {@code newPosition} changes in the method will be ignored.
//      *
//      * @param oldPosition previous position
//      * @param newPosition current position
//      */
//     void afterChangePosition(@Nonnull Point2D oldPosition, @Nonnull Point2D newPosition);
// }


import com.codeforces.commons.geometry.Point2D;
import com.codeforces.commons.geometry.Vector2D;
import com.codeforces.commons.text.StringUtil;
import com.codegame.codeseries.notreal2d.listener.PositionListener;
import javax.annotation.Nonnull;
import java.util.*;
import static com.codeforces.commons.math.Math.DOUBLE_PI;
import static com.codeforces.commons.math.Math.PI;

            }
        }

        this.position = this.new ListeningPoint2D(newPosition);

        if (positionListenerEntries != null) {
            for (PositionListenerEntry positionListenerEntry : positionListenerEntries) {
                positionListenerEntry.listener.afterChangePosition(oldPosition.copy(), newPosition.copy());
            }
        }
    }

    public double getAngle() {
        return angle;
    }

    public void setAngle(double angle) {
        this.angle = angle;
    }

    public void normalizeAngle() {
        while (angle > PI) {
            angle -= DOUBLE_PI;
        }

        while (angle < -PI) {
            angle += DOUBLE_PI;
        }
    }


// Path: src/main/java/com/codegame/codeseries/notreal2d/listener/PositionListener.java
// public interface PositionListener {
//     /**
//      * Physics engine iterates over all registered position listeners in some order and invokes this method before
//      * changing position. If any listener returns {@code false}, it cancels all remaining method calls and the change
//      * itself.
//      * <p>
//      * Any {@code oldPosition} changes in the method will be ignored.
//      * Any {@code newPosition} changes in the method will be saved and used to update associated object after last
//      * iteration (all listeners should return {@code true}).
//      *
//      * @param oldPosition current position
//      * @param newPosition next position
//      * @return {@code true} iff physics engine should continue to change position
//      */
//     boolean beforeChangePosition(@Nonnull Point2D oldPosition, @Nonnull Point2D newPosition);
// 
//     /**
//      * Physics engine iterates over all registered position listeners in some order and invokes this method after
//      * changing position.
//      * <p>
//      * Any {@code oldPosition} changes in the method will be ignored.
//      * Any {@code newPosition} changes in the method will be ignored.
//      *
//      * @param oldPosition previous position
//      * @param newPosition current position
//      */
//     void afterChangePosition(@Nonnull Point2D oldPosition, @Nonnull Point2D newPosition);
// }


// Path: src/main/java/com/codegame/codeseries/notreal2d/StaticState.java
import com.codeforces.commons.geometry.Point2D;
import com.codeforces.commons.geometry.Vector2D;
import com.codeforces.commons.text.StringUtil;
import com.codegame.codeseries.notreal2d.listener.PositionListener;
import javax.annotation.Nonnull;
import java.util.*;
import static com.codeforces.commons.math.Math.DOUBLE_PI;
import static com.codeforces.commons.math.Math.PI;

            }
        }

        this.position = this.new ListeningPoint2D(newPosition);

        if (positionListenerEntries != null) {
            for (PositionListenerEntry positionListenerEntry : positionListenerEntries) {
                positionListenerEntry.listener.afterChangePosition(oldPosition.copy(), newPosition.copy());
            }
        }
    }

    public double getAngle() {
        return angle;
    }

    public void setAngle(double angle) {
        this.angle = angle;
    }

    public void normalizeAngle() {
        while (angle > PI) {
            angle -= DOUBLE_PI;
        }

        while (angle < -PI) {
            angle += DOUBLE_PI;
        }
    }


    public void registerPositionListener(@Nonnull PositionListener listener, @Nonnull String name, double priority) {
