In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Bayes Visualization

This app is based on the visualization of Bayes' Theorem described in this post: http://lesswrong.com/lw/2b0/bayes_theorem_illustrated_my_way/

This app was designed for a window size of 800x600.  You will need to click the "Preview Fullscreen" button in order to see the right half of the app.

or view the version at http://peerinfinity.com/BayesVisualization/
Get Adobe Flash player
by PeerInfinity 13 Mar 2012
/**
 * Copyright PeerInfinity ( http://wonderfl.net/user/PeerInfinity )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/32WF
 */

// This app is based on the visualization of Bayes' Theorem described in this post:
// http://lesswrong.com/lw/2b0/bayes_theorem_illustrated_my_way/

// This app was designed for a window size of 800x600.
// You will need to click the "Preview Fullscreen" button
// in order to see the right half of the app.

// or view the version at http://peerinfinity.com/BayesVisualization/

// this app has known bugs.
// Any help fixing these bugs or adding features is appreciated.

package 
{
    import flash.display.Sprite;
    import flash.events.Event;

    import flash.display.*;
    import flash.text.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.ui.*;
    
    public class Main extends Sprite
    {
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            
            var newFormat:TextFormat;
            
            m_Label_HypothesisCount = new TextField();
            m_Label_HypothesisCount.text = "Number of Hypotheses:";
            m_Label_HypothesisCount.width = 130;

            newFormat = m_Label_HypothesisCount.getTextFormat();
            newFormat.size = 12;
            newFormat.align = TextFormatAlign.RIGHT;
            m_Label_HypothesisCount.setTextFormat(newFormat);

            m_Label_HypothesisCount.x = 0;
            m_Label_HypothesisCount.y = 10;
            
            addChild(m_Label_HypothesisCount);
            
            m_Edit_HypothesisCount = new TextField();

            m_Edit_HypothesisCount.text = "2";
            
            m_Edit_HypothesisCount.type = TextFieldType.INPUT;
            m_Edit_HypothesisCount.selectable = true;
            mouseChildren = true;
            m_Edit_HypothesisCount.border = true;
            m_Edit_HypothesisCount.background = true;
            m_Edit_HypothesisCount.textColor = 0x000000;
            m_Edit_HypothesisCount.multiline = false;

            newFormat = m_Edit_HypothesisCount.getTextFormat();
            newFormat.size = 12;
            newFormat.align = TextFormatAlign.RIGHT;
            m_Edit_HypothesisCount.setTextFormat(newFormat);

            //m_Edit_HypothesisCount.autoSize = TextFieldAutoSize.CENTER;
            m_Edit_HypothesisCount.width = 40;
            m_Edit_HypothesisCount.height = 20;
            
            m_Edit_HypothesisCount.x = m_Label_HypothesisCount.x + m_Label_HypothesisCount.width + 2;
            m_Edit_HypothesisCount.y = 10;

            //trace(m_Label_HypothesisCount.x);
            //trace(m_Label_HypothesisCount.width);
            //trace(m_Edit_HypothesisCount.x);
            //trace(m_Edit_HypothesisCount.width);
            
            addChild(m_Edit_HypothesisCount);
            
            m_Edit_HypothesisCount.addEventListener(Event.CHANGE, HypothesisCountChanged);
            
            ResetEverything();
        }
        
        private function HypothesisCountChanged(e:Event):void
        {
            //trace("event");
            if ( Number(m_Edit_HypothesisCount.text) > 10 || Number(m_Edit_HypothesisCount.text) < 2 )
            {
                m_Label_HypothesisCount.textColor = 0xFF0000;
            }
            else
            {
                m_Label_HypothesisCount.textColor = 0x000000;
                
                ResetEverything();
            }
        }
        
        private function ResetEverything():void
        {
            var hypothesisCount:int = Number(m_Edit_HypothesisCount.text);
            
            //trace(hypothesisCount);
            
            var i:uint = 0;
            var j:uint = 0;
            var newFormat:TextFormat;
            
            for each( var CurrentRow:DisplayRow in m_Array_DisplayRows )
            {
                CurrentRow.ClearDisplayRow();
            }
            
            m_Array_DisplayRows = [];

            graphics.clear();
            
            for( i = 0; i < hypothesisCount; i++ )
            {
                m_Array_DisplayRows[i] = new DisplayRow();
                
                m_Array_DisplayRows[i].m_Index = i;
                
                m_Array_DisplayRows[i].ResetDisplayRow();
                
                addChild(m_Array_DisplayRows[i]);
            }
        }
    }
}

import flash.display.*;
import flash.text.*;
import flash.events.*;
import flash.geom.*;
import flash.ui.*;

var m_Label_HypothesisCount:TextField;
var m_Edit_HypothesisCount:TextField;

var m_Array_DisplayRows:Array = [];
        
var g_ColorArray:Array = [0x0000FF, 0x00FF00, 0x00FFFF, 0xFF0000, 0xFF00FF, 0xFFFF00, 0x000080, 0x008000, 0x800000, 0x808080];

class DisplayRow extends Sprite
{
    public var m_Index:int;
    
    public var m_Label_PriorProbability:TextField;
    public var m_Edit_PriorProbability:TextField;
    public var m_PriorProbabilityAfterLastUpdate:Number;
    
    public var m_HypothesisShape:HypothesisShape;
    
    public var m_Array_ResultRows:Array;
    
    public var m_AlreadyUpdatingPriorProbability:Boolean = false;

    public function ClearDisplayRow():void
    {
        removeChild(m_Label_PriorProbability);
        removeChild(m_Edit_PriorProbability);
        removeChild(m_HypothesisShape);
        
        for each( var CurrentRow:ResultRow in m_Array_ResultRows )
        {
            CurrentRow.ClearResultRow();
        }
    }
    
    public function ResetDisplayRow():void
    {
        var i:uint = m_Index;
        var j:uint = 0;
        
        var hypothesisCount:int = Number(m_Edit_HypothesisCount.text);
        
        var newFormat:TextFormat;
        
        var priorProbability:Number = 1 / hypothesisCount;
        m_PriorProbabilityAfterLastUpdate = priorProbability * 100;
        
        m_Label_PriorProbability = new TextField();
        m_Label_PriorProbability.text = "Prior Probability of H" + (i+1) + ":";
        m_Label_PriorProbability.width = 130;

        newFormat = m_Label_PriorProbability.getTextFormat();
        newFormat.size = 12;
        newFormat.align = TextFormatAlign.RIGHT;
        m_Label_PriorProbability.setTextFormat(newFormat);

        m_Label_PriorProbability.x = 0;
        m_Label_PriorProbability.y = 40 + (i * 110);
        
        addChild(m_Label_PriorProbability);
        
        m_Edit_PriorProbability = new TextField();
        
        m_Edit_PriorProbability.text = String(100/hypothesisCount);
        
        m_Edit_PriorProbability.type = TextFieldType.INPUT;
        m_Edit_PriorProbability.selectable = true;
        mouseChildren = true;
        m_Edit_PriorProbability.border = true;
        m_Edit_PriorProbability.background = true;
        m_Edit_PriorProbability.textColor = 0x000000;
        m_Edit_PriorProbability.multiline = false;

        newFormat = m_Edit_PriorProbability.getTextFormat();
        newFormat.size = 12;
        newFormat.align = TextFormatAlign.RIGHT;
        m_Edit_PriorProbability.setTextFormat(newFormat);

        //m_Edit_PriorProbability.autoSize = TextFieldAutoSize.CENTER;
        m_Edit_PriorProbability.width = 40;
        m_Edit_PriorProbability.height = 20;
        
        m_Edit_PriorProbability.x = m_Label_HypothesisCount.x + m_Label_HypothesisCount.width + 2;
        m_Edit_PriorProbability.y = m_Label_PriorProbability.y;

        //trace(m_Label_HypothesisCount.x);
        //trace(m_Label_HypothesisCount.width);
        //trace(m_Edit_PriorProbability.x);
        //trace(m_Edit_PriorProbability.width);
        
        addChild(m_Edit_PriorProbability);

        
        m_HypothesisShape = new HypothesisShape();
        
        m_HypothesisShape.m_size = priorProbability;
        m_HypothesisShape.m_color = g_ColorArray[i];
        
        m_HypothesisShape.DrawHypothesisShape();
        
        m_HypothesisShape.x = m_Edit_PriorProbability.x + m_Edit_PriorProbability.width + 10;
        m_HypothesisShape.y = m_Edit_PriorProbability.y;
        
        addChild(m_HypothesisShape);
        
        m_Array_ResultRows = [];
        
        for( j = 0; j < hypothesisCount; j++ )
        {
            m_Array_ResultRows[j] = new ResultRow();
            
            m_Array_ResultRows[j].m_ParentIndex = i;
            m_Array_ResultRows[j].m_Index = j;
            
            m_Array_ResultRows[j].m_Parent = this;
            
            m_Array_ResultRows[j].ResetResultRow();
            
            addChild(m_Array_ResultRows[j]);
        }
        
        m_Edit_PriorProbability.addEventListener(Event.CHANGE, PriorProbabilityChanged);
    }

    // this only gets called when the user changes the value, not when the code changes the edit box's text value?
    private function PriorProbabilityChanged(e:Event):void
    {
        var newPriorProbability:Number = Number(m_Edit_PriorProbability.text);

        if ( newPriorProbability > 100 || newPriorProbability < 0 )
        {
            m_Label_PriorProbability.textColor = 0xFF0000;
        }
        else
        {
            m_Label_PriorProbability.textColor = 0x000000;
            
            DoPriorProbabilityChanged();
        }
    }
    
    public function DoPriorProbabilityChanged():void
    {
        if ( !m_AlreadyUpdatingPriorProbability )
        {
            m_AlreadyUpdatingPriorProbability = true;
            
            var newPriorProbability:Number = Number(m_Edit_PriorProbability.text);

            var totalPriorProbability:Number = newPriorProbability;

            for each( var CurrentRow:DisplayRow in m_Array_DisplayRows )
            {
                if ( !CurrentRow.m_AlreadyUpdatingPriorProbability )
                {
                    if ( totalPriorProbability + Number(CurrentRow.m_Edit_PriorProbability.text) > 100 )
                    {
                        CurrentRow.m_Edit_PriorProbability.text = String( 100 - totalPriorProbability );
                        
                        // because this doesn't happen automatically
                        CurrentRow.DoPriorProbabilityChanged();
                    }
                    
                    totalPriorProbability += Number(CurrentRow.m_Edit_PriorProbability.text);
                }
            }
            
            ResizeDisplayRowShapes(newPriorProbability);

            for each( var CurrentRow2:ResultRow in m_Array_ResultRows )
            {
                //CurrentRow2.ResizeResultRowShapes();
                //CurrentRow2.DoResultProbabilityChanged();
                
                var prevVal:Number = Number(CurrentRow2.m_Edit_ResultProbability.text);
                
                var newVal:Number = prevVal / m_PriorProbabilityAfterLastUpdate * newPriorProbability;
                
                CurrentRow2.m_Edit_ResultProbability.text = String(newVal);
                
                CurrentRow2.ResizeResultRowShapes(newVal);
            }
            
            m_PriorProbabilityAfterLastUpdate = newPriorProbability;

            m_AlreadyUpdatingPriorProbability = false;
        }
    }
    
    public function ResizeDisplayRowShapes(newPriorProbability:int):void
    {
        m_HypothesisShape.m_size = newPriorProbability / 100;
        
        m_HypothesisShape.DrawHypothesisShape();
    }
}

class ResultRow extends Sprite
{
    public var m_ParentIndex:int;
    public var m_Index:int;
    
    public var m_Parent:DisplayRow;
    
    public var m_Edit_ResultProbability:TextField;
    public var m_ResultProbabilityAfterLastUpdate:Number;
    
    public var m_ResultShape:ResultShape;

    public var m_Label_UnscaledProbability:TextField;
    public var m_Label_RescaledProbability:TextField;
    
    public var m_AlreadyUpdatingResultProbability:Boolean = false;

    public function ClearResultRow():void
    {
        removeChild(m_Edit_ResultProbability);
        removeChild(m_ResultShape);
        removeChild(m_Label_UnscaledProbability);
        removeChild(m_Label_RescaledProbability);
    }
    
    public function ResetResultRow():void
    {
        var i:uint = m_ParentIndex;
        var j:uint = m_Index;
        
        var hypothesisCount:int = Number(m_Edit_HypothesisCount.text);
        
        var newFormat:TextFormat;
        
        var priorProbability:Number = 1 / hypothesisCount;
        //var resultProbability:Number = priorProbability / hypothesisCount;
        var resultProbability:Number = priorProbability;
        m_ResultProbabilityAfterLastUpdate = resultProbability * 100;
        
        m_Edit_ResultProbability = new TextField();

        m_Edit_ResultProbability.text = String(resultProbability * 100);
        
        m_Edit_ResultProbability.type = TextFieldType.INPUT;
        m_Edit_ResultProbability.selectable = true;
        mouseChildren = true;
        m_Edit_ResultProbability.border = true;
        m_Edit_ResultProbability.background = true;
        m_Edit_ResultProbability.textColor = 0x000000;
        m_Edit_ResultProbability.multiline = false;

        newFormat = m_Edit_ResultProbability.getTextFormat();
        newFormat.size = 12;
        newFormat.align = TextFormatAlign.RIGHT;
        m_Edit_ResultProbability.setTextFormat(newFormat);

        //m_Edit_ResultProbability.autoSize = TextFieldAutoSize.CENTER;
        m_Edit_ResultProbability.width = 40;
        m_Edit_ResultProbability.height = 20;
        
        m_Edit_ResultProbability.x = m_Parent.m_HypothesisShape.x + 100 + 2;
        m_Edit_ResultProbability.y = m_Parent.m_HypothesisShape.y + ( j * ( 100 / hypothesisCount ) );

        //trace(m_Label_HypothesisCount.x);
        //trace(m_Label_HypothesisCount.width);
        //trace(m_Edit_ResultProbability.x);
        //trace(m_Edit_ResultProbability.width);
        
        addChild(m_Edit_ResultProbability);

        
        m_ResultShape = new ResultShape();
        
        m_ResultShape.m_size = resultProbability;
        m_ResultShape.m_color = g_ColorArray[i];
        m_ResultShape.m_sides = 3 + j;
        
        m_ResultShape.DrawResultShape();
        
        m_ResultShape.x = m_Edit_ResultProbability.x + m_Edit_ResultProbability.width + 10;
        m_ResultShape.y = m_Edit_ResultProbability.y;
        
        addChild(m_ResultShape);

        
        m_Label_UnscaledProbability = new TextField();
        m_Label_UnscaledProbability.text = "Unscaled Result R" + (j+1) + ":";
        m_Label_UnscaledProbability.width = 130;

        newFormat = m_Label_UnscaledProbability.getTextFormat();
        newFormat.size = 12;
        newFormat.align = TextFormatAlign.RIGHT;
        m_Label_UnscaledProbability.setTextFormat(newFormat);

        m_Label_UnscaledProbability.x = m_ResultShape.x + 100;
        m_Label_UnscaledProbability.y = m_ResultShape.y;
        
        addChild(m_Label_UnscaledProbability);

        
        m_Label_RescaledProbability = new TextField();
        m_Label_RescaledProbability.text = "Rescaled Result R" + (j+1) + ":";
        m_Label_RescaledProbability.width = 130;

        newFormat = m_Label_RescaledProbability.getTextFormat();
        newFormat.size = 12;
        newFormat.align = TextFormatAlign.RIGHT;
        m_Label_RescaledProbability.setTextFormat(newFormat);

        m_Label_RescaledProbability.x = m_Label_UnscaledProbability.x + m_Label_UnscaledProbability.width;
        m_Label_RescaledProbability.y = m_Label_UnscaledProbability.y;
        
        addChild(m_Label_RescaledProbability);
        
        m_Edit_ResultProbability.addEventListener(Event.CHANGE, ResultProbabilityChanged);
    }

    // this only gets called when the user changes the value, not when the code changes the edit box's text value?
    private function ResultProbabilityChanged(e:Event):void
    {
        //var maxProbability:Number = Number(m_Parent.m_Edit_PriorProbability.text);
        var maxProbability:Number = 100;

        var newResultProbability:Number = Number(m_Edit_ResultProbability.text);

        if ( newResultProbability > maxProbability || newResultProbability < 0 )
        {
            m_Label_UnscaledProbability.textColor = 0xFF0000;
            m_Label_RescaledProbability.textColor = 0xFF0000;
        }
        else
        {
            m_Label_UnscaledProbability.textColor = 0x000000;
            m_Label_RescaledProbability.textColor = 0x000000;

            DoResultProbabilityChanged();
        }
    }
    
    public function DoResultProbabilityChanged():void
    {
        if ( !m_AlreadyUpdatingResultProbability )
        {
            m_AlreadyUpdatingResultProbability = true;
            
            //var maxProbability:Number = Number(m_Parent.m_Edit_PriorProbability.text);
            var maxProbability:Number = 100;

            var newResultProbability:Number = Number(m_Edit_ResultProbability.text);

            var totalResultProbability:Number = newResultProbability;
            
            for each( var CurrentRow:ResultRow in m_Parent.m_Array_ResultRows )
            {
                if ( !CurrentRow.m_AlreadyUpdatingResultProbability )
                {
                    if ( totalResultProbability + Number(CurrentRow.m_Edit_ResultProbability.text) > maxProbability )
                    {
                        CurrentRow.m_Edit_ResultProbability.text = String( maxProbability - totalResultProbability );
                        
                        // because this doesn't happen automatically
                        CurrentRow.DoResultProbabilityChanged();
                    }
                    
                    totalResultProbability += Number(CurrentRow.m_Edit_ResultProbability.text);
                }
            }
            
            ResizeResultRowShapes(newResultProbability);

            m_ResultProbabilityAfterLastUpdate = newResultProbability;

            m_AlreadyUpdatingResultProbability = false;
        }
    }
    
    public function ResizeResultRowShapes(newResultProbability:int):void
    {
        m_ResultShape.m_size = newResultProbability / 100;
        
        m_ResultShape.DrawResultShape();
        
        var totalUnscaled:Number = 0;
        
        var i:int = 0;
        
        var count:int = Number(m_Edit_HypothesisCount.text);
        
        for ( i = 0; i < count; i++ )
        {
            //var tempUnscaled:Number = 1;
            var tempUnscaled:Number = ( Number(m_Array_DisplayRows[i].m_Array_ResultRows[m_Index].m_Edit_ResultProbability.text) * Number(m_Array_DisplayRows[i].m_Edit_PriorProbability.text) / 100 );
            
            //trace(m_Array_DisplayRows[i].m_Edit_PriorProbability.text);
            //trace(m_Array_DisplayRows[i].m_Array_ResultRows[m_Index].m_Edit_ResultProbability.text);
            
            totalUnscaled += tempUnscaled;
        }
        
        for ( i = 0; i < count; i++ )
        {
            var currentUnscaled:Number = ( Number(m_Array_DisplayRows[i].m_Array_ResultRows[m_Index].m_Edit_ResultProbability.text) * Number(m_Array_DisplayRows[i].m_Edit_PriorProbability.text) / 100 );
            var currentRescaled:Number = currentUnscaled / totalUnscaled * 100;
            
            //CurrentRow2.m_Label_UnscaledProbability.text = "Unscaled Result R" + (CurrentRow2.m_Index+1) + ": " + currentUnscaled;
            //CurrentRow2.m_Label_RescaledProbability.text = "Rescaled Result R" + (CurrentRow2.m_Index+1) + ": " + currentRescaled;
            m_Array_DisplayRows[i].m_Array_ResultRows[m_Index].m_Label_UnscaledProbability.text = "Unscaled Result: " + currentUnscaled;
            m_Array_DisplayRows[i].m_Array_ResultRows[m_Index].m_Label_RescaledProbability.text = "Rescaled Result: " + currentRescaled;
        }
        
    }
}

class HypothesisShape extends Sprite
{
    public var m_size:Number;
    public var m_color:int;
    
    public function DrawHypothesisShape():void
    {
        graphics.clear();
        graphics.beginFill(m_color);
        graphics.lineStyle(2, 0x000000);
        //graphics.drawRect(0, 0, 100*m_size, 100*m_size);
        graphics.drawCircle(50*m_size, 50*m_size, 50*m_size);
        graphics.endFill();
    }
}

// done quick and dirty.  a quick google search didn't find a standard class for regular polygons
class ResultShape extends Sprite
{
    public var m_size:Number;
    public var m_color:int;
    public var m_sides:int;
    
    public function DrawResultShape():void
    {
        graphics.clear();
        
//        graphics.beginFill(m_color);
//        graphics.lineStyle(2, 0x000000);
//        graphics.drawRect(0, 0, 100*m_size, 100*m_size);
        //graphics.drawCircle(50*m_size, 50*m_size, 50*m_size);
//        graphics.endFill();

        const REVOLUTION:int = 360;
        var _radius:int = 100/Number(m_Edit_HypothesisCount.text)*m_size;
        var _sides:int = m_sides;
        var _strokeThickness:int = 2;
        var _strokeColor:int = 0x000000;
        var _fillColor:int;
        var _strokeAlpha:Number;
        var _fillAlpha:Number;
        var _angle:int = 0;

        _fillColor = m_color;
        _fillAlpha = 1;
        _strokeColor = 0x000000;
        _strokeAlpha = 1;
        _strokeThickness = 2;
        _angle = REVOLUTION;
        
        var angle:Number = 0;
        var angleInc:Number = (REVOLUTION / _sides);
        var xpos:Number = 0;
        var ypos:Number = 0;
        xpos = getAngleX(_radius, angle);
        ypos = getAngleY(_radius, angle);
        //graphics.clear();
        if(_strokeColor > -1) graphics.lineStyle(_strokeThickness, _strokeColor, _strokeAlpha);
        graphics.moveTo(xpos+_radius, ypos+_radius);
        graphics.beginFill(_fillColor, _fillAlpha);
        while(angle <= _angle)
        {
            xpos = getAngleX(_radius, angle);
            ypos = getAngleY(_radius, angle);
            angle += angleInc;
            graphics.lineTo(xpos+_radius,ypos+_radius);
        }

        graphics.endFill();
    }

    public function getAngleX(r:Number, Angle:Number):Number { return (  r * Math.cos((90 - Angle) * Math.PI / 180)); }
    public function getAngleY(r:Number, Angle:Number):Number { return ( -r * Math.sin((90 - Angle) * Math.PI / 180)); } 
    
}

//todo - add a message to report when the probabilities add up to less than 100?
// and a button to automatically update one probability to make the total 100?
// or just make the math support probability totals of less than 100?