package com.rails2u.debug {
    import flash.errors.IllegalOperationError;
    import flash.external.ExternalInterface;
    import flash.utils.ByteArray;
    import flash.utils.getQualifiedClassName;

    public class ExportJS {
        private static var inited:Boolean = false;
        public static var objects:Object = {};

        public static function init():void {
            if (!ExternalInterface.available) throw (new IllegalOperationError('ExternalInterface.available should be true.'));
            if (inited) return;

            ExternalInterface.addCallback('updateProperty', updateProperty);
            ExternalInterface.addCallback('callMethod', callMethod);
            ExternalInterface.addCallback('reloadObject', reloadObject);
            inited = true;
        }

        public static function updateProperty(jsName:String, chainProperties:Array, value:Object):void {
            var obj:Object = objects[jsName];
            while (chainProperties.length > 1) {
                var prop:String = chainProperties.shift();
                obj = obj[prop];
            }
            obj[chainProperties.shift()] = value;
        }

        public static function callMethod(jsName:String, chainProperties:Array, args:Object):void {
            var obj:Object = objects[jsName];
            while (chainProperties.length > 1) {
                var prop:String = chainProperties.shift();
                obj = obj[prop];
            }
            var func:Function = obj[chainProperties.shift()] as Function;
            if (func is Function) func.apply(obj, args);
        }

        public static function reloadObject(jsName:String) {
            export(objects[jsName], jsName);
        }

        private static var cNum:uint = 0;
        private static function nonameCounter():uint {
            return cNum++;
        }

        public static function export(targetObject:*, jsName:String = undefined):String {
            init();

            if (!jsName) jsName = '__swf__' + nonameCounter();

            var b:ByteArray = new ByteArray();
            b.writeObject(targetObject);
            b.position = 0;
            var obj:Object = b.readObject();

            // custom for Sprite/Shape
            if (!obj.hasOwnProperty('graphics') && targetObject.hasOwnProperty('graphics'))
                obj.graphics = {};

            objects[jsName] = targetObject;
            ExternalInterface.call(<><![CDATA[
                (function(target, objectID, jsName, klassName) {
                    var swfObject = document.getElementsByName(objectID)[0];

                    var defineAttr = function(obj, parentProperties) {
                        var tmp = {};
                        for (var i in obj) {
                            if (obj[i] && (typeof(obj[i]) == "object" || typeof(obj[i]) == "array")) {
                                var pp = parentProperties.slice();
                                pp.push(i);
                                defineAttr(obj[i], pp);
                                continue;
                            }
                            tmp[i] = obj[i];
                            obj.__defineGetter__(i,
                                (function(attrName) {
                                    return function() {
                                       return this.__tmpProperties__[attrName]
                                    }
                                })(i)
                            );
                            obj.__defineSetter__(i,
                                (function(attrName) {
                                    return function(val) {
                                        swfObject.updateProperty(jsName, [].concat(parentProperties).concat(attrName), val);
                                        return this.__tmpProperties__[attrName] = val;
                                    }
                                })(i)
                            );
                        }
                        obj.__noSuchMethod__ = function(attrName, args) {
                            swfObject.callMethod(jsName, [].concat(parentProperties).concat(attrName), args);
                        }
                        obj.__tmpProperties__ = tmp;
                    }
                    defineAttr(target, []);

                    target.__reload = function() { return swfObject.reloadObject(jsName) };
                    target.toString = function() { return klassName };
                    window[jsName] = target;
                ;})
            ]]></>.toString(), obj, ExternalInterface.objectID, jsName, getQualifiedClassName(targetObject));
            return jsName;
        }
    }
}

package com.rails2u.debug {
    import flash.errors.IllegalOperationError;
    import flash.external.ExternalInterface;
    import flash.utils.ByteArray;
    import flash.utils.getQualifiedClassName;

    public class ExportJS {
        private static var inited:Boolean = false;
        public static var objects:Object = {};

        public static function init():void {
            if (!ExternalInterface.available) throw (new IllegalOperationError('ExternalInterface.available should be true.'));
            if (inited) return;

            ExternalInterface.addCallback('updateProperty', updateProperty);
            ExternalInterface.addCallback('callMethod', callMethod);
            ExternalInterface.addCallback('reloadObject', reloadObject);
            inited = true;
        }

        public static function updateProperty(jsName:String, chainProperties:Array, value:Object):Boolean {
            var obj:Object = objects[jsName];
            while (chainProperties.length > 1) {
                var prop:String = chainProperties.shift();
                obj = obj[prop];
            }
            try {
                obj[chainProperties.shift()] = value;
            } catch(e:Error) {
                ExternalInterface.call('console.error', e.message);
                return false;
            }
            return true;
        }

        public static function callMethod(jsName:String, chainProperties:Array, args:Object):* {
            var obj:Object = objects[jsName];
            while (chainProperties.length > 1) {
                var prop:String = chainProperties.shift();
                obj = obj[prop];
            }
            var func:Function = obj[chainProperties.shift()] as Function;

            try {
                if (func is Function) return func.apply(obj, args);
            } catch(e:Error) {
                ExternalInterface.call('console.error', e.message);
            }
        }

        public static function reloadObject(jsName:String) {
            export(objects[jsName], jsName);
            ExternalInterface.call('console.info', 'reloaded: ' + jsName);
        }

        private static var cNum:uint = 0;
        private static function nonameCounter():uint {
            return cNum++;
        }

        public static function export(targetObject:*, jsName:String = undefined):String {
            init();

            if (!jsName) jsName = '__swf__' + nonameCounter();

            var b:ByteArray = new ByteArray();
            b.writeObject(targetObject);
            b.position = 0;
            var obj:Object = b.readObject();

            // custom for Sprite/Shape
            if (!obj.hasOwnProperty('graphics') && targetObject.hasOwnProperty('graphics'))
                obj.graphics = {};

            objects[jsName] = targetObject;
            ExternalInterface.call(<><![CDATA[
                (function(target, objectID, jsName, klassName) {
                    var swfObject = document.getElementsByName(objectID)[0];

                    var defineAttr = function(obj, parentProperties) {
                        var tmp = {};
                        for (var i in obj) {
                            if (obj[i] && (typeof(obj[i]) == "object" || typeof(obj[i]) == "array")) {
                                var pp = parentProperties.slice();
                                pp.push(i);
                                defineAttr(obj[i], pp);
                                continue;
                            }
                            tmp[i] = obj[i];
                            obj.__defineGetter__(i,
                                (function(attrName) {
                                    return function() {
                                       return this.__tmpProperties__[attrName]
                                    }
                                })(i)
                            );
                            obj.__defineSetter__(i,
                                (function(attrName) {
                                    return function(val) {
                                        if (swfObject.updateProperty(jsName, [].concat(parentProperties).concat(attrName), val)) {
                                            return this.__tmpProperties__[attrName] = val;
                                        } else {
                                            return this.__tmpProperties__[attrName];
                                        }
                                    }
                                })(i)
                            );
                        }
                        obj.__noSuchMethod__ = function(attrName, args) {
                            swfObject.callMethod(jsName, [].concat(parentProperties).concat(attrName), args);
                        }
                        obj.__tmpProperties__ = tmp;
                    }
                    defineAttr(target, []);

                    target.__reload = function() { return swfObject.reloadObject(jsName) };
                    if (!target.hasOwnProperty('reload')) target.reload = target.__reload;

                    target.toString = function() { return klassName };
                    window[jsName] = target;
                ;})
            ]]></>.toString(), obj, ExternalInterface.objectID, jsName, getQualifiedClassName(targetObject));
            return jsName;
        }
    }
}

fix sum bugs

fix sum bugs

git-svn-id: 864080e30cc358c5edb906449bbf014f90258007@50 96db6a20-122f-0410-8d9f-89437bbe4005


