class CompatibilityScheduler implements Scheduler, VizArchitecture {

    private final float updateFpsLimit = 5f;
    private final Object worldLock = new Object();
    //States
    AtomicBoolean animating = new AtomicBoolean();
    AtomicBoolean cameraMoved = new AtomicBoolean();
    AtomicBoolean mouseMoved = new AtomicBoolean();
    AtomicBoolean startDrag = new AtomicBoolean();
    AtomicBoolean drag = new AtomicBoolean();
    AtomicBoolean stopDrag = new AtomicBoolean();
    AtomicBoolean mouseClick = new AtomicBoolean();
    //Architeture
    private GraphDrawable graphDrawable;
    private CompatibilityEngine engine;
    private VizConfig vizConfig;
    //Animators
    private BasicFPSAnimator displayAnimator;
    private BasicFPSAnimator updateAnimator;
    private float displayFpsLimit = 30f;

    @Override
    public void initArchitecture() {<FILL_FUNCTION_BODY>}

    @Override
    public synchronized void start() {
        if (displayAnimator != null) {
            displayAnimator.shutdown();
        }
        if (updateAnimator != null) {
            updateAnimator.shutdown();
        }
        displayAnimator = new BasicFPSAnimator(new Runnable() {
            @Override
            public void run() {
                graphDrawable.display();
            }
        }, worldLock, "DisplayAnimator", displayFpsLimit);
        displayAnimator.start();

        updateAnimator = new BasicFPSAnimator(new Runnable() {
            @Override
            public void run() {
                updateWorld();
            }
        }, worldLock, "UpdateAnimator", updateFpsLimit);
        updateAnimator.start();
    }

    @Override
    public synchronized void stop() {
        updateAnimator.shutdown();
        displayAnimator.shutdown();

        cameraMoved.set(false);
        mouseMoved.set(false);
        startDrag.set(false);
        drag.set(false);
        stopDrag.set(false);
        mouseClick.set(false);
    }

    @Override
    public boolean isAnimating() {
        return displayAnimator != null && displayAnimator.isAnimating();
    }

    @Override
    public void display(GL2 gl, GLU glu) {
        //Boolean vals
        boolean execMouseClick = mouseClick.getAndSet(false);
        boolean execMouseMove = mouseMoved.getAndSet(false);
        boolean execDrag = drag.get() || startDrag.get() || stopDrag.get();

        if (cameraMoved.getAndSet(false)) {
            graphDrawable.setCameraPosition(gl, glu);

            engine.getOctree().updateVisibleOctant(gl);
            //Objects iterators in octree are ready

            //Task MODEL - LOD
            engine.updateLOD();
        }

        //Task SELECTED
        if (execMouseMove) {
            engine.mouseMove();
            engine.updateSelection(gl, glu);
        } else if (execDrag) {
            //Drag
            if (stopDrag.getAndSet(false)) {
                engine.stopDrag();
            }
            if (startDrag.getAndSet(false)) {
                engine.startDrag();
            }
            if (drag.getAndSet(false)) {
                engine.mouseDrag();
            }
        }

        //Task AFTERSELECTION
        if (execMouseClick) {
            engine.mouseClick();
        }

        //Display
        engine.beforeDisplay(gl, glu);
        engine.display(gl, glu);
        engine.afterDisplay(gl, glu);
    }

    @Override
    public void updateWorld() {
        if (engine.updateWorld()) {
            cameraMoved.set(true);
            mouseMoved.set(true);
        }
    }

    @Override
    public void updatePosition() {
//        if (objectsMoved.getAndSet(false)) {
//            engine.updateObjectsPosition();
//            cameraMoved.set(true);
//        }
    }

    @Override
    public void requireUpdateVisible() {
        cameraMoved.set(true);
    }

    @Override
    public void requireUpdateSelection() {
        mouseMoved.set(true);
    }

    @Override
    public void requireStartDrag() {
        startDrag.set(true);
    }

    @Override
    public void requireDrag() {
        drag.set(true);
    }

    @Override
    public void requireStopDrag() {
        stopDrag.set(true);
    }

    @Override
    public void requireMouseClick() {
        mouseClick.set(true);
    }

    @Override
    public float getFps() {
        return displayFpsLimit;
    }

    @Override
    public void setFps(float maxFps) {
        this.displayFpsLimit = maxFps;
        if (displayAnimator != null) {
            displayAnimator.setFps(maxFps);
        }
    }
}

        this.graphDrawable = VizController.getInstance().getDrawable();
        this.engine = (CompatibilityEngine) VizController.getInstance().getEngine();
        this.vizConfig = VizController.getInstance().getVizConfig();
    
<no_super_class>