<commit_before>package;

import flixel.FlxG;
import flixel.FlxSprite;
import flixel.FlxObject;
import flixel.util.FlxColor;
import flixel.plugin.MouseEventManager;

import Constants.*;
import PlayState;
import IceCream;
import Cup;
import Device;
import Doser;
import Scale;

class ConveyorTile extends FlxSprite {
    private var _direction:Int;
    private var _rolling:Bool;
    private var _type:Int;

    // When the tile is the end of conveyor belt, it has to handle ice creams in
    // a different way.
    private var _isEnd:Bool;
    private var _truck:FlxSprite;

    // When fail to deliver ice cream to next tile, this flag is set to true.
    private var _retryDeliver:Bool;

    // Tile grid used to communicate to neighbor tiles.
    private var _grid:Array<Array<ConveyorTile>>;

    // Coordenates to next tile following _direction.
    private var _targetI:Int;
    private var _targetJ:Int;

    // Coordinates in tile matrix.
    public var i:Int;
    public var j:Int;

    // Callback function to add objects to Playstate.
    private var _addIceCream:IceCream->Void;
    private var _addDevice:Device->Void;
    private var _addSprite:FlxSprite->Void;

    private var _device:Device;
    private var _item:IceCream;

    /**
     * Position i,j with respect of tile grid. The screen coordinates x,y will
     * be calculated automaticaly latter in init();
     */
    public function new(I:Int, J:Int, type:Int, grid:Array<Array<ConveyorTile>>,
                        direction:Int = SW, animationFrames:Array<Int> = null,
                        addIceCreamCallback:IceCream->Void = null,
                        addDeviceCallback:Device->Void = null,
                        addSpriteCallback:FlxSprite->Void = null) {

        super(0, 0);
        init(I, J, type, grid, direction, animationFrames, addIceCreamCallback,
             addDeviceCallback, addSpriteCallback);
    }

    public function init(I:Int, J:Int, type:Int,
                         grid:Array<Array<ConveyorTile>>, direction:Int = SW,
                         animationFrames:Array<Int> = null,
                         addIceCreamCallback:IceCream->Void = null,
                         addDeviceCallback:Device->Void = null,
                         addSpriteCallback:FlxSprite->Void = null) {
        i = I;
        j = J;
        _grid = grid;
        _direction = direction;
        _type = type;
        _isEnd = false;
        _retryDeliver = false;
        _addIceCream = addIceCreamCallback;
        _addDevice = addDeviceCallback;
        _addSprite = addSpriteCallback;

        x = (TILE_WIDTH / 2.0) * (j - i) + X_OFFSET;
        y = (i + j) * (TILE_HEIGHT / 2.0) + Y_OFFSET;

        // TODO: this moves the hitbox. It sholud be the new origin (position)
        //       of the sprite. But origin in Flixel is used only for rotation.
        //       Best approach would be create MySprite which extends FlXSprite
        //       and handle offset the way it is needed.
        offset.set(TILE_WIDTH / 2.0, TILE_HEIGHT / 2.0);

        // loadGraphic(PATH, ANIMATED, FRAME_WIDTH, FRAME_HEIGHT)
        loadGraphic("assets/images/conveyor.png", true, TILE_FRAME_WIDTH,
                    TILE_FRAME_HEIGHT);
        antialiasing = true;

        setFacingFlip(FlxObject.LEFT, false, false);
        setFacingFlip(FlxObject.RIGHT, true, false);
        facing = FlxObject.LEFT;

        _rolling = false;
        setTile(direction, _type);
        initAnimations(_type, animationFrames);

        // Setup the mouse events
        // add(SPRITE, ON_MOUSE_DOWN, ON_MOUSE_UP, ON_MOUSE_OVER, ON_MOUSE_OUT)
        MouseEventManager.add(this, null, onUp, onOver, onOut);
    }

    public function setTile(direction:Int, type:Int):Void {
        if (type == HIDDEN) {
            active = visible = false;
        }
        else {
            active = visible = true;
        }

        if (_direction == SE || _direction == NE) {
            facing = FlxObject.RIGHT;
        }

        _targetI = i;
        _targetJ = j;
        if (_type == GROUND) {
            return;
        }

        setDirectionTarget(_direction);
    }