/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 package org.mangui.osmf.plugins.traits {
    import org.mangui.hls.HLS;
    import org.mangui.hls.constant.HLSPlayStates;
    import org.mangui.hls.event.HLSEvent;
    import org.osmf.traits.PlayState;
    import org.osmf.traits.PlayTrait;

    CONFIG::LOGGING {
    import org.mangui.hls.utils.Log;
    }

    public class HLSPlayTrait extends PlayTrait
    {
        private var _hls : HLS;

        private var streamStarted : Boolean = false;

        public function HLSPlayTrait(hls : HLS)
        {
            CONFIG::LOGGING {
            Log.debug("HLSPlayTrait()");
            }
            super();
            _hls = hls;
            _hls.addEventListener(HLSEvent.PLAYBACK_STATE, _stateChangedHandler);
            _hls.addEventListener(HLSEvent.PLAYBACK_COMPLETE, _playbackComplete);
        }

        override public function dispose() : void
        {
            CONFIG::LOGGING {
            Log.debug("HLSPlayTrait:dispose");
            }
            _hls.removeEventListener(HLSEvent.PLAYBACK_STATE, _stateChangedHandler);
            _hls.removeEventListener(HLSEvent.PLAYBACK_COMPLETE, _playbackComplete);
            super.dispose();
        }

        override protected function playStateChangeStart(newPlayState:String):void
        {
            CONFIG::LOGGING
            {
                Log.info("HLSPlayTrait:playStateChangeStart:" + newPlayState);
            }
            switch (newPlayState)
            {
                case PlayState.PLAYING:
                    if (!streamStarted)
                    {
                        _hls.stream.play();
                        streamStarted = true;
                    }
                    else
                    {
                        _hls.stream.resume();

                    }
                    break;
                case PlayState.PAUSED:
                    _hls.stream.pause();
                    break;
                case PlayState.STOPPED:
                    streamStarted = false;
                    _hls.stream.close();
                    break;
            }
        }

        /** state changed handler **/
        private function _stateChangedHandler(event:HLSEvent):void {
            switch (event.state) {
                case HLSPlayStates.PLAYING:
                CONFIG::LOGGING {
                    Log.debug("HLSPlayTrait:_stateChangedHandler:setBuffering(true)");
                }
                    if (!streamStarted) {
                        streamStarted = true;
                        play();
                    }
                default:
            }
        }

        /** playback complete handler **/
        private function _playbackComplete(event : HLSEvent) : void {
            stop();
        }
    }
}

fix indents and spaces

fix indents and spaces


//
// flump-exporter

package flump.export {

import com.threerings.util.Arrays;
import com.threerings.util.F;
import com.threerings.util.Log;
import com.threerings.util.Map;
import com.threerings.util.Maps;

import flash.desktop.InvokeEventReason;
import flash.desktop.NativeApplication;
import flash.events.Event;
import flash.events.InvokeEvent;
import flash.filesystem.File;

import spark.components.Window;

public class FlumpApp
{
    public static const NA :NativeApplication = NativeApplication.nativeApplication;

    public static function get app () :FlumpApp {
        return _app;
    }

    public function FlumpApp () {
        if (_app != null) {
            throw new Error("FlumpApp is a singleton");
        }
        _app = this;
    }

    public function run () :void {
        Log.setLevel("", Log.INFO);

        var launched :Boolean = false;
        NA.addEventListener(InvokeEvent.INVOKE, function (event :InvokeEvent) :void {
            if (event.arguments.length > 0) {
                // A project file has been double-clicked. Open it.
                openProject(new File(event.arguments[0]));

            } else if (!launched) {
                // The app has been launched directly. Open the last-opened project if
                // it exists; else open a new project.
                openProject(FlumpSettings.hasConfigFilePath ?
                    new File(FlumpSettings.configFilePath) : null);
            } else if (_projects.length == 0) {
                // The app has been resumed. We have no open projects; create a new one.
                openProject();
            }

            launched = true;
        });
    }

    public function openProject (configFile :File = null) :void {
        // This project may already be open.
        for each (var ctrl :ProjectController in _projects) {
            if (ctrl.configFile == configFile) {
                ctrl.win.visible = false;
                if (!ctrl.win.orderToFront()) {
                    ctrl.win.restore();
                    ctrl.win.orderToFront();
                }

                return;
            }
        }

        var controller :ProjectController = new ProjectController(configFile);
        controller.win.addEventListener(Event.CLOSE, F.callbackOnce(closeProject, controller));
        _projects.push(controller);
    }

    protected function closeProject (controller :ProjectController) :void {
        Arrays.removeFirst(_projects, controller);
    }

    protected var _projects :Array = [];

    protected static var _app :FlumpApp;
}
}

//
// flump-exporter

package flump.export {

import com.threerings.util.Arrays;
import com.threerings.util.F;
import com.threerings.util.Log;
import com.threerings.util.Map;
import com.threerings.util.Maps;

import flash.desktop.InvokeEventReason;
import flash.desktop.NativeApplication;
import flash.events.Event;
import flash.events.InvokeEvent;
import flash.filesystem.File;

import spark.components.Window;

public class FlumpApp
{
    public static const NA :NativeApplication = NativeApplication.nativeApplication;

    public static function get app () :FlumpApp {
        return _app;
    }

    public function FlumpApp () {
        if (_app != null) {
            throw new Error("FlumpApp is a singleton");
        }
        _app = this;
    }

    public function run () :void {
        Log.setLevel("", Log.INFO);

        var launched :Boolean = false;
        NA.addEventListener(InvokeEvent.INVOKE, function (event :InvokeEvent) :void {
            if (event.arguments.length > 0) {
                // A project file has been double-clicked. Open it.
                openProject(new File(event.arguments[0]));

            } else if (!launched) {
                // The app has been launched directly. Open the last-opened project if
                // it exists; else open a new project.
                openProject(FlumpSettings.hasConfigFilePath ?
                    new File(FlumpSettings.configFilePath) : null);
            } else if (_projects.length == 0) {
                // The app has been resumed. We have no open projects; create a new one.
                openProject();
            }

            launched = true;
        });
    }

    public function openProject (configFile :File = null) :void {
        // This project may already be open.
        for each (var ctrl :ProjectController in _projects) {
            if (ctrl.configFile != null && ctrl.configFile.nativePath == configFile.nativePath) {
                ctrl.win.activate();
                return;
            }
        }

        var controller :ProjectController = new ProjectController(configFile);
        controller.win.addEventListener(Event.CLOSE, F.callbackOnce(closeProject, controller));
        _projects.push(controller);
    }

    protected function closeProject (controller :ProjectController) :void {
        Arrays.removeFirst(_projects, controller);
    }

    protected var _projects :Array = [];

    protected static var _app :FlumpApp;
}
}

Fix opening already-open projects

Fix opening already-open projects


