Reputation: 23038
I have a pure ActionScript 3 problem, but the simplified test case I've prepared is in Flex 4 for better visibility (the source code is below):
Since Flash Player 11 / AIR 3 support JSON natively, I've decided to move a multiplayer game, which used XML for communicating with server, to JSON.
But I have a frustrating problem, that given two Objects like
{ 9013: [
"OK305894249541",
"OK151358069597",
"OK515549948434",
] },
{ 8991: [
"OK253525117889",
"OK529081480134",
] },
I don't know how to create an ActionScript function, which would report 3 for the first Object and 2 for the second Object?
The "9013" and "8991" in the example above are game numbers.
The "OKxxxx" strings represent players.
A game is "full" when it holds 3 players, "vacant" otherwise.
Here is my very simple TestCase.mxml:
<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="init(event)">
<fx:Declarations>
<s:RadioButtonGroup id="_filter" change="handleRadio(event);" />
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
[Bindable]
private var _games:ArrayCollection = new ArrayCollection();
[Bindable]
private var _all:uint = 0;
[Bindable]
private var _vac:uint = 0;
[Bindable]
private var _full:uint = 0;
private function vacantGame(obj:Object):Boolean {
// XXX how to implement?
// XXX return true if obj has less than 3 players
return true;
}
private function fullGame(item:Object):Boolean {
// XXX how to implement?
// XXX return true if obj has exactly 3 players
return true;
}
private function init(event:FlexEvent):void {
var i:uint;
_games.source = OBJ['games'];
_all = _games.length;
_vac = 0;
for (i = 0; i < _games.length; i++)
if (vacantGame(_games[i]))
_vac++;
_full = 0;
for (i = 0; i < _games.length; i++)
if (fullGame(_games[i]))
_full++;
}
private function handleRadio(event:Event):void {
switch (_filter.selection) {
case _allBtn:
_games.filterFunction = null;
break;
case _vacBtn:
_games.filterFunction = vacantGame;
break;
case _fullBtn:
_games.filterFunction = fullGame;
break;
}
_games.refresh();
}
private const OBJ:Object = {
lobby: [
"OK108900197210",
"OK266559712237",
"DE6577",
"DE7981",
"OK225312168135",
"OK20629248715",
"DE7880",
],
games: [
{ 0: [] },
{ 9012: [
"VK48058967",
"MR14315189992643135976",
"OK10218913103",
] },
{ 9013: [
"OK305894249541",
"OK151358069597",
"OK515549948434",
] },
{ 8991: [
"OK253525117889",
"OK529081480134",
] },
{ 8937: [
"OK304672497140",
"VK90145027",
"OK338360548262",
] },
{ 9005: [
"OK40798070412",
"DE7979",
"OK531589632132",
] },
{ 9010: [
"OK357833936215",
] },
]
};
]]>
</fx:Script>
<s:HGroup verticalAlign="baseline">
<s:Label text="Games:" />
<s:RadioButton id="_allBtn" group="{_filter}" label="All: {_all}" selected="true" />
<s:RadioButton id="_vacBtn" group="{_filter}" label="Vacant: {_vac}" />
<s:RadioButton id="_fullBtn" group="{_filter}" label="Full: {_full}" />
</s:HGroup>
</s:Application>
Upvotes: 0
Views: 1078
Reputation: 4583
The right answer is to rethink your data structure. Drop the surrounding array, all games have a unique ID anyway.
But if you insist on using it as above, you can do the following:
private function vacantGame(obj:Object):Boolean{
for( var gameNumber : String in obj ){
var players : Array = obj[ gameNumber ]
return players.length < 3
}
return false;
}
The better way:
games: {
0: [],
9012: [
"VK48058967",
"MR14315189992643135976",
"OK10218913103",
],
9013: [
"OK305894249541",
"OK151358069597",
"OK515549948434",
],
...
}
then
for( var gameNumber : String in OBJ.games ){
var players : Array = OBJ.games[ gameNumber ];
if( players.length < 3 ){
//vacant
}else{
//full
}
}
Upvotes: 1