    private function initAnimations(type:Int, animationFrames:Array<Int>):Void {
        animation.destroyAnimations();

        if (animationFrames != null) {
            // animation.add(NAME, FRAMES, FRAME_RATE, SHOULD_LOOP)
            animation.add("idle", [animationFrames[0]], 1, false);
            animation.play("idle");

            if (type != HIDDEN && type != GROUND) {
                animation.add("roll", animationFrames, 4, true);
            }
        }
    }

    override public function update():Void {
        if (_retryDeliver) {
            deliverIceCream();
        }
        super.update();
    }

    public function turnOn():Void {
        if (!_rolling) {
            _rolling = true;
            if (animation.paused) {
                animation.resume();
            } else {
                animation.play("roll");
            }
            if (_device != null) {
                _device.turnOn();
            }
        }
    }

    public function turnOff():Void {
        if (_rolling) {
            _rolling = false;
            animation.pause();
            if (_device != null) {
                _device.turnOff();
            }
        }
    }

    public function receiveIceCream(item:IceCream):Void {
        if (item == null) {
            trace("Received null ice cream.");
        }
        else if (_item != null) {
            // Should not accept other ice cream.
            item.setShaking(true);
        }
        else {
            // Every thing is fine. Accepting ice cream.
            _item = item;
            _item.setGridPosition(i, j);
            _item.direction = _direction;
        }
    }