package battlecode.client.viewer.render {
    import battlecode.client.viewer.MatchController;
    import battlecode.common.MapLocation;
    import battlecode.common.Team;
    import battlecode.common.TerrainTile;
    import battlecode.events.MatchEvent;
    import battlecode.world.GameMap;

    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.ColorTransform;
    import flash.geom.Rectangle;

    import mx.containers.Canvas;
    import mx.core.UIComponent;

    public class DrawMap extends Canvas {
        private var controller:MatchController;
        private var origin:MapLocation;

        // various canvases for layering and quick toggling of features
        private var mapCanvas:UIComponent;
        private var gridCanvas:UIComponent;
        private var neutralCanvas:UIComponent;
        private var groundUnitCanvas:UIComponent;

        // optimizations for caching
        private var lastRound:uint = 0;

        public function DrawMap(controller:MatchController) {
            super();

            this.controller = controller;
            this.controller.addEventListener(MatchEvent.ROUND_CHANGE, onRoundChange);
            this.controller.addEventListener(MatchEvent.MATCH_CHANGE, onMatchChange);
            this.addEventListener(Event.ENTER_FRAME, onEnterFrame);

            this.mapCanvas = new UIComponent();
            this.gridCanvas = new UIComponent();
            this.neutralCanvas = new UIComponent();
            this.groundUnitCanvas = new UIComponent();

            this.mapCanvas.cacheAsBitmap = true;
            this.gridCanvas.cacheAsBitmap = true;

            this.addChild(mapCanvas);
            this.addChild(gridCanvas);
            this.addChild(neutralCanvas);
            this.addChild(groundUnitCanvas);
        }

        ///////////////////////////////////////////////////////
        ////////////////// UTILITY METHODS ////////////////////
        ///////////////////////////////////////////////////////

        public function getMapWidth():uint {
            if (controller.match)
                return controller.match.getMap().getWidth() * RenderConfiguration.GRID_SIZE;
            return 0;
        }

        public function getMapHeight():uint {
            if (controller.match)
                return controller.match.getMap().getHeight() * RenderConfiguration.GRID_SIZE + 5;
            return 0;
        }

        private function getGridSize():Number {
            return RenderConfiguration.getGridSize();
        }

        ///////////////////////////////////////////////////////
        ////////////////// DRAWING METHODS ////////////////////
        ///////////////////////////////////////////////////////

        public function redrawAll():void {
            drawMap();
            drawGridlines();
            drawUnits();
            drawCows();

            var o:DrawObject;

            for each (o in controller.currentState.getGroundRobots()) {
                o.draw(true);
            }

            this.scrollRect = new Rectangle(this.mapCanvas.x, this.mapCanvas.y,
                    getMapWidth() * RenderConfiguration.getScalingFactor(),
                    getMapHeight() * RenderConfiguration.getScalingFactor());
        }

        private function drawMap():void {
            var i:uint, j:uint, tile:TerrainTile;
            var map:GameMap = controller.match.getMap();
            var terrain:Array = map.getTerrainTiles();
            var colorTransform:ColorTransform, scalar:uint;

            origin = map.getOrigin();

            this.mapCanvas.graphics.clear();
            for (i = 0; i < map.getHeight(); i++) {
                for (j = 0; j < map.getWidth(); j++) {
                    tile = terrain[i][j] as TerrainTile;
                    if (tile.getType() == TerrainTile.LAND) {
                        scalar = 0xFF * 0.9;
                        colorTransform = new ColorTransform(0, 0, 0, 1, scalar, scalar, scalar, 0);
                        this.mapCanvas.graphics.beginFill(colorTransform.color, 1.0);
                        this.mapCanvas.graphics.drawRect(j * getGridSize(), i * getGridSize(), getGridSize(), getGridSize());
                        this.mapCanvas.graphics.endFill();
                    } else if (tile.getType() == TerrainTile.ROAD) {
                        scalar = 0xFF * 0.7;
                        colorTransform = new ColorTransform(0, 0, 0, 1, scalar, scalar, scalar, 0);
                        this.mapCanvas.graphics.beginFill(colorTransform.color, 1.0);
                        this.mapCanvas.graphics.drawRect(j * getGridSize(), i * getGridSize(), getGridSize(), getGridSize());
                        this.mapCanvas.graphics.endFill();
                    } else {
                        colorTransform = new ColorTransform(0, 0, 0, 1, 0x00, 0x00, 0x99, 0);
                        this.mapCanvas.graphics.beginFill(colorTransform.color, 1.0);
                        this.mapCanvas.graphics.drawRect(j * getGridSize(), i * getGridSize(), getGridSize(), getGridSize());
                        this.mapCanvas.graphics.endFill();
                    }
                }
            }
        }

        private function drawGridlines():void {
            var i:uint, j:uint;
            var map:GameMap = controller.match.getMap();

            this.gridCanvas.graphics.clear();
            for (i = 0; i < map.getHeight(); i++) {
                for (j = 0; j < map.getWidth(); j++) {
                    this.gridCanvas.graphics.lineStyle(.5, 0x999999, 0.3);
                    this.gridCanvas.graphics.drawRect(j * getGridSize(), i * getGridSize(), getGridSize(), getGridSize());
                }
            }
        }

        private function drawCows():void {
            var cows:Array = controller.currentState.getNeutralDensities();
            var cowsTeams:Array = controller.currentState.getNeutralTeams();
            var i:uint, j:uint, team:String;

            this.neutralCanvas.graphics.clear();
            var g:Number = getGridSize();
            for (i = 0; i < cows.length; i++) {
                for (j = 0; j < cows[i].length; j++) {
                    var density:Number = cows[i][j] / 8000.0;
                    var color:Number = Team.cowColor(Team.valueOf(cowsTeams[i][j]));
                    this.neutralCanvas.graphics.lineStyle(1, color, 0.8);
                    this.neutralCanvas.graphics.beginFill(color, 0.4);
                    this.neutralCanvas.graphics.drawCircle((i + .5) * g, (j + .5) * g, g * density / 2);
                    this.neutralCanvas.graphics.endFill();
                }
            }
        }

        private function drawUnits():void {
            var loc:MapLocation, i:uint, j:uint, robot:DrawRobot;
            var groundRobots:Object = controller.currentState.getGroundRobots();

            while (groundUnitCanvas.numChildren > 0)
                groundUnitCanvas.removeChildAt(0);

            for each (robot in groundRobots) {
                loc = robot.getLocation();
                j = (loc.getX() - origin.getX());
                i = (loc.getY() - origin.getY());
                robot.x = j * getGridSize() + getGridSize() / 2;
                robot.y = i * getGridSize() + getGridSize() / 2;
                robot.addEventListener(MouseEvent.CLICK, onRobotSelect, false, 0, true);
                groundUnitCanvas.addChild(robot);
                robot.draw();
            }
        }

        private function updateUnits():void {
            var loc:MapLocation, i:uint, j:uint, robot:DrawRobot;
            var groundRobots:Object = controller.currentState.getGroundRobots();

            for each (robot in groundRobots) {
                loc = robot.getLocation();
                j = (loc.getX() - origin.getX());
                i = (loc.getY() - origin.getY());
                robot.x = j * getGridSize() + getGridSize() / 2;
                robot.y = i * getGridSize() + getGridSize() / 2;
                if (!robot.parent && robot.isAlive()) {
                    robot.addEventListener(MouseEvent.CLICK, onRobotSelect, false, 0, true);
                    groundUnitCanvas.addChild(robot);
                }
                robot.draw();
            }
        }

        ///////////////////////////////////////////////////////
        //////////////////// EVENT HANDLERS ///////////////////
        ///////////////////////////////////////////////////////

        private function onEnterFrame(e:Event):void {
            gridCanvas.visible = RenderConfiguration.showGridlines();
            groundUnitCanvas.visible = RenderConfiguration.showGround();
            neutralCanvas.visible = RenderConfiguration.showCows();
        }

        private function onRoundChange(e:MatchEvent):void {
            if (e.currentRound < lastRound) {
                drawUnits();
            }
            updateUnits();
            drawCows();

            lastRound = e.currentRound;

            this.visible = (e.currentRound != 0);
        }

        private function onMatchChange(e:MatchEvent):void {
            redrawAll();
        }

        private function onRobotSelect(e:MouseEvent):void {
            var x:Number, y:Number;

            if (RenderConfiguration.isTournament())
                return;

            if (controller.selectedRobot && controller.selectedRobot.parent) {
                controller.selectedRobot.setSelected(false);
                x = controller.selectedRobot.x;
                y = controller.selectedRobot.y;
                controller.selectedRobot.draw(true);
                controller.selectedRobot.x = x;
                controller.selectedRobot.y = y;
            }

            var robot:DrawRobot = e.currentTarget as DrawRobot;
            robot.setSelected(true);
            x = robot.x;
            y = robot.y;
            robot.draw(true);
            robot.x = x;
            robot.y = y;
            controller.selectedRobot = robot;
        }

    }

}

package battlecode.client.viewer.render {
    import battlecode.client.viewer.MatchController;
    import battlecode.common.MapLocation;
    import battlecode.common.Team;
    import battlecode.common.TerrainTile;
    import battlecode.events.MatchEvent;
    import battlecode.world.GameMap;

    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.ColorTransform;
    import flash.geom.Rectangle;

    import mx.containers.Canvas;
    import mx.core.UIComponent;

    public class DrawMap extends Canvas {
        private var controller:MatchController;
        private var origin:MapLocation;

        // various canvases for layering and quick toggling of features
        private var mapCanvas:UIComponent;
        private var gridCanvas:UIComponent;
        private var neutralCanvas:UIComponent;
        private var groundUnitCanvas:UIComponent;

        // optimizations for caching
        private var lastRound:uint = 0;

        public function DrawMap(controller:MatchController) {
            super();

            this.controller = controller;
            this.controller.addEventListener(MatchEvent.ROUND_CHANGE, onRoundChange);
            this.controller.addEventListener(MatchEvent.MATCH_CHANGE, onMatchChange);
            this.addEventListener(Event.ENTER_FRAME, onEnterFrame);

            this.mapCanvas = new UIComponent();
            this.gridCanvas = new UIComponent();
            this.neutralCanvas = new UIComponent();
            this.groundUnitCanvas = new UIComponent();

            this.mapCanvas.cacheAsBitmap = true;
            this.gridCanvas.cacheAsBitmap = true;

            this.addChild(mapCanvas);
            this.addChild(gridCanvas);
            this.addChild(neutralCanvas);
            this.addChild(groundUnitCanvas);
        }

        ///////////////////////////////////////////////////////
        ////////////////// UTILITY METHODS ////////////////////
        ///////////////////////////////////////////////////////

        public function getMapWidth():uint {
            if (controller.match)
                return controller.match.getMap().getWidth() * RenderConfiguration.GRID_SIZE;
            return 0;
        }

        public function getMapHeight():uint {
            if (controller.match)
                return controller.match.getMap().getHeight() * RenderConfiguration.GRID_SIZE + 5;
            return 0;
        }

        private function getGridSize():Number {
            return RenderConfiguration.getGridSize();
        }

        ///////////////////////////////////////////////////////
        ////////////////// DRAWING METHODS ////////////////////
        ///////////////////////////////////////////////////////

        public function redrawAll():void {
            drawMap();
            drawGridlines();
            drawUnits();
            drawCows();

            var o:DrawObject;

            for each (o in controller.currentState.getGroundRobots()) {
                o.draw(true);
            }

            this.scrollRect = new Rectangle(this.mapCanvas.x, this.mapCanvas.y,
                    getMapWidth() * RenderConfiguration.getScalingFactor(),
                    getMapHeight() * RenderConfiguration.getScalingFactor());
        }

        private function drawMap():void {
            var i:uint, j:uint, tile:TerrainTile;
            var map:GameMap = controller.match.getMap();
            var terrain:Array = map.getTerrainTiles();
            var colorTransform:ColorTransform, scalar:uint;

            origin = map.getOrigin();

            this.mapCanvas.graphics.clear();
            for (i = 0; i < map.getHeight(); i++) {
                for (j = 0; j < map.getWidth(); j++) {
                    tile = terrain[i][j] as TerrainTile;
                    if (tile.getType() == TerrainTile.LAND) {
                        scalar = 0xFF * 0.9;
                        colorTransform = new ColorTransform(0, 0, 0, 1, scalar, scalar, scalar, 0);
                        this.mapCanvas.graphics.beginFill(colorTransform.color, 1.0);
                        this.mapCanvas.graphics.drawRect(j * getGridSize(), i * getGridSize(), getGridSize(), getGridSize());
                        this.mapCanvas.graphics.endFill();
                    } else if (tile.getType() == TerrainTile.ROAD) {
                        scalar = 0xFF * 0.7;
                        colorTransform = new ColorTransform(0, 0, 0, 1, scalar, scalar, scalar, 0);
                        this.mapCanvas.graphics.beginFill(colorTransform.color, 1.0);
                        this.mapCanvas.graphics.drawRect(j * getGridSize(), i * getGridSize(), getGridSize(), getGridSize());
                        this.mapCanvas.graphics.endFill();
                    } else {
                        colorTransform = new ColorTransform(0, 0, 0, 1, 0x00, 0x00, 0x99, 0);
                        this.mapCanvas.graphics.beginFill(colorTransform.color, 1.0);
                        this.mapCanvas.graphics.drawRect(j * getGridSize(), i * getGridSize(), getGridSize(), getGridSize());
                        this.mapCanvas.graphics.endFill();
                    }
                }
            }
        }

        private function drawGridlines():void {
            var i:uint, j:uint;
            var map:GameMap = controller.match.getMap();

            this.gridCanvas.graphics.clear();
            for (i = 0; i < map.getHeight(); i++) {
                for (j = 0; j < map.getWidth(); j++) {
                    this.gridCanvas.graphics.lineStyle(.5, 0x999999, 0.3);
                    this.gridCanvas.graphics.drawRect(j * getGridSize(), i * getGridSize(), getGridSize(), getGridSize());
                }
            }
        }

        private function drawCows():void {
            var cows:Array = controller.currentState.getNeutralDensities();
            var cowsTeams:Array = controller.currentState.getNeutralTeams();
            var i:uint, j:uint, team:String;

            this.neutralCanvas.graphics.clear();
            var g:Number = getGridSize();
            for (i = 0; i < cows.length; i++) {
                for (j = 0; j < cows[i].length; j++) {
                    var density:Number = cows[i][j] / 8000.0;
                    var color:Number = Team.cowColor(Team.valueOf(cowsTeams[i][j]));
                    this.neutralCanvas.graphics.lineStyle(1, color, 0.8);
                    this.neutralCanvas.graphics.beginFill(color, 0.4);
                    this.neutralCanvas.graphics.drawCircle((i + .5) * g, (j + .5) * g, g * Math.sqrt(density) / 2);
                    this.neutralCanvas.graphics.endFill();
                }
            }
        }

        private function drawUnits():void {
            var loc:MapLocation, i:uint, j:uint, robot:DrawRobot;
            var groundRobots:Object = controller.currentState.getGroundRobots();

            while (groundUnitCanvas.numChildren > 0)
                groundUnitCanvas.removeChildAt(0);

            for each (robot in groundRobots) {
                loc = robot.getLocation();
                j = (loc.getX() - origin.getX());
                i = (loc.getY() - origin.getY());
                robot.x = j * getGridSize() + getGridSize() / 2;
                robot.y = i * getGridSize() + getGridSize() / 2;
                robot.addEventListener(MouseEvent.CLICK, onRobotSelect, false, 0, true);
                groundUnitCanvas.addChild(robot);
                robot.draw();
            }
        }

        private function updateUnits():void {
            var loc:MapLocation, i:uint, j:uint, robot:DrawRobot;
            var groundRobots:Object = controller.currentState.getGroundRobots();

            for each (robot in groundRobots) {
                loc = robot.getLocation();
                j = (loc.getX() - origin.getX());
                i = (loc.getY() - origin.getY());
                robot.x = j * getGridSize() + getGridSize() / 2;
                robot.y = i * getGridSize() + getGridSize() / 2;
                if (!robot.parent && robot.isAlive()) {
                    robot.addEventListener(MouseEvent.CLICK, onRobotSelect, false, 0, true);
                    groundUnitCanvas.addChild(robot);
                }
                robot.draw();
            }
        }

        ///////////////////////////////////////////////////////
        //////////////////// EVENT HANDLERS ///////////////////
        ///////////////////////////////////////////////////////

        private function onEnterFrame(e:Event):void {
            gridCanvas.visible = RenderConfiguration.showGridlines();
            groundUnitCanvas.visible = RenderConfiguration.showGround();
            neutralCanvas.visible = RenderConfiguration.showCows();
        }

        private function onRoundChange(e:MatchEvent):void {
            if (e.currentRound < lastRound) {
                drawUnits();
            }
            updateUnits();
            drawCows();

            lastRound = e.currentRound;

            this.visible = (e.currentRound != 0);
        }

        private function onMatchChange(e:MatchEvent):void {
            redrawAll();
        }

        private function onRobotSelect(e:MouseEvent):void {
            var x:Number, y:Number;

            if (RenderConfiguration.isTournament())
                return;

            if (controller.selectedRobot && controller.selectedRobot.parent) {
                controller.selectedRobot.setSelected(false);
                x = controller.selectedRobot.x;
                y = controller.selectedRobot.y;
                controller.selectedRobot.draw(true);
                controller.selectedRobot.x = x;
                controller.selectedRobot.y = y;
            }

            var robot:DrawRobot = e.currentTarget as DrawRobot;
            robot.setSelected(true);
            x = robot.x;
            y = robot.y;
            robot.draw(true);
            robot.x = x;
            robot.y = y;
            controller.selectedRobot = robot;
        }

    }

}

Change cow circle radii

Change cow circle radii

This changes cow circle radii from being proportional to the number of
cows in a square to being proportional to the square root of the
number of cows in a square.  Since the circle area is proportional to
the square of the radius, this makes the area of circles proportional
to the number of cows, instead of the square of the number of cows.


//
// $Id: GameConfig.java 4026 2006-04-18 01:32:41Z mdb $
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.threerings.parlor.game.data {

import com.threerings.util.ClassUtil;
import com.threerings.util.Cloneable;
import com.threerings.util.Hashable;
import com.threerings.util.Name;
import com.threerings.util.StringUtil;

import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.TypedArray;

import com.threerings.crowd.data.PlaceConfig;

import com.threerings.parlor.client.TableConfigurator;
import com.threerings.parlor.game.client.GameConfigurator;

/**
 * The game config class encapsulates the configuration information for a
 * particular type of game. The hierarchy of game config objects mimics the
 * hierarchy of game managers and controllers. Both the game manager and game
 * controller are provided with the game config object when the game is
 * created.
 *
 * <p> The game config object is also the mechanism used to instantiate the
 * appropriate game manager and controller. Every game must have an associated
 * game config derived class that overrides {@link #createController} and
 * {@link #getManagerClassName}, returning the appropriate game controller and
 * manager class for that game. Thus the entire chain of events that causes a
 * particular game to be created is the construction of the appropriate game
 * config instance which is provided to the server as part of an invitation or
 * via some other matchmaking mechanism.
 */
public /*abstract*/ class GameConfig extends PlaceConfig
    implements Cloneable, Hashable
{
    /** The usernames of the players involved in this game, or an empty
     * array if such information is not needed by this particular game. */
    public var players :TypedArray = TypedArray.create(Name);

    /** Indicates whether or not this game is rated. */
    public var rated :Boolean = true;

    /** Configurations for AIs to be used in this game. Slots with real
     * players should be null and slots with AIs should contain
     * configuration for those AIs. A null array indicates no use of AIs
     * at all. */
    public var ais :TypedArray = TypedArray.create(GameAI);

    /**
     * Returns the message bundle identifier for the bundle that should be
     * used to translate the translatable strings used to describe the
     * game config parameters.
     */
    public /*abstract*/ function getBundleName () :String
    {
        throw new Error("abstract");
    }

    /**
     * Creates a configurator that can be used to create a user interface
     * for configuring this instance prior to starting the game. If no
     * configuration is necessary, this method should return null.
     */
    public /*abstract*/ function createConfigurator () :GameConfigurator
    {
        throw new Error("abstract");
    }

    /**
     * Creates a table configurator for initializing 'table' properties
     * of the game. The default implementation returns null.
     */
    public function createTableConfigurator () :TableConfigurator
    {
        return null;
    }

    /**
     * Returns a translatable label describing this game.
     */
    public function getGameName () :String
    {
        // the whole getRatingTypeId(), getGameName(), getBundleName()
        // business should be cleaned up. we should have getGameIdent()
        // and everything should have a default implementation using that
        return "m." + getBundleName();
    }

    /**
     * Returns the game rating type, if the system uses such things.
     */
    public function getRatingTypeId () :int
    {
        return -1;
    }

    /**
     * Returns an Array of strings that describe the configuration of this
     * game. Default implementation returns an empty array.
     */
    public function getDescription () :Array
    {
        return new Array(); // nothing by default
    }

    /**
     * Returns true if this game config object is equal to the supplied
     * object (meaning it is also a game config object and its
     * configuration settings are the same as ours).
     */
    public function equals (other :Object) :Boolean
    {
        // make sure they're of the same class
        if (ClassUtil.getClassName(other) == ClassUtil.getClassName(this)) {
            var that :GameConfig = GameConfig(other);
            return this.rated == that.rated;

        } else {
            return false;
        }
    }

    /**
     * Computes a hashcode for this game config object that supports our
     * {@link #equals} implementation. Objects that are equal should have
     * the same hashcode.
     */
    public function hashCode () :int
    {
        // look ma, it's so sophisticated!
        return StringUtil.hashCode(ClassUtil.getClassName(this)) +
            (rated ? 1 : 0);
    }

    // from Cloneable
    public function clone () :Object
    {
        var copy :GameConfig = (ClassUtil.newInstance(this) as GameConfig);
        copy.players = this.players;
        copy.rated = this.rated;
        copy.ais = this.ais;

        return copy;
    }

    override public function writeObject (out :ObjectOutputStream) :void
    {
        super.writeObject(out);

        out.writeObject(players);
        out.writeBoolean(rated);
        out.writeObject(ais);
    }

    override public function readObject (ins :ObjectInputStream) :void
    {
        super.readObject(ins);

        players = (ins.readObject() as TypedArray);
        rated = ins.readBoolean();
        ais = (ins.readObject() as TypedArray);
    }
}
}

//
// $Id: GameConfig.java 4026 2006-04-18 01:32:41Z mdb $
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.threerings.parlor.game.data {

import com.threerings.util.ClassUtil;
import com.threerings.util.Cloneable;
import com.threerings.util.Hashable;
import com.threerings.util.Name;
import com.threerings.util.StringUtil;

import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.TypedArray;

import com.threerings.crowd.data.PlaceConfig;

import com.threerings.parlor.client.TableConfigurator;
import com.threerings.parlor.game.client.GameConfigurator;

/**
 * The game config class encapsulates the configuration information for a
 * particular type of game. The hierarchy of game config objects mimics the
 * hierarchy of game managers and controllers. Both the game manager and game
 * controller are provided with the game config object when the game is
 * created.
 *
 * <p> The game config object is also the mechanism used to instantiate the
 * appropriate game manager and controller. Every game must have an associated
 * game config derived class that overrides {@link #createController} and
 * {@link #getManagerClassName}, returning the appropriate game controller and
 * manager class for that game. Thus the entire chain of events that causes a
 * particular game to be created is the construction of the appropriate game
 * config instance which is provided to the server as part of an invitation or
 * via some other matchmaking mechanism.
 */
public /*abstract*/ class GameConfig extends PlaceConfig
    implements Cloneable, Hashable
{
    /** The usernames of the players involved in this game, or an empty
     * array if such information is not needed by this particular game. */
    public var players :TypedArray = TypedArray.create(Name);

    /** Indicates whether or not this game is rated. */
    public var rated :Boolean = true;

    /** Configurations for AIs to be used in this game. Slots with real
     * players should be null and slots with AIs should contain
     * configuration for those AIs. A null array indicates no use of AIs
     * at all. */
    public var ais :TypedArray = TypedArray.create(GameAI);

    /**
     * Returns the message bundle identifier for the bundle that should be
     * used to translate the translatable strings used to describe the
     * game config parameters.
     */
    public /*abstract*/ function getBundleName () :String
    {
        throw new Error("abstract");
    }

    /**
     * Creates a configurator that can be used to create a user interface
     * for configuring this instance prior to starting the game. If no
     * configuration is necessary, this method should return null.
     */
    public /*abstract*/ function createConfigurator () :GameConfigurator
    {
        throw new Error("abstract");
    }

    /**
     * Creates a table configurator for initializing 'table' properties
     * of the game. The default implementation returns null.
     */
    public function createTableConfigurator () :TableConfigurator
    {
        return null;
    }

    /**
     * Returns a translatable label describing this game.
     */
    public function getGameName () :String
    {
        // the whole getRatingTypeId(), getGameName(), getBundleName()
        // business should be cleaned up. we should have getGameIdent()
        // and everything should have a default implementation using that
        return "m." + getBundleName();
    }

    /**
     * Returns the game rating type, if the system uses such things.
     */
    public function getRatingTypeId () :int
    {
        return -1;
    }

    /**
     * Returns an Array of strings that describe the configuration of this
     * game. Default implementation returns an empty array.
     */
    public function getDescription () :Array
    {
        return new Array(); // nothing by default
    }

    /**
     * Returns true if this game config object is equal to the supplied
     * object (meaning it is also a game config object and its
     * configuration settings are the same as ours).
     */
    public function equals (other :Object) :Boolean
    {
        // make sure they're of the same class
        if (ClassUtil.isSameClass(other, this)) {
            var that :GameConfig = GameConfig(other);
            return this.rated == that.rated;

        } else {
            return false;
        }
    }

    /**
     * Computes a hashcode for this game config object that supports our
     * {@link #equals} implementation. Objects that are equal should have
     * the same hashcode.
     */
    public function hashCode () :int
    {
        // look ma, it's so sophisticated!
        return StringUtil.hashCode(ClassUtil.getClassName(this)) +
            (rated ? 1 : 0);
    }

    // from Cloneable
    public function clone () :Object
    {
        var copy :GameConfig = (ClassUtil.newInstance(this) as GameConfig);
        copy.players = this.players;
        copy.rated = this.rated;
        copy.ais = this.ais;

        return copy;
    }

    override public function writeObject (out :ObjectOutputStream) :void
    {
        super.writeObject(out);

        out.writeObject(players);
        out.writeBoolean(rated);
        out.writeObject(ais);
    }

    override public function readObject (ins :ObjectInputStream) :void
    {
        super.readObject(ins);

        players = (ins.readObject() as TypedArray);
        rated = ins.readBoolean();
        ais = (ins.readObject() as TypedArray);
    }
}
}

Use ClassUtil.isSameClass().

Use ClassUtil.isSameClass().

git-svn-id: a3e1eb16dde062992de22c830ed8045c8013209a@40 c613c5cb-e716-0410-b11b-feb51c14d237


/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * 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.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 *   Marc Alcaraz <ekameleon@gmail.com>.
 */

package com.google.analytics.campaign
{
    import com.google.analytics.core.Buffer;
    import com.google.analytics.core.OrganicReferrer;
    import com.google.analytics.debug.DebugConfiguration;
    import com.google.analytics.debug.VisualDebugMode;
    import com.google.analytics.utils.Protocols;
    import com.google.analytics.utils.URL;
    import com.google.analytics.utils.Variables;
    import com.google.analytics.v4.Configuration;

    /**
     * The CampaignManager class.
     */
    public class CampaignManager
    {
        private var _config:Configuration;
        private var _debug:DebugConfiguration;
        private var _buffer:Buffer;

        private var _domainHash:Number;
        private var _referrer:String;
        private var _timeStamp:Number;

        /**
         * Delimiter for campaign tracker.
         */
        public static const trackingDelimiter:String = "|";

        /**
         * Creates a new CampaignManager instance.
         */
        public function CampaignManager( config:Configuration, debug:DebugConfiguration, buffer:Buffer,
                                         domainHash:Number, referrer:String, timeStamp:Number )
        {
            _config     = config;
            _debug      = debug;
            _buffer     = buffer;

            _domainHash = domainHash;
            _referrer   = referrer;
            _timeStamp  = timeStamp;
        }

        /**
         * This method will return true if and only document referrer is invalid.
         * Document referrer is considered to be invalid when it's empty (undefined,
         * empty string, "-", or "0"), or it's not a valid URL (doesn't have protocol)
         *
         * @private
         * @param {String} docRef Document referrer to be evaluated for validity.
         *
         * @return {Boolean} True if and only if document referrer is invalid.
         */
        public static function isInvalidReferrer( referrer:String ):Boolean
        {
            if( (referrer == "") ||
                (referrer == "-") ||
                (referrer == "0") )
            {
                return true;
            }

            if( referrer.indexOf("://") > -1 )
            {
                var url:URL = new URL( referrer );

                if( (url.protocol == Protocols.file) ||
                    (url.protocol == Protocols.none) )
                    {
                    return true;
                    }
            }

            return false;
        }

        /**
         * Checks if the document referrer is from the google custom search engine.
         * @private
         * @return true if the referrer is from google custom search engine.
         */
        public static function isFromGoogleCSE( referrer:String, config:Configuration ):Boolean
        {
            var url:URL = new URL( referrer );

            // verify that the referrer is google cse search query.
            if( url.hostName.indexOf( config.google ) > -1 )
            {
                if( url.search.indexOf( config.googleSearchParam+"=" ) > -1 )
                {
                    // check if this is google custom search engine.
                    if( url.path == "/"+config.googleCsePath )
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        /**
         * Retrieves campaign information.  If linker functionality is allowed, and
         * the cookie parsed from search string is valid (hash matches), then load the
         * __utmz value form search string, and write the value to cookie, then return
         * "".  Otherwise, attempt to retrieve __utmz value from cookie.  Then
         * retrieve campaign information from search string.  If that fails, try
         * organic campaigns next.  If that fails, try referral campaigns next.  If
         * that fails, try direct campaigns next.  If it still fails, return nothing.
         * Finally, determine whether the campaign is duplicated.  If the campaign is
         * not duplicated, then write campaign information to cookie, and indicate
         * there is a new campaign for gif hit.  Else, just indicate this is a
         * repeated click for campaign.
         *
         * @private
         * @param {_gat.GA_Cookie_} inCookie GA_Cookie instance containing cookie
         *     values parsed in from URL (linker).  This value should never be
         *     undefined.
         * @param {Boolean} noSession Indicating whether a session has been
         *     initialized. If __utmb and/or __utmc cookies are not set, then session
         *     has either timed-out or havn't been initialized yet.
         *
         * @return {String} Gif hit key-value pair indicating wether this is a repeated
         *     click, or a brand new campaign for the visitor.
         */
        public function getCampaignInformation( search:String, noSessionInformation:Boolean ):CampaignInfo
        {
            var campInfo:CampaignInfo = new CampaignInfo();
            var campaignTracker:CampaignTracker;
            var duplicateCampaign:Boolean = false;
            var campNoOverride:Boolean = false;
            var responseCount:int = 0;

            /* Allow linker functionality, and cookie is parsed from URL, and the cookie
              hash matches.
            */
            if( _config.allowLinker && _buffer.isGenuine() )
            {
                if( !_buffer.hasUTMZ() )
                {
                    return campInfo;
                }
            }

            // retrieves tracker from search string
            campaignTracker = getTrackerFromSearchString( search );

            if( isValid( campaignTracker ) )
            {
                // check for no override flag in search string
                campNoOverride = hasNoOverride( search );

                // if no override is true, and there is a utmz value, then do nothing now
                if( campNoOverride && !_buffer.hasUTMZ() )
                {
                    return campInfo;
                }
            }

            // Get organic campaign if there is no campaign tracker from search string.
            if( !isValid( campaignTracker ) )
            {
                campaignTracker = getOrganicCampaign();

                //If there is utmz cookie value, and organic keyword is being ignored, do nothing.
                if( !_buffer.hasUTMZ() && isIgnoredKeyword( campaignTracker ) )
                {
                    return campInfo;
                }
            }

            /* Get referral campaign if there is no campaign tracker from search string
               and organic campaign, and either utmb or utmc is missing (no session).
            */
            if( !isValid( campaignTracker ) && noSessionInformation )
            {
                campaignTracker = getReferrerCampaign();

                //If there is utmz cookie value, and referral domain is being ignored, do nothing
                if( !_buffer.hasUTMZ() && isIgnoredReferral( campaignTracker ) )
                {
                    return campInfo;
                }
            }

            /* Get direct campaign if there is no campaign tracker from search string,
              organic campaign, or referral campaign.
            */
            if( !isValid( campaignTracker ) )
            {
                /* Only get direct campaign when there is no utmz cookie value, and there is
                   no session. (utmb or utmc is missing value)
                */
                if( !_buffer.hasUTMZ() && noSessionInformation )
                {
                    campaignTracker = getDirectCampaign();
                }

            }

            //Give up (do nothing) if still cannot get campaign tracker.
            if( !isValid( campaignTracker ) )
            {
                return campInfo;
            }

            //utmz cookie have value, check whether campaign is duplicated.
            if( _buffer.hasUTMZ() && !_buffer.utmz.isEmpty() )
            {
                var oldTracker:CampaignTracker = new CampaignTracker();
                    oldTracker.fromTrackerString( _buffer.utmz.campaignTracking );

                duplicateCampaign = ( oldTracker.toTrackerString() == campaignTracker.toTrackerString() );

                responseCount = _buffer.utmz.responseCount;
            }

            /* Record as new campaign if and only if campaign is not duplicated, or there
              is no session information.
            */
            if( !duplicateCampaign || noSessionInformation )
            {
                var sessionCount:int = _buffer.utma.sessionCount;
                responseCount++;

                // if there is no session number, increment
                if( sessionCount == 0 )
                {
                    sessionCount = 1;
                }

                // construct utmz cookie
                _buffer.utmz.domainHash       = _domainHash;
                _buffer.utmz.campaignCreation = _timeStamp;
                _buffer.utmz.campaignSessions = sessionCount;
                _buffer.utmz.responseCount    = responseCount;
                _buffer.utmz.campaignTracking = campaignTracker.toTrackerString();

                _debug.info( _buffer.utmz.toString(), VisualDebugMode.geek );

                // indicate new campaign
                campInfo = new CampaignInfo( false, true );
            }
            else
            {
                // indicate repeated campaign
                campInfo = new CampaignInfo( false, false );
            }

            return campInfo;
        }

        /**
         * This method returns the organic campaign information.
         * @private
         * @return {_gat.GA_Campaign_.Tracker_} Returns undefined if referrer is not
         * a matching organic campaign source. Otherwise, returns the campaign tracker object.
         */
        public function getOrganicCampaign():CampaignTracker
        {
            var camp:CampaignTracker;

            // if there is no referrer, or referrer is not a valid URL, or the referrer
            // is google custom search engine, return an empty tracker
            if( isInvalidReferrer( _referrer ) || isFromGoogleCSE( _referrer, _config ) )
            {
                return camp;
            }

            var ref:URL = new URL( _referrer );
            var name:String = "";

            if( ref.hostName != "" )
            {
                if( ref.hostName.indexOf( "." ) > -1 )
                {
                    var tmp:Array = ref.hostName.split( "." );

                    switch( tmp.length)
                    {
                        case 2:
                        // case: http://domain.com
                        name = tmp[0];
                        break;

                        case 3:
                        //case: http://www.domain.com
                        name = tmp[1];
                        break;
                    }
                }
            }

            // organic source match
            if( _config.organic.match( name ) )
            {
                var currentOrganicSource:OrganicReferrer = _config.organic.getReferrerByName( name );

                // extract keyword value from query string
                var keyword:String = _config.organic.getKeywordValue( currentOrganicSource, ref.search );

                camp = new CampaignTracker();
                camp.source = currentOrganicSource.engine;
                camp.name   = "(organic)";
                camp.medium = "organic";
                camp.term   = keyword;
            }

            return camp;
        }

        /**
         * This method returns the referral campaign information.
         *
         * @private
         * @return {_gat.GA_Campaign_.Tracker_} Returns nothing if there is no
         *     referrer. Otherwise, return referrer campaign tracker.
         */
        public function getReferrerCampaign():CampaignTracker
        {
            var camp:CampaignTracker;

            // if there is no referrer, or referrer is not a valid URL, or the referrer
            // is google custom search engine, return an empty tracker
            if( isInvalidReferrer( _referrer ) || isFromGoogleCSE( _referrer, _config ) )
            {
                return camp;
            }

            // get host name from referrer
            var ref:URL = new URL( _referrer );
            var hostname:String = ref.hostName;
            var content:String  = ref.path;

            if( hostname.indexOf( "www." ) == 0 )
            {
                hostname = hostname.substr( 4 );
            }

            camp = new CampaignTracker();
            camp.source  = hostname;
            camp.name    = "(referral)";
            camp.medium  = "referral";
            camp.content = content;

            return camp;
        }

        /**
         * Returns the direct campaign tracker string.
         * @private
         * @return {_gat.GA_Campaign_.Tracker_} Direct campaign tracker object.
         */
        public function getDirectCampaign():CampaignTracker
        {
            var camp:CampaignTracker = new CampaignTracker();
                camp.source = "(direct)";
                camp.name   = "(direct)";
                camp.medium = "(none)";

            return camp;
        }

        /**
         * Indicates if the manager has no override with the search value.
         */
        public function hasNoOverride( search:String ):Boolean
        {
            var key:CampaignKey = _config.campaignKey;

            if( search == "" )
            {
                return false;
            }

            var variables:Variables = new Variables( search );
            var value:String           = "";

            if( variables.hasOwnProperty( key.UCNO ) )
            {
                value = variables[ key.UCNO ];

                switch( value )
                {
                    case "1":
                    return true;

                    case "":
                    case "0":
                    default:
                    return false;
                }
            }

            return false;
        }

        /**
         * This method returns true if and only if campaignTracker is a valid organic
         * campaign tracker (utmcmd=organic), and the keyword (utmctr) is contained in
         * the ignore watch list (ORGANIC_IGNORE).
         *
         * @private
         * @param {_gat.GA_Campaign_.Tracker_} campaignTracker Campaign tracker
         *     reference.
         *
         * @return {Boolean} Return true if and only if the campaign tracker is a valid
         *     organic campaign tracker, and the keyword is contained in the ignored
         *     watch list.
         */
        public function isIgnoredKeyword( tracker:CampaignTracker ):Boolean
        {
            // organic campaign, try to match ignored keywords
            if( tracker && (tracker.medium == "organic") )
            {
                return _config.organic.isIgnoredKeyword( tracker.term );
            }

            return false;
        }

        /**
         * This method returns true if and only if campaignTracker is a valid
         * referreal campaign tracker (utmcmd=referral), and the domain (utmcsr) is
         * contained in the ignore watch list (REFERRAL_IGNORE).
         *
         * @private
         * @param {String} campaignTracker String representation of the campaign
         *     tracker.
         *
         * @return {Boolean} Return true if and only if the campaign tracker is a
         *     valid referral campaign tracker, and the domain is contained in the
         *     ignored watch list.
         */
        public function isIgnoredReferral( tracker:CampaignTracker ):Boolean
        {
            // referral campaign, try to match ignored domains
            if( tracker && (tracker.medium == "referral") )
            {
                return _config.organic.isIgnoredReferral( tracker.source );
            }

            return false;
        }

        public function isValid( tracker:CampaignTracker ):Boolean
        {
            if( tracker && tracker.isValid() )
            {
                return true;
            }

            return false;
        }

        /**
        * Retrieves campaign tracker from search string.
        *
        * @param {String} searchString Search string to retrieve campaign tracker from.
        * @return {String} Return campaign tracker retrieved from search string.
        */
        public function getTrackerFromSearchString( search:String ):CampaignTracker
        {
            var organicCampaign:CampaignTracker = getOrganicCampaign();
            var camp:CampaignTracker            = new CampaignTracker();
            var key:CampaignKey                 = _config.campaignKey;

            if( search == "" )
            {
                return camp;
            }

            var variables:Variables = new Variables( search );

            //id
            if( variables.hasOwnProperty( key.UCID ) )
            {
                camp.id = variables[ key.UCID ];
            }

            //source
            if( variables.hasOwnProperty( key.UCSR ) )
            {
                camp.source = variables[ key.UCSR ];
            }

            //click id
            if( variables.hasOwnProperty( key.UGCLID ) )
            {
                camp.clickId = variables[ key.UGCLID ];
            }

            //name
            if( variables.hasOwnProperty( key.UCCN ) )
            {
                camp.name = variables[ key.UCCN ];
            }
            else
            {
                camp.name = "(not set)";
            }

            //medium
            if( variables.hasOwnProperty( key.UCMD ) )
            {
                camp.medium = variables[ key.UCMD ];
            }
            else
            {
                camp.medium = "(not set)";
            }

            //term
            if( variables.hasOwnProperty( key.UCTR ) )
            {
                camp.term = variables[ key.UCTR ];
            }
            else if( organicCampaign && organicCampaign.term != "" )
            {
                camp.term = organicCampaign.term;
            }

            //content
            if( variables.hasOwnProperty( key.UCCT ) )
            {
                camp.content = variables[ key.UCCT ];
            }

            return camp;
        }

    }
}

/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * 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.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 *   Marc Alcaraz <ekameleon@gmail.com>.
 */

package com.google.analytics.campaign
{
    import com.google.analytics.core.Buffer;
    import com.google.analytics.core.OrganicReferrer;
    import com.google.analytics.debug.DebugConfiguration;
    import com.google.analytics.debug.VisualDebugMode;
    import com.google.analytics.utils.Variables;
    import com.google.analytics.v4.Configuration;

    import core.uri;

    /**
     * The CampaignManager class.
     */
    public class CampaignManager
    {
        private var _config:Configuration;
        private var _debug:DebugConfiguration;
        private var _buffer:Buffer;

        private var _domainHash:Number;
        private var _referrer:String;
        private var _timeStamp:Number;

        /**
         * Delimiter for campaign tracker.
         */
        public static const trackingDelimiter:String = "|";

        /**
         * Creates a new CampaignManager instance.
         */
        public function CampaignManager( config:Configuration, debug:DebugConfiguration, buffer:Buffer,
                                         domainHash:Number, referrer:String, timeStamp:Number )
        {
            _config     = config;
            _debug      = debug;
            _buffer     = buffer;

            _domainHash = domainHash;
            _referrer   = referrer;
            _timeStamp  = timeStamp;
        }

        /**
         * This method will return true if and only document referrer is invalid.
         * Document referrer is considered to be invalid when it's empty (undefined,
         * empty string, "-", or "0"), or it's not a valid URL (doesn't have protocol)
         *
         * @private
         * @param {String} docRef Document referrer to be evaluated for validity.
         *
         * @return {Boolean} True if and only if document referrer is invalid.
         */
        public static function isInvalidReferrer( referrer:String ):Boolean
        {
            if( (referrer == "") ||
                (referrer == "-") ||
                (referrer == "0") )
            {
                return true;
            }

            var url:uri = new uri( referrer );

            if( (url.scheme == "file") ||
                (url.scheme == "") )
            {
                return true;
            }

            return false;
        }

        /**
         * Checks if the document referrer is from the google custom search engine.
         * @private
         * @return true if the referrer is from google custom search engine.
         */
        public static function isFromGoogleCSE( referrer:String, config:Configuration ):Boolean
        {
            var url:uri = new uri( referrer );

            if( url.host.indexOf( config.google ) > -1 )
            {
                if( (url.path == "/"+config.googleCsePath ) &&
                    (url.query.indexOf( config.googleSearchParam+"=" ) > -1) )
                {
                    return true;
                }
            }

            return false;
        }

        /**
         * Retrieves campaign information.  If linker functionality is allowed, and
         * the cookie parsed from search string is valid (hash matches), then load the
         * __utmz value form search string, and write the value to cookie, then return
         * "".  Otherwise, attempt to retrieve __utmz value from cookie.  Then
         * retrieve campaign information from search string.  If that fails, try
         * organic campaigns next.  If that fails, try referral campaigns next.  If
         * that fails, try direct campaigns next.  If it still fails, return nothing.
         * Finally, determine whether the campaign is duplicated.  If the campaign is
         * not duplicated, then write campaign information to cookie, and indicate
         * there is a new campaign for gif hit.  Else, just indicate this is a
         * repeated click for campaign.
         *
         * @private
         * @param {_gat.GA_Cookie_} inCookie GA_Cookie instance containing cookie
         *     values parsed in from URL (linker).  This value should never be
         *     undefined.
         * @param {Boolean} noSession Indicating whether a session has been
         *     initialized. If __utmb and/or __utmc cookies are not set, then session
         *     has either timed-out or havn't been initialized yet.
         *
         * @return {String} Gif hit key-value pair indicating wether this is a repeated
         *     click, or a brand new campaign for the visitor.
         */
        public function getCampaignInformation( search:String, noSessionInformation:Boolean ):CampaignInfo
        {
            var campInfo:CampaignInfo = new CampaignInfo();
            var campaignTracker:CampaignTracker;
            var duplicateCampaign:Boolean = false;
            var campNoOverride:Boolean = false;
            var responseCount:int = 0;

            /* Allow linker functionality, and cookie is parsed from URL, and the cookie
              hash matches.
            */
            if( _config.allowLinker && _buffer.isGenuine() )
            {
                if( !_buffer.hasUTMZ() )
                {
                    return campInfo;
                }
            }

            // retrieves tracker from search string
            campaignTracker = getTrackerFromSearchString( search );

            if( isValid( campaignTracker ) )
            {
                // check for no override flag in search string
                campNoOverride = hasNoOverride( search );

                // if no override is true, and there is a utmz value, then do nothing now
                if( campNoOverride && !_buffer.hasUTMZ() )
                {
                    return campInfo;
                }
            }

            // Get organic campaign if there is no campaign tracker from search string.
            if( !isValid( campaignTracker ) )
            {
                campaignTracker = getOrganicCampaign();

                //If there is utmz cookie value, and organic keyword is being ignored, do nothing.
                if( !_buffer.hasUTMZ() && isIgnoredKeyword( campaignTracker ) )
                {
                    return campInfo;
                }
            }

            /* Get referral campaign if there is no campaign tracker from search string
               and organic campaign, and either utmb or utmc is missing (no session).
            */
            if( !isValid( campaignTracker ) && noSessionInformation )
            {
                campaignTracker = getReferrerCampaign();

                //If there is utmz cookie value, and referral domain is being ignored, do nothing
                if( !_buffer.hasUTMZ() && isIgnoredReferral( campaignTracker ) )
                {
                    return campInfo;
                }
            }

            /* Get direct campaign if there is no campaign tracker from search string,
              organic campaign, or referral campaign.
            */
            if( !isValid( campaignTracker ) )
            {
                /* Only get direct campaign when there is no utmz cookie value, and there is
                   no session. (utmb or utmc is missing value)
                */
                if( !_buffer.hasUTMZ() && noSessionInformation )
                {
                    campaignTracker = getDirectCampaign();
                }

            }

            //Give up (do nothing) if still cannot get campaign tracker.
            if( !isValid( campaignTracker ) )
            {
                return campInfo;
            }

            //utmz cookie have value, check whether campaign is duplicated.
            if( _buffer.hasUTMZ() && !_buffer.utmz.isEmpty() )
            {
                var oldTracker:CampaignTracker = new CampaignTracker();
                    oldTracker.fromTrackerString( _buffer.utmz.campaignTracking );

                duplicateCampaign = ( oldTracker.toTrackerString() == campaignTracker.toTrackerString() );

                responseCount = _buffer.utmz.responseCount;
            }

            /* Record as new campaign if and only if campaign is not duplicated, or there
              is no session information.
            */
            if( !duplicateCampaign || noSessionInformation )
            {
                var sessionCount:int = _buffer.utma.sessionCount;
                responseCount++;

                // if there is no session number, increment
                if( sessionCount == 0 )
                {
                    sessionCount = 1;
                }

                // construct utmz cookie
                _buffer.utmz.domainHash       = _domainHash;
                _buffer.utmz.campaignCreation = _timeStamp;
                _buffer.utmz.campaignSessions = sessionCount;
                _buffer.utmz.responseCount    = responseCount;
                _buffer.utmz.campaignTracking = campaignTracker.toTrackerString();

                _debug.info( _buffer.utmz.toString(), VisualDebugMode.geek );

                // indicate new campaign
                campInfo = new CampaignInfo( false, true );
            }
            else
            {
                // indicate repeated campaign
                campInfo = new CampaignInfo( false, false );
            }

            return campInfo;
        }

        /**
         * This method returns the organic campaign information.
         * @private
         * @return {_gat.GA_Campaign_.Tracker_} Returns undefined if referrer is not
         * a matching organic campaign source. Otherwise, returns the campaign tracker object.
         */
        public function getOrganicCampaign():CampaignTracker
        {
            var camp:CampaignTracker;

            // if there is no referrer, or referrer is not a valid URL, or the referrer
            // is google custom search engine, return an empty tracker
            if( isInvalidReferrer( _referrer ) || isFromGoogleCSE( _referrer, _config ) )
            {
                return camp;
            }

            var ref:uri = new uri( _referrer );
            var name:String;

            if( (ref.host != "") && (ref.host.indexOf(".") > -1) )
            {
                var tmp:Array = ref.host.split( "." );

                switch( tmp.length )
                {
                    case 2:
                    name = tmp[0];
                    break;

                    case 3:
                    name = tmp[1];
                }
            }

            // organic source match
            if( _config.organic.match( name ) )
            {
                var currentOrganicSource:OrganicReferrer = _config.organic.getReferrerByName( name );

                // extract keyword value from query string
                var keyword:String = _config.organic.getKeywordValue( currentOrganicSource, ref.query );

                camp = new CampaignTracker();
                camp.source = currentOrganicSource.engine;
                camp.name   = "(organic)";
                camp.medium = "organic";
                camp.term   = keyword;
            }

            return camp;
        }

        /**
         * This method returns the referral campaign information.
         *
         * @private
         * @return {_gat.GA_Campaign_.Tracker_} Returns nothing if there is no
         *     referrer. Otherwise, return referrer campaign tracker.
         */
        public function getReferrerCampaign():CampaignTracker
        {
            var camp:CampaignTracker;

            // if there is no referrer, or referrer is not a valid URL, or the referrer
            // is google custom search engine, return an empty tracker
            if( isInvalidReferrer( _referrer ) || isFromGoogleCSE( _referrer, _config ) )
            {
                return camp;
            }

            // get host name from referrer
            var ref:uri = new uri( _referrer );
            var hostname:String = ref.host;
            var content:String  = ref.path;

            if( content == "" ) { content = "/"; } //fix empty path

            if( hostname.indexOf( "www." ) == 0 )
            {
                hostname = hostname.substr( 4 );
            }

            camp = new CampaignTracker();
            camp.source  = hostname;
            camp.name    = "(referral)";
            camp.medium  = "referral";
            camp.content = content;

            return camp;
        }

        /**
         * Returns the direct campaign tracker string.
         * @private
         * @return {_gat.GA_Campaign_.Tracker_} Direct campaign tracker object.
         */
        public function getDirectCampaign():CampaignTracker
        {
            var camp:CampaignTracker = new CampaignTracker();
                camp.source = "(direct)";
                camp.name   = "(direct)";
                camp.medium = "(none)";

            return camp;
        }

        /**
         * Indicates if the manager has no override with the search value.
         */
        public function hasNoOverride( search:String ):Boolean
        {
            var key:CampaignKey = _config.campaignKey;

            if( search == "" )
            {
                return false;
            }

            var variables:Variables = new Variables( search );
            var value:String           = "";

            if( variables.hasOwnProperty( key.UCNO ) )
            {
                value = variables[ key.UCNO ];

                switch( value )
                {
                    case "1":
                    return true;

                    case "":
                    case "0":
                    default:
                    return false;
                }
            }

            return false;
        }

        /**
         * This method returns true if and only if campaignTracker is a valid organic
         * campaign tracker (utmcmd=organic), and the keyword (utmctr) is contained in
         * the ignore watch list (ORGANIC_IGNORE).
         *
         * @private
         * @param {_gat.GA_Campaign_.Tracker_} campaignTracker Campaign tracker
         *     reference.
         *
         * @return {Boolean} Return true if and only if the campaign tracker is a valid
         *     organic campaign tracker, and the keyword is contained in the ignored
         *     watch list.
         */
        public function isIgnoredKeyword( tracker:CampaignTracker ):Boolean
        {
            // organic campaign, try to match ignored keywords
            if( tracker && (tracker.medium == "organic") )
            {
                return _config.organic.isIgnoredKeyword( tracker.term );
            }

            return false;
        }

        /**
         * This method returns true if and only if campaignTracker is a valid
         * referreal campaign tracker (utmcmd=referral), and the domain (utmcsr) is
         * contained in the ignore watch list (REFERRAL_IGNORE).
         *
         * @private
         * @param {String} campaignTracker String representation of the campaign
         *     tracker.
         *
         * @return {Boolean} Return true if and only if the campaign tracker is a
         *     valid referral campaign tracker, and the domain is contained in the
         *     ignored watch list.
         */
        public function isIgnoredReferral( tracker:CampaignTracker ):Boolean
        {
            // referral campaign, try to match ignored domains
            if( tracker && (tracker.medium == "referral") )
            {
                return _config.organic.isIgnoredReferral( tracker.source );
            }

            return false;
        }

        public function isValid( tracker:CampaignTracker ):Boolean
        {
            if( tracker && tracker.isValid() )
            {
                return true;
            }

            return false;
        }

        /**
        * Retrieves campaign tracker from search string.
        *
        * @param {String} searchString Search string to retrieve campaign tracker from.
        * @return {String} Return campaign tracker retrieved from search string.
        */
        public function getTrackerFromSearchString( search:String ):CampaignTracker
        {
            var organicCampaign:CampaignTracker = getOrganicCampaign();
            var camp:CampaignTracker            = new CampaignTracker();
            var key:CampaignKey                 = _config.campaignKey;

            if( search == "" )
            {
                return camp;
            }

            var variables:Variables = new Variables( search );

            //id
            if( variables.hasOwnProperty( key.UCID ) )
            {
                camp.id = variables[ key.UCID ];
            }

            //source
            if( variables.hasOwnProperty( key.UCSR ) )
            {
                camp.source = variables[ key.UCSR ];
            }

            //click id
            if( variables.hasOwnProperty( key.UGCLID ) )
            {
                camp.clickId = variables[ key.UGCLID ];
            }

            //name
            if( variables.hasOwnProperty( key.UCCN ) )
            {
                camp.name = variables[ key.UCCN ];
            }
            else
            {
                camp.name = "(not set)";
            }

            //medium
            if( variables.hasOwnProperty( key.UCMD ) )
            {
                camp.medium = variables[ key.UCMD ];
            }
            else
            {
                camp.medium = "(not set)";
            }

            //term
            if( variables.hasOwnProperty( key.UCTR ) )
            {
                camp.term = variables[ key.UCTR ];
            }
            else if( organicCampaign && organicCampaign.term != "" )
            {
                camp.term = organicCampaign.term;
            }

            //content
            if( variables.hasOwnProperty( key.UCCT ) )
            {
                camp.content = variables[ key.UCCT ];
            }

            return camp;
        }

    }
}

replace URL class by core.uri

replace URL class by core.uri