Is there a way to generate true random numbers in Flash Builder? - actionscript-3

I have a project that generates strings of random numbers that are used to select items from a test bank. I noticed that some of the items were being selected at disproportionately high rates so I decided to check the 'randomness' of Math.Random.
The following code produces randomly ordered lists of the numbers 0 through n-1. It then counts the number of times the first item is a 0, 1, 2,... ,n-1
You can change the number of samples that are generated with the horizontal slider.
What I have produced appears to indicate that the random numbers are not at all random For example, if I select 100 samples of a six digit string, I get the following distribution suggesting that 0, and 5 are greatly under represented: 11,23,15,18,24,9
This pattern holds as I re-run the simulation.
I've checked my code but would greatly appreciate the insight of others concerning the accuracy of this.
I've heard that AS3 does not produce true random numbers, but can they really be this bad?
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="955" minHeight="600" >
<mx:Script>
<![CDATA[
import mx.events.ListEvent;
private var startingArray:Array = [];
private var questionsArray:Array;
private var countArray:Array;
private var randomNumbers:int = 3;
private function calculate():void{
countArray = [0,0,0,0,0,0,0,0,0,0];
for( var i:int = 0; i < slider.value; i++){
questionsArray = [];//Reset the list of questions
createRandomListOfQuestions(randomNumbers);
}
result.text = String(countArray);
}
public function createRandomListOfQuestions(_numQuestions:int):void{
//Create an array containing the sequence of test questions
var numQuestions:int=_numQuestions;
//Reset the array
startingArray=[];//Contains a randomized question order
for (var i:int=0;i<numQuestions; i++){//Create an array of question numbers starting at 1
var count:int = 0
startingArray.push(i);
}
//splice() removes one or more elements from an array and returns the deleted elements,
//here only one (as specified in the second argument)
while (startingArray.length > 0) {//Create a randomized list (questionsArray) from startingArray
var val:int =startingArray.splice(Math.round(Math.random() * (startingArray.length - 1)), 1)
questionsArray.push(val);
if(count == 0){
countArray[val] += 1
count++
}
}
questionsArrayText.text += String(questionsArray) + "\r";
}
private function changeEvt(event:Event):void {
randomNumbers = event.currentTarget.selectedItem.data
}
]]>
</mx:Script>
<mx:VBox horizontalCenter="0" verticalCenter="0">
<mx:Text x="487" y="261" text="{}" width="500" id="result"/>
<mx:ComboBox change="changeEvt(event)" >
<mx:ArrayCollection>
<mx:Object label="Three" data="3"/>
<mx:Object label="Four" data="4"/>
<mx:Object label="Five" data="5"/>
<mx:Object label="Six" data="6"/>
<mx:Object label="Seven" data="7"/>
<mx:Object label="Eight" data="8"/>
<mx:Object label="Nine" data="9"/>
<mx:Object label="Ten" data="10"/>
</mx:ArrayCollection>
</mx:ComboBox>
<mx:Button label="New list" click="calculate()"/>
<mx:HSlider id="slider" value="5" minimum="5" maximum="100" snapInterval="1" />
<mx:Label text="Random Numbers: {Math.round(slider.value) }"/>
</mx:VBox>
<mx:Text id="questionsArrayText" horizontalCenter="0" verticalCenter="0"/>
</mx:Application>

There are numerous implementations of custom random number generation available; however, ActionScript's Math.random() produces an expected distribution given a fair number of samples.
Below are distributions via Math.random() generating a number between 0 and 100. Vertical axis shows the number of times that value was generated.
1,000,000 Samples
100,000 Samples
10,000 Samples
1,000 Samples
100 Samples
Code to generate and visualize samples:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.collections.ArrayList;
import mx.events.FlexEvent;
[Bindable]
protected var data:ArrayList = new ArrayList();
protected function creationCompleteHandler(event:FlexEvent):void
{
var i:uint = 0;
var set:Dictionary = new Dictionary();
const ITERATIONS:uint = 100;
for (i = 0; i < 100; i++)
{
set[i] = {value: i, count: 0};
}
for (i = 0; i < ITERATIONS; i++)
{
var n:uint = Math.random() * 100;
set[n].count++;
}
for (i = 0; i < 100; i++)
{
data.addItem({value: set[i].value, count: set[i].count});
}
}
]]>
</fx:Script>
<fx:Declarations>
<mx:SolidColor id="areaFill"
color="0x123456"
alpha=".3" />
<mx:SolidColorStroke id="areaStroke"
color="0x123456" />
</fx:Declarations>
<mx:AreaChart height="100%"
width="100%"
paddingLeft="5"
paddingRight="5"
showDataTips="true"
dataProvider="{data}">
<mx:verticalAxis>
<mx:LinearAxis title="count" />
</mx:verticalAxis>
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="value"
title="value" />
</mx:horizontalAxis>
<mx:series>
<mx:AreaSeries yField="count"
areaStroke="{areaStroke}"
areaFill="{areaFill}">
</mx:AreaSeries>
</mx:series>
</mx:AreaChart>
</s:Application>

You may call random.org, but you will have to wait until the web site returns using an event listener.
function getRandomNum(min, max) {
var randTextURLRequest:URLRequest = new URLRequest("http://www.random.org/integers/?num=1&min=" + min + "&max=" + max + "&col=1&base=10&format=plain&rnd=new");
var randTextLoader:URLLoader = new URLLoader();
randTextLoader.addEventListener(Event.COMPLETE, randCompleteHandler);
randTextLoader.load(randTextURLRequest);
}
function randCompleteHandler(e:Event)
{
var randVal = Number(randTextLoader.data);
trace("Number " + randVal + " selected");
}
// You may then type in your code getRandomNum(1, 100)

Related

Increase height of reflected object

Want to reflect an image, and my code looks like
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
height="500" width="500"
creationComplete="init(event)">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import flash.filters.BlurFilter;
import mx.core.UIComponent;
import mx.events.FlexEvent;
private var loader:Loader = new Loader();
private var picture:BitmapData;
private var reflection:BitmapData;
private var reflectionHolder:Bitmap;
protected function init(event:FlexEvent):void
{
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest("assets/rectangle.png"));
}
private function onComplete (event:Event):void
{
trace("loaded!");
var loaderInfo:LoaderInfo = LoaderInfo(event.target);
picture = new BitmapData(loaderInfo.width, loaderInfo.height, false, 0xFFFFFF);
picture.draw(loaderInfo.loader);
img.source=picture;
trace(picture.height,picture.width);
}
private function createReflection():void
{
reflection=new BitmapData(picture.width,picture.height,true,0x00ffffff);
var flipMatrix:Matrix = new Matrix();
flipMatrix.rotate(Math.PI);
flipMatrix.scale( -1, 1 );
flipMatrix.translate(0, picture.height);
reflection.draw(picture, flipMatrix);
for (var i:int = 0; i < picture.height; i++)
{
var rowFactor:Number = Math.max(0, 1 - (i / picture.height));
for (var j:int = 0; j < picture.width; j++)
{
var pixelColor:uint = reflection.getPixel32(j,i);
var pixelAlpha:uint = pixelColor>>24&0xff;
var pixelRGB:uint = pixelColor&0xffffff;
var resultAlpha:uint = pixelAlpha*rowFactor;
reflection.setPixel32(j, i, resultAlpha << 24 | pixelRGB);
}
}
reflection.applyFilter(reflection, reflection.rect, new Point(0, 0), new BlurFilter(4, 4, 3));
reflectionHolder=new Bitmap(reflection);
reflectionHolder.y=img.y+img.height;
reflectionHolder.x=img.x;
reflectionHolder.width = img.width;
reflectionHolder.height = img.height;
var uIComponent:UIComponent = new UIComponent();
uIComponent.addChild(reflectionHolder);
this.addElement(uIComponent);
}
protected function btn_clickHandler(event:MouseEvent):void
{
createReflection();
}
]]>
</fx:Script>
<s:Group height="100%" width="100%">
<s:BorderContainer backgroundColor="0x0d0d0d" height="100%" width="100%"/>
<s:Image id="img" height="100" width="200" />
<s:Button id="btn" click="btn_clickHandler(event)" />
</s:Group>
</s:WindowedApplication>
it shows result but the out put was not perfect...
Objective:- Reflected object should be same as the real Object and Have Some Distance From Real Object.
It will be very much code to show in one answer. Actually, I searched my very old archives, and I found my old class for reflection (2009 year). It will create reflection for you, It supports animated objects, and also distance from object to start of reflection. With only 2 lines of code:
var test:Sprite = new Sprite();
test.graphics.beginFill(0x990099);
test.graphics.drawRect(0, 0, 100, 50);
addChild(test);
test.x = test.y = 50;
//Reflection
//test - object that will be reflected
//40 - alpha, 40%
//200 - ratio, max value 0xFF or 255, with 0xFF you will see full object in reflection
//-1 - update frame rate, for animated objects
//0 - some dropoff... actually I don't remember it, don't use it by passing zero, It affects reflection bounds
//10 - distance to the reflection in pixels...
var vars:ReflectVars = new ReflectVars(test, 40, 200, -1, 0, 10);
var reflect:Reflect = new Reflect(vars);
And a result:
if you are interested in the class, I could move it to GitHub.
flipMatrix.translate(0, picture.height);
try changing this to
flipMatrix.translate(0, picture.height + 20);
OR
reflectionHolder.y=img.y+img.height;
try changing this to
reflectionHolder.y=img.y+img.height + 20;
for adding space between reflection & real picture

How to get all the values of one column and calculate a total

I am making a program where people can create their own food schedule.
I also want to calculate the total amount of calories per food schedule.
So first off people can add items to a list which are saved in an arraycollection:
<s:List includeIn="State2" x="12" y="533" width="428" height="157" dataProvider="{acKoop}"
enabled="true" change="totalcal(event)">
<s:itemRenderer>
<fx:Component>
<mx:Label text="{data.Type} {data.Kcal}" />
</fx:Component>
</s:itemRenderer>
</s:List>
I want a function that retrieves all the values of data.Kcal and then makes a Sum of it.
public function totalcal(event:Event):void{
var price:Number=acKoop[event.columnIndex].Kcal;
total += price;
}
Here the code of link I was send, maybe will be useful:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" creationComplete="init()">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
[Bindable]
private var acKoop:ArrayCollection = null;
public function init():void{
var arr:ArrayCollection = new ArrayCollection();
var obj:Object = new Object();
obj.Type = "TYPE1";
obj.Kcal = 10;
arr.addItem(obj);
obj = new Object();
obj.Type = "TYPE2";
obj.Kcal = 50;
arr.addItem(obj);
acKoop = arr;
}
public function totalcal(event:Event):void{
var i:Number = 0;
for each(var obj:Object in ArrayCollection(List(event.currentTarget).dataProvider)){
i = i + obj.Kcal;
}
Alert.show("Total of Kcal = " + i.toString());
}
]]>
</fx:Script>
<s:List dataProvider="{acKoop}"
enabled="true" change="totalcal(event)">
<s:itemRenderer>
<fx:Component>
<mx:Label text="{data.Type} {data.Kcal}" />
</fx:Component>
</s:itemRenderer>
</s:List>
</s:Application>
Basically, on the change event I take the dataprovider information from the event, and calculate the TOTAL with the for each loop. I hope this will be useful.

how to achive the string effects like http://www.bcaa.it/

I wanna do a string effect like this website http://www.bcaa.it/
What kind of script or tutorial can I learn from?
Basically I want to achieve same as the website. Have the bouncing string effects, drag the item and move away others item that near it, drag and the sub object follow with easing...
Hey just started coding this up, need something similar for a graph display I'm working on. Here's my start, just two buttons but the idea could be extrapolated/optimized:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="windowedapplication1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
private var optimalDistanceUpdateTimer:Timer;
private var optimalDistance:Number = 100;
private var objectUserGrabbed:Button;
private var delayDenominator:Number = 6;
protected function button1_mouseDownHandler(event:MouseEvent):void
{
objectUserGrabbed = event.target as Button;
objectUserGrabbed.startDrag();
}
protected function button1_mouseUpHandler(event:MouseEvent):void
{
objectUserGrabbed.stopDrag();
}
protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
{
optimalDistanceUpdateTimer = new Timer(33);
optimalDistanceUpdateTimer.addEventListener(TimerEvent.TIMER, optimalDistanceTickedHandler);
optimalDistanceUpdateTimer.start();
}
private function optimalDistanceTickedHandler(event:TimerEvent):void
{
var targetPoint:Point;
var deltaX:Number;
var deltaY:Number;
if(!objectUserGrabbed)
return;
if(objectUserGrabbed == button1)
{
//Basically here I'm playing of Pythagorean theorem for a 45 degree triangle the x component and the y component are the distance of the hypotenuse over Sqrt(2) for different offsets, radially you'd need to adjust this to compute the target point for each object... would do something like var angleForEach:Number = 360/numObjects; then figure out the target point for each of the objects in a loop var angleForThis = angleForEach*index; (in this example only two objects, no loop needed)
targetPoint = new Point(objectUserGrabbed.x-optimalDistance/Math.SQRT2, objectUserGrabbed.y-optimalDistance/Math.SQRT2);
deltaX = (targetPoint.x-button2.x);
deltaY = (targetPoint.y-button2.y);
button2.move(button2.x+deltaX/delayDenominator, button2.y+deltaY/delayDenominator);
}
else
{
targetPoint = new Point(objectUserGrabbed.x+optimalDistance/Math.SQRT2, objectUserGrabbed.y + optimalDistance/Math.SQRT2);
deltaX = (targetPoint.x-button1.x);
deltaY = (targetPoint.y-button1.y);
button1.move(button1.x+deltaX/delayDenominator, button1.y+deltaY/delayDenominator);
}
lineDrawingArea.graphics.clear();
lineDrawingArea.graphics.lineStyle(1);
lineDrawingArea.graphics.moveTo(button1.x + button1.width/2,button1.y + button1.height/2);
lineDrawingArea.graphics.lineTo(button2.x + button2.width/2,button2.y + button2.height/2);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Group id="lineDrawingArea"/>
<s:Button id="button1" label="Item 1" mouseDown="button1_mouseDownHandler(event)" mouseUp="button1_mouseUpHandler(event)" x="0" y="0"/>
<s:Button id="button2" label="Item 2" mouseDown="button1_mouseDownHandler(event)" mouseUp="button1_mouseUpHandler(event)" x="0" y="0"/>
</s:WindowedApplication>

Flex 3: inquiry about printing

I have created a scheduling application that spans upwards of 16 weeks. I would like to be able to print the schedule using Flex. I've created a test application that lists incrementing dates. These dates obviously stretch longer than the width of my computer. I would like for my print function to print the entire width of dates across several pages... currently, it prints just what appears on my screen. Is there a way to accomplish this?
Below is the app i've created. There are some calls to custom functions, but they in no way relate to the issue at hand:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init();">
<mx:Script source="functions/dateFunctions.as" />
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.collections.ArrayCollection;
[Bindable] public var date:Date = new Date;
public var numDays:Number = 50;
[Bindable] public var datesAC:ArrayCollection = new ArrayCollection;
public function init():void
{
var tempDate:String = new String;
for (var i:int = 0; i < numDays; i++)
{
tempDate = dateToNumText(rightDate(date.getMonth(), date.getDate() + i, date.getFullYear()));
datesAC.addItem(tempDate);
}
}
private function printMe() :void
{
var pj:PrintJob = new PrintJob();
pj.start();
// setTimeout(function() :void { finishPrinting(pj);}, 1);
finishPrinting(pj);
}
private function finishPrinting(pj:PrintJob): void {
pj.addPage(this);
pj.send();
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%">
<mx:Button id="print" label="Start Print" click="printMe()" />
<mx:HorizontalList id="dateList" dataProvider="{datesAC}" width="100%" height="100%" useRollOver="false">
<mx:itemRenderer>
<mx:Component>
<mx:Canvas borderColor="#000000" borderSides="right" borderStyle="solid">
<mx:Text text="{data}" textAlign="center" color="#000000" width="100" />
</mx:Canvas>
</mx:Component>
</mx:itemRenderer>
</mx:HorizontalList>
</mx:VBox>
</mx:Application>
You would have to break up/paginate content on your own. You can send each such logically broken up page to PrintJob.appPage() API so it becomes a printed paper. At present, what is happening would be that content would be getting clipped.
I guess you should use PrintJob.addPage() to add your dates to print job.

Adobe Flex creating polygon

How to create a polygon in Adobe flex 3.0
You draw a bunch of lines connecting the points of the polygon.
As a quick example:
function drawPolygon(first, ... rest) {
graphics.moveTo(first.x, first.y);
for(var i = 0; i < rest.length; i++) {
graphics.lineTo(rest[i].x, rest[i].y);
}
graphics.lineTo(first.x, first.y);
}
May be some minor syntax errors, but you get the idea. You'd call it by passing a bunch of Point objects indicating the points of the polygon.
Try this sample
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:esri="http://www.esri.com/2008/ags">
<fx:Script>
<![CDATA[
import com.esri.ags.Graphic;
import com.esri.ags.SpatialReference;
import com.esri.ags.Units;
import com.esri.ags.geometry.Geometry;
import com.esri.ags.geometry.MapPoint;
import com.esri.ags.geometry.Polygon;
import com.esri.ags.geometry.Polyline;
import com.esri.ags.utils.GeometryUtil;
import mx.utils.StringUtil;
private const sr:SpatialReference = new SpatialReference(4326);
protected function onCreatePolyline(event:MouseEvent):void
{
addMessage("Create polyline clicked");
var pts:Array = new Array();
for (var i:int; i < 10; i++) // add 10 random points to path
{
var pt:MapPoint = new MapPoint(Math.random()*10000, Math.random()*10000, sr);
pts.push(pt);
}
var pl:Polyline = new Polyline(new Array(pts), sr);
var lengths:Array = GeometryUtil.geodesicLengths(new Array(pl), Units.KILOMETERS);
if (lengths != null && lengths.length > 0)
{
addMessage(StringUtil.substitute("polyline created with length {0} km", lengths[0]));
}
addGraphic(pl);
}
protected function onCreatePolygon(event:MouseEvent):void
{
addMessage("Create polygon clicked");
var pts:Array = new Array();
for (var i:int; i < 10; i++) // add 10 random points to ring
{
var pt:MapPoint = new MapPoint(Math.random()*10000, Math.random()*10000, sr);
pts.push(pt);
}
var pg:Polygon = new Polygon(new Array(pts), sr);
var areas:Array = GeometryUtil.geodesicAreas(new Array(pg), Units.SQUARE_KILOMETERS);
if (areas != null && areas.length > 0)
{
addMessage(StringUtil.substitute("polygon created with area {0} kmĀ²", Math.abs(areas[0])));
}
addGraphic(pg);
}
private function addMessage(message:String):void
{
log.text = StringUtil.substitute("> > > {0}\n{1}", message, log.text);
}
private function addGraphic(geometry:Geometry):void
{
var gr:Graphic = new Graphic(geometry);
grLayer.clear();
var grId:String = grLayer.add(gr);
addMessage(StringUtil.substitute("graphic added with id='{0}'", grId));
map.initialExtent = geometry.extent;
map.zoomToInitialExtent();
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout gap="10"
paddingBottom="10"
paddingLeft="10"
paddingRight="10"
paddingTop="10"/>
</s:layout>
<s:Button label="Create polyline"
click="onCreatePolyline(event)"/>
<s:Button label="Create polygon"
click="onCreatePolygon(event)"/>
<s:TextArea id="log"
width="100%"
height="100%"/>
<esri:Map id="map"
zoomSliderVisible="false"
minHeight="200"
width="100%">
<esri:GraphicsLayer id="grLayer" />
</esri:Map>
</s:Application>