    public function deliverIceCream():Void {
        if (_item == null) {
            // No ice cream to deliver.
            _retryDeliver = false;
            return;
        }

        // If there is a device in this tile, it transforms the ice cream.
        if (_device != null) {
            _device.transformIceCream(_item);
        }<commit_msg>Bug Fix: no more super ice cream stack.<commit_after>package;

import flixel.FlxG;
import flixel.FlxSprite;
import flixel.FlxObject;
import flixel.util.FlxColor;
import flixel.plugin.MouseEventManager;

import Constants.*;
import PlayState;
import IceCream;
import Cup;
import Device;
import Doser;
import Scale;

class ConveyorTile extends FlxSprite {
    private var _direction:Int;
    private var _rolling:Bool;
    private var _type:Int;

    // When the tile is the end of conveyor belt, it has to handle ice creams in
    // a different way.
    private var _isEnd:Bool;
    private var _truck:FlxSprite;

    // When fail to deliver ice cream to next tile, this flag is set to true.
    private var _retryDeliver:Bool;

    // Tile grid used to communicate to neighbor tiles.
    private var _grid:Array<Array<ConveyorTile>>;

    // Coordenates to next tile following _direction.
    private var _targetI:Int;
    private var _targetJ:Int;

    // Coordinates in tile matrix.
    public var i:Int;
    public var j:Int;

    // Callback function to add objects to Playstate.
    private var _addIceCream:IceCream->Void;
    private var _addDevice:Device->Void;
    private var _addSprite:FlxSprite->Void;

    private var _device:Device;
    private var _item:IceCream;

    /**
     * Position i,j with respect of tile grid. The screen coordinates x,y will
     * be calculated automaticaly latter in init();
     */
    public function new(I:Int, J:Int, type:Int, grid:Array<Array<ConveyorTile>>,
                        direction:Int = SW, animationFrames:Array<Int> = null,
                        addIceCreamCallback:IceCream->Void = null,
                        addDeviceCallback:Device->Void = null,
                        addSpriteCallback:FlxSprite->Void = null) {

        super(0, 0);
        init(I, J, type, grid, direction, animationFrames, addIceCreamCallback,
             addDeviceCallback, addSpriteCallback);
    }

    public function init(I:Int, J:Int, type:Int,
                         grid:Array<Array<ConveyorTile>>, direction:Int = SW,
                         animationFrames:Array<Int> = null,
                         addIceCreamCallback:IceCream->Void = null,
                         addDeviceCallback:Device->Void = null,
                         addSpriteCallback:FlxSprite->Void = null) {
        i = I;
        j = J;
        _grid = grid;
        _direction = direction;
        _type = type;
        _isEnd = false;
        _retryDeliver = false;
        _addIceCream = addIceCreamCallback;
        _addDevice = addDeviceCallback;
        _addSprite = addSpriteCallback;

        x = (TILE_WIDTH / 2.0) * (j - i) + X_OFFSET;
        y = (i + j) * (TILE_HEIGHT / 2.0) + Y_OFFSET;

        // TODO: this moves the hitbox. It sholud be the new origin (position)
        //       of the sprite. But origin in Flixel is used only for rotation.
        //       Best approach would be create MySprite which extends FlXSprite
        //       and handle offset the way it is needed.
        offset.set(TILE_WIDTH / 2.0, TILE_HEIGHT / 2.0);

        // loadGraphic(PATH, ANIMATED, FRAME_WIDTH, FRAME_HEIGHT)
        loadGraphic("assets/images/conveyor.png", true, TILE_FRAME_WIDTH,
                    TILE_FRAME_HEIGHT);
        antialiasing = true;

        setFacingFlip(FlxObject.LEFT, false, false);
        setFacingFlip(FlxObject.RIGHT, true, false);
        facing = FlxObject.LEFT;

        _rolling = false;
        setTile(direction, _type);
        initAnimations(_type, animationFrames);

        // Setup the mouse events
        // add(SPRITE, ON_MOUSE_DOWN, ON_MOUSE_UP, ON_MOUSE_OVER, ON_MOUSE_OUT)
        MouseEventManager.add(this, null, onUp, onOver, onOut);
    }

    public function setTile(direction:Int, type:Int):Void {
        if (type == HIDDEN) {
            active = visible = false;
        }
        else {
            active = visible = true;
        }

        if (_direction == SE || _direction == NE) {
            facing = FlxObject.RIGHT;
        }

        _targetI = i;
        _targetJ = j;
        if (_type == GROUND) {
            return;
        }

        setDirectionTarget(_direction);
    }

    private function initAnimations(type:Int, animationFrames:Array<Int>):Void {
        animation.destroyAnimations();

        if (animationFrames != null) {
            // animation.add(NAME, FRAMES, FRAME_RATE, SHOULD_LOOP)
            animation.add("idle", [animationFrames[0]], 1, false);
            animation.play("idle");

            if (type != HIDDEN && type != GROUND) {
                animation.add("roll", animationFrames, 4, true);
            }
        }
    }

    override public function update():Void {
        if (_retryDeliver) {
            deliverIceCream();
        }
        super.update();
    }

    public function turnOn():Void {
        if (!_rolling) {
            _rolling = true;
            if (animation.paused) {
                animation.resume();
            } else {
                animation.play("roll");
            }
            if (_device != null) {
                _device.turnOn();
            }
        }
    }

    public function turnOff():Void {
        if (_rolling) {
            _rolling = false;
            animation.pause();
            if (_device != null) {
                _device.turnOff();
            }
        }
    }

    public function receiveIceCream(item:IceCream):Void {
        if (item == null) {
            trace("Received null ice cream.");
        }
        else if (_item != null) {
            // Should not accept other ice cream.
            item.setShaking(true);
        }
        else {
            // Every thing is fine. Accepting ice cream.
            _item = item;
            _item.setGridPosition(i, j);
            _item.direction = _direction;
        }
    }

    public function deliverIceCream():Void {
        if (_item == null) {
            // No ice cream to deliver.
            _retryDeliver = false;
            return;
        }

        // If there is a device in this tile, it transforms ice cream (once).
        if (_device != null && !_retryDeliver) {
            _device.transformIceCream(_item);
        }
{'fraction_non_alphanumeric': 0.09689953857362583, 'fraction_numerical': 0.0021047518821338948, 'mean_word_length': 1.8590604026845639, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5522325', 'n_tokens_mistral': 3645, 'n_tokens_neox': 3545, 'n_words': 948}