randomizing questions via XML
Copy link to clipboard
Copied
I have an application which pulls in data (questions) via XML and randomizes them. Right now if there is 50 questions in the XML file, 50 questions are displayed and randomized in the application. I am trying to figure out how to limit the randomizing pool so that only 35 questions display or something like that. My current code which brings in the file and randomizes is below.
package exam {
import flash.net.* //to create URLRequest and load XML file
import flash.events.* //for Load events
//import flash.display.* //for testing purposes - remove when testing complete
//This class downloads the XML document, and then inserts info into arrays and variables.
//Also provides text of questions and correct answers when requested.
internal class XaMLDiplomat extends EventDispatcher {
//VARIABLES:
//for loaded XML doc
private var myXML:XML;
//for loading in XML
private var examLoader:URLLoader;
private var numQstns:Number; //count of total questions in a section
private var sectStart:Number;
//contains exam questions - ALL ARRAYS ARE ZERO RELATIVE -> actual question numbers = array index + 1
private var questions:Array;
//contain associated answer choices
private var choiceA:Array;
private var choiceB:Array;
private var choiceC:Array;
private var choiceD:Array;
private var choiceE:Array;
private var choiceF:Array;
//array of the correct answers
private var answers:Array;
//use custom Mixer class to randomize order
private var myMixer:Mixer;
//CONSTRUCTOR
public function XaMLDiplomat () { //NEED TO ADD ARGUMENTS (docLocation)
//create URLRequest from argument
var examSite:URLRequest = new URLRequest("protected/Questions.xml");
//create a loader for the XML
examLoader = new URLLoader();
//add listener for load completion
examLoader.addEventListener(Event.COMPLETE, fullyLoaded);
examLoader.load(examSite);
//var ugly:Mixer = new Mixer(25);
}
//Load listener - creates XML object, and checks it for multiple sections. If multiple, it asks users
//which section they want - FIRST it needs to check database for any completed sections.
//If single, it goes ahead and starts array creation for first (& only) section
private function fullyLoaded (e:Event):void {
myXML = new XML(examLoader.data);
//myXML.prettyPrinting = false;
//still need to pull out SYSTEM data and pass it along...
var system:XMLList = myXML..SYSTEM;
var sysObj:Object = new Object();
sysObj.examTitle = system.TITLE.toString();
sysObj.totalMin = system.MINUTES.toString();
sysObj.retakePW = system.RETAKEPW.toString();
var numSections:Number = myXML..SECTION.length();
if (numSections == 1) {
generateArrays(1);
}
dispatchEvent(new MultiSectEvent(MultiSectEvent.SECTIONS, numSections, sysObj));
}
//Assigns arrays to instance variables for the selected section
internal function generateArrays (sectn:Number):void {
var whichSection:XMLList = myXML..SECTION.(@id == String(sectn));
var probList:XMLList = whichSection.PROBLEM;
numQstns = probList.length();
sectStart = Number(probList[0].@id);
questions = new Array();
choiceA = new Array();
choiceB = new Array();
choiceC = new Array();
choiceD = new Array();
choiceE = new Array();
choiceF = new Array();
answers = new Array();
for (var i:Number=0; i<numQstns; i++) {
var curProb:XMLList = probList.(@id == String(i+1));
if (curProb.QUESTION.hasSimpleContent()) {
questions = curProb.QUESTION.toString();
}else {
//trace(curProb.QUESTION.toXMLString());
questions = dropTags(curProb.QUESTION[0]);
}
choiceA = curProb.CHOICE.(@letter == "a").toString();
choiceB = curProb.CHOICE.(@letter == "b").toString();
choiceC = curProb.CHOICE.(@letter == "c").toString();
choiceD = curProb.CHOICE.(@letter == "d").toString();
choiceE = curProb.CHOICE.(@letter == "e").toString();
choiceF = curProb.CHOICE.(@letter == "f").toString();
answers = curProb.CHOICE.(hasOwnProperty("@correct") && @correct == "true").@letter.toString();
}
myMixer = new Mixer(numQstns);//mixer commented out
/*
trace("Question: "+questions[3]);
trace("a: "+choiceA[3]);
trace("b: "+choiceB[3]);
trace("c: "+choiceC[3]);
trace("d: "+choiceD[3]);
trace("\r\n answer: "+answers[3]); */
}
//method for external classes to acquire text of current exam question
internal function getQuestion (qnum:Number):Object {
var returnObj:Object = new Object();
var randomQ:Number = myMixer.getRandomNumber(qnum-1);
returnObj.q = questions[randomQ];
returnObj.ca = choiceA[randomQ];
returnObj.cb = choiceB[randomQ];
returnObj.cc = choiceC[randomQ];
returnObj.cd = choiceD[randomQ];
returnObj.ce = choiceE[randomQ];
returnObj.cf = choiceF[randomQ];
returnObj.num = qnum;
//trace(randomQ);
return returnObj;
}
private function dropTags (txt:XML):String {
var txtString:String = "";
for each (var child:XML in txt.*) {
if (child.nodeKind == "text") {
txtString += child.toString();
}else {
txtString += " " + child.toXMLString();
}
}
//trace(txtString);
return txtString;
}
/*
private function dropTags (txt:String):String {
var sliceStart:Number = txt.indexOf(">");
var sliceStop:Number = txt.lastIndexOf("<");
return txt.slice((sliceStart+1), sliceStop);
}*/
internal function getAnswer (num:Number):String {
return answers[num];
}
internal function getQCount ():Number {
return numQstns;
}
internal function getSectStart():Number {
return sectStart;
}
internal function getRealNum (num:Number):Number {
return myMixer.getRandomNumber(num-1);
}
}
}
Copy link to clipboard
Copied
call getQuestion() 35 times.
Copy link to clipboard
Copied
would it be here?
internal function getQCount (35):Number {
return numQstns;
}
Copy link to clipboard
Copied
no. it would be the bold function below:
package exam { import flash.net.* //to create URLRequest and load XML file
import flash.events.* //for Load events
//import flash.display.* //for testing purposes - remove when testing complete
//This class downloads the XML document, and then inserts info into arrays and variables.
//Also provides text of questions and correct answers when requested.
internal class XaMLDiplomat extends EventDispatcher {
//VARIABLES:
//for loaded XML doc
private var myXML:XML;
//for loading in XML
private var examLoader:URLLoader;
private var numQstns:Number; //count of total questions in a section
private var sectStart:Number;
//contains exam questions - ALL ARRAYS ARE ZERO RELATIVE -> actual question numbers = array index + 1
private var questions:Array;
//contain associated answer choices
private var choiceA:Array;
private var choiceB:Array;
private var choiceC:Array;
private var choiceD:Array;
private var choiceE:Array;
private var choiceF:Array;
//array of the correct answers
private var answers:Array;
//use custom Mixer class to randomize order
private var myMixer:Mixer;
//CONSTRUCTOR
public function XaMLDiplomat () { //NEED TO ADD ARGUMENTS (docLocation)
//create URLRequest from argument
var examSite:URLRequest = new URLRequest("protected/Questions.xml");
//create a loader for the XML
examLoader = new URLLoader();
//add listener for load completion
examLoader.addEventListener(Event.COMPLETE, fullyLoaded);
examLoader.load(examSite);
//var ugly:Mixer = new Mixer(25);
}
//Load listener - creates XML object, and checks it for multiple sections. If multiple, it asks users
//which section they want - FIRST it needs to check database for any completed sections.
//If single, it goes ahead and starts array creation for first (& only) section
private function fullyLoaded (e:Event):void {
myXML = new XML(examLoader.data);
//myXML.prettyPrinting = false;
//still need to pull out SYSTEM data and pass it along...
var system:XMLList = myXML..SYSTEM;
var sysObj:Object = new Object();
sysObj.examTitle = system.TITLE.toString();
sysObj.totalMin = system.MINUTES.toString();
sysObj.retakePW = system.RETAKEPW.toString();
var numSections:Number = myXML..SECTION.length();
if (numSections == 1) {
generateArrays(1);
}
dispatchEvent(new MultiSectEvent(MultiSectEvent.SECTIONS, numSections, sysObj));
}
//Assigns arrays to instance variables for the selected section
internal function generateArrays (sectn:Number):void {
var whichSection:XMLList = myXML..SECTION.(@id == String(sectn));
var probList:XMLList = whichSection.PROBLEM;
numQstns = probList.length();
sectStart = Number(probList[0].@id);
questions = new Array();
choiceA = new Array();
choiceB = new Array();
choiceC = new Array();
choiceD = new Array();
choiceE = new Array();
choiceF = new Array();
answers = new Array();
for (var i:Number=0; i<numQstns; i++) {
var curProb:XMLList = probList.(@id == String(i+1));
if (curProb.QUESTION.hasSimpleContent()) {
questions = curProb.QUESTION.toString();
}else {
//trace(curProb.QUESTION.toXMLString());
questions = dropTags(curProb.QUESTION[0]);
}
choiceA = curProb.CHOICE.(@letter == "a").toString();
choiceB = curProb.CHOICE.(@letter == "b").toString();
choiceC = curProb.CHOICE.(@letter == "c").toString();
choiceD = curProb.CHOICE.(@letter == "d").toString();
choiceE = curProb.CHOICE.(@letter == "e").toString();
choiceF = curProb.CHOICE.(@letter == "f").toString();
answers = curProb.CHOICE.(hasOwnProperty("@correct") && @correct == "true").@letter.toString();
}
myMixer = new Mixer(numQstns);//mixer commented out
/*
trace("Question: "+questions[3]);
trace("a: "+choiceA[3]);
trace("b: "+choiceB[3]);
trace("c: "+choiceC[3]);
trace("d: "+choiceD[3]);
trace("\r\n answer: "+answers[3]); */
}
//method for external classes to acquire text of current exam question
internal function getQuestion (qnum:Number):Object {
var returnObj:Object = new Object();
var randomQ:Number = myMixer.getRandomNumber(qnum-1);
returnObj.q = questions[randomQ];
returnObj.ca = choiceA[randomQ];
returnObj.cb = choiceB[randomQ];
returnObj.cc = choiceC[randomQ];
returnObj.cd = choiceD[randomQ];
returnObj.ce = choiceE[randomQ];
returnObj.cf = choiceF[randomQ];
returnObj.num = qnum;
//trace(randomQ);
return returnObj;
}
private function dropTags (txt:XML):String {
var txtString:String = "";
for each (var child:XML in txt.*) {
if (child.nodeKind == "text") {
txtString += child.toString();
}else {
txtString += " " + child.toXMLString();
}
}
//trace(txtString);
return txtString;
}
/*
private function dropTags (txt:String):String {
var sliceStart:Number = txt.indexOf(">");
var sliceStop:Number = txt.lastIndexOf("<");
return txt.slice((sliceStart+1), sliceStop);
}*/
internal function getAnswer (num:Number):String {
return answers[num];
}
internal function getQCount ():Number {
return numQstns;
}
internal function getSectStart():Number {
return sectStart;
}
internal function getRealNum (num:Number):Number {
return myMixer.getRandomNumber(num-1);
}
}
}
Copy link to clipboard
Copied
would I just need to add this to that function?
[as]
call getQuestion(35);
[/as]
Copy link to clipboard
Copied
you wouldn't add that code to the function. you would add that code where you need to retrieve a question. (thought it's not clear
myMixer.getRandomNumber() is randomizing without repeats.)
Copy link to clipboard
Copied
I don't want any repeats, just to randomly pick a number of questions out of the XML, so if there are fifty questions in the XML, display 35, but a different 35 each time(random). Would I still use Call?
is this where I need to change?
var randomQ:Number = myMixer.getRandomNumber(qnum-1);
Copy link to clipboard
Copied
i don't know if it's randomizing without repeats or not. that part of the code isn't shown.
but, i suspect it's not. to randomize without repeats the questions array should be randomized or "shuffled". i've posted a shuffle function numerous times in these forums over the years.
Copy link to clipboard
Copied
your right, the mixer code was in a different package. Here is that code.
package exam {
//This is a very simple object that creates the random order in which exam questions are presented
internal class Mixer {
//retains the array that is consulted for random question numbers
private var randomizedOrder:Array;
//CONSTRUCTOR - passed total number of questions in section
public function Mixer (questnsTotal:Number) {
randomizedOrder = new Array();
randomizedOrder[0] = Math.floor(Math.random()*questnsTotal);
for (var i:Number=1; i<questnsTotal; i++) {
randomizedOrder = newNumber(questnsTotal, i);
}
/*
for (var k:Number=0; k<questnsTotal; k++) {
trace(""+k+": "+randomizedOrder
}*/
}
//recursive function that creates a new number until it creates one that isn't already in use
private function newNumber (qTotal:Number, curNum:Number):Number {
var newNum:Number = Math.floor(Math.random()*qTotal);
for (var j:Number=0; j<curNum; j++) {
if (randomizedOrder
return newNumber(qTotal, curNum);
}
}
return newNum;
}
//This is how external classes acquire a random number from this class's array
//(programNum = the question the program wants to ask next, based on sequential order, or user selection)
internal function getRandomNumber(programNum:Number):Number {
return randomizedOrder[programNum];
}
}
}
Copy link to clipboard
Copied
that's poor coding but it's close to randomizing the questions without repeats IF it were called once. but it's called repeatedly which isn't correct.
actually, the whole setup is a mess but you can continue to work with that using:
package exam {import flash.net.* //to create URLRequest and load XML file
import flash.events.* //for Load events
//import flash.display.* //for testing purposes - remove when testing complete
//This class downloads the XML document, and then inserts info into arrays and variables.
//Also provides text of questions and correct answers when requested.
internal class XaMLDiplomat extends EventDispatcher {
//VARIABLES:
//for loaded XML doc
private var myXML:XML;
//for loading in XML
private var examLoader:URLLoader;
private var numQstns:Number; //count of total questions in a section
private var sectStart:Number;
//contains exam questions - ALL ARRAYS ARE ZERO RELATIVE -> actual question numbers = array index + 1
private var questions:Array;
//contain associated answer choices
private var choiceA:Array;
private var choiceB:Array;
private var choiceC:Array;
private var choiceD:Array;
private var choiceE:Array;
private var choiceF:Array;
//array of the correct answers
private var answers:Array;
private var questionNum:Array=[];
//CONSTRUCTOR
public function XaMLDiplomat () { //NEED TO ADD ARGUMENTS (docLocation)
//create URLRequest from argument
var examSite:URLRequest = new URLRequest("protected/Questions.xml");
//create a loader for the XML
examLoader = new URLLoader();
//add listener for load completion
examLoader.addEventListener(Event.COMPLETE, fullyLoaded);
examLoader.load(examSite);
//var ugly:Mixer = new Mixer(25);
}
//Load listener - creates XML object, and checks it for multiple sections. If multiple, it asks users
//which section they want - FIRST it needs to check database for any completed sections.
//If single, it goes ahead and starts array creation for first (& only) section
private function fullyLoaded (e:Event):void {
myXML = new XML(examLoader.data);
//myXML.prettyPrinting = false;
//still need to pull out SYSTEM data and pass it along...
var system:XMLList = myXML..SYSTEM;
var sysObj:Object = new Object();
sysObj.examTitle = system.TITLE.toString();
sysObj.totalMin = system.MINUTES.toString();
sysObj.retakePW = system.RETAKEPW.toString();
var numSections:Number = myXML..SECTION.length();
if (numSections == 1) {
generateArrays(1);
}
dispatchEvent(new MultiSectEvent(MultiSectEvent.SECTIONS, numSections, sysObj));
}
//Assigns arrays to instance variables for the selected section
internal function generateArrays (sectn:Number):void {
var whichSection:XMLList = myXML..SECTION.(@id == String(sectn));
var probList:XMLList = whichSection.PROBLEM;
numQstns = probList.length();
sectStart = Number(probList[0].@id);
questions = new Array();
choiceA = new Array();
choiceB = new Array();
choiceC = new Array();
choiceD = new Array();
choiceE = new Array();
choiceF = new Array();
answers = new Array();
for (var i:Number=0; i<numQstns; i++) {
var curProb:XMLList = probList.(@id == String(i+1));
if (curProb.QUESTION.hasSimpleContent()) {
questions = curProb.QUESTION.toString();
}else {
//trace(curProb.QUESTION.toXMLString());
questions = dropTags(curProb.QUESTION[0]);
}questionNum.push(i);
choiceA = curProb.CHOICE.(@letter == "a").toString();
choiceB = curProb.CHOICE.(@letter == "b").toString();
choiceC = curProb.CHOICE.(@letter == "c").toString();
choiceD = curProb.CHOICE.(@letter == "d").toString();
choiceE = curProb.CHOICE.(@letter == "e").toString();
choiceF = curProb.CHOICE.(@letter == "f").toString();
answers = curProb.CHOICE.(hasOwnProperty("@correct") && @correct == "true").@letter.toString();
}questionNum=shuffle(questionNum)
}
//method for external classes to acquire text of current exam question
internal function getQuestion (qnum:Number):Object {
var returnObj:Object = new Object();
var randomQ:Number = questionNum(qnum);
returnObj.q = questions[randomQ];
returnObj.ca = choiceA[randomQ];
returnObj.cb = choiceB[randomQ];
returnObj.cc = choiceC[randomQ];
returnObj.cd = choiceD[randomQ];
returnObj.ce = choiceE[randomQ];
returnObj.cf = choiceF[randomQ];
returnObj.num = qnum;
//trace(randomQ);
return returnObj;
}
private function shuffle(a:Array) {
var p:int;
var t:*;
var ivar:int;
for (ivar = a.length-1; ivar>=0; ivar--) {
p=Math.floor((ivar+1)*Math.random());
t = a[ivar];
a[ivar] = a;
a= t;
}
}
private function dropTags (txt:XML):String {
var txtString:String = "";
for each (var child:XML in txt.*) {
if (child.nodeKind == "text") {
txtString += child.toString();
}else {
txtString += " " + child.toXMLString();
}
}
//trace(txtString);
return txtString;
}
/*
private function dropTags (txt:String):String {
var sliceStart:Number = txt.indexOf(">");
var sliceStop:Number = txt.lastIndexOf("<");
return txt.slice((sliceStart+1), sliceStop);
}*/
internal function getAnswer (num:Number):String {
return answers[num];
}
internal function getQCount ():Number {
return numQstns;
}
internal function getSectStart():Number {
return sectStart;
}
internal function getRealNum (num:Number):Number {
return myMixer.getRandomNumber(num-1);
}
}
}
Copy link to clipboard
Copied
thanks, I will try ot out, and yes, the current code is a mess. So with the code you provided, do I still need to add the call to limit the display?
Copy link to clipboard
Copied
you just call getQuestion() and pass the current question number (starting with 0,...,34) each time you want to retrieve a new question, choices and correct answer.
Copy link to clipboard
Copied
other than what I have posted , this package brings in the question and answer display.
package exam {
import flash.display.*;
import flash.events.*;
import flash.text.*;
//This class displays the current question, and contains the Choices for the question
public class QMachine extends Sprite {
//VARIABLES
private var QObject:Object; //object from XaMLDiplomat, containing necessary text
private var limit:Number;
private var QNumTxt:TextField;
private var QTxt:TextField;
private var sub:TextField;
private var txtStyle:StyleSheet;
private var choiceA:Choice;
private var choiceB:Choice;
private var choiceC:Choice;
private var choiceD:Choice;
private var choiceE:Choice;
private var choiceF:Choice;
//CONSTRUCTOR
public function QMachine (hite:Number) {
limit = hite;
var style:Object = new Object();
style.fontFamily = "Arial";
//style.fontWeight = "bold";
style.fontSize = "16";
style.color = "#333333";
txtStyle = new StyleSheet();
txtStyle.setStyle("p",style);
QNumTxt = new TextField();
QNumTxt.styleSheet = txtStyle;
//QNumTxt.embedFonts = true;
QNumTxt.htmlText = "<p>1) </p>";
QNumTxt.autoSize = TextFieldAutoSize.RIGHT;
QNumTxt.x = 10;
QNumTxt.mouseEnabled = false;
QTxt = new TextField();
QTxt.styleSheet = txtStyle;
//QTxt.embedFonts = true;
QTxt.width = 300;
QTxt.multiline = true;
QTxt.wordWrap = true;
QTxt.autoSize = TextFieldAutoSize.LEFT;
QTxt.htmlText = "<p>Question 1</p>";
QTxt.x = 35;
QTxt.mouseEnabled = false;
addChild(QNumTxt);
addChild(QTxt);
choiceA = new Choice("a");
choiceA.x = 350;
addChild(choiceA);
choiceB = new Choice("b");
choiceB.x = 350;
addChild(choiceB);
choiceC = new Choice("c");
choiceC.x = 350;
addChild(choiceC);
choiceD = new Choice("d");
choiceD.x = 350;
addChild(choiceD);
choiceE = new Choice("e");
choiceE.x = 350;
addChild(choiceE);
choiceF = new Choice("f");
choiceF.x = 350;
addChild(choiceF);
addEventListener(MouseEvent.MOUSE_UP, selectResponse, true);
}
internal function newQuestion (obj:Object, prior:String = ""):void {
//trace(obj.num);
QNumTxt.htmlText = "<p>"+ obj.num + ".</p>";
QTxt.htmlText = "<p>"+ obj.q + "</p>";
choiceA.deselect();
choiceB.deselect();
choiceC.deselect();
choiceD.deselect();
choiceE.deselect();
choiceF.deselect();
choiceA.resetSize();
choiceB.resetSize();
choiceC.resetSize();
choiceD.resetSize();
choiceE.resetSize();
choiceF.resetSize();
choiceA.changeTxt(obj.ca);
choiceB.changeTxt(obj.cb);
choiceB.y = choiceA.height + 5;
if (obj.cc == undefined || String(obj.cc) == "") {
choiceC.visible = false;
}else {
choiceC.changeTxt(obj.cc);
choiceC.y = choiceB.y + choiceB.height + 5;
choiceC.visible = true;
}
if (obj.cd == undefined || String(obj.cd) == "") {
choiceD.visible = false;
}else {
choiceD.changeTxt(obj.cd);
choiceD.y = choiceC.y + choiceC.height + 5;
choiceD.visible = true;
}
if (obj.ce == undefined || String(obj.ce) == "") {
choiceE.visible = false;
}else {
choiceE.changeTxt(obj.ce);
choiceE.y = choiceD.y + choiceD.height + 5;
choiceE.visible = true;
}
if (obj.cf == undefined || String(obj.cf) == "") {
choiceF.visible = false;
}else {
choiceF.changeTxt(obj.cf);
choiceF.y = choiceE.y + choiceE.height + 5;
choiceF.visible = true;
}
var curHite:Number;
if (choiceF.visible) {
curHite = choiceF.y + choiceF.height + 5;
}else if (choiceE.visible) {
curHite = choiceE.y + choiceE.height + 5;
}else if (choiceD.visible) {
curHite = choiceD.y + choiceD.height + 5;
}else {
curHite = choiceC.y + choiceC.height + 5;
}
if (curHite > (limit-150)) {
shrinkText();
}
if (prior != "") {
if (prior == "a") {
choiceA.nowSelected();
}else if (prior == "b") {
choiceB.nowSelected();
}else if (prior == "c") {
choiceC.nowSelected();
}else if (prior == "d") {
choiceD.nowSelected();
}else if (prior == "e") {
choiceE.nowSelected();
}else if (prior == "f") {
choiceF.nowSelected();
}
}
}
private function shrinkText() {
choiceA.dropSize();
choiceB.dropSize();
choiceC.dropSize();
choiceD.dropSize();
choiceE.dropSize();
choiceF.dropSize();
choiceB.y = choiceA.y + choiceA.height + 5;
choiceC.y = choiceB.y + choiceB.height + 5;
choiceD.y = choiceC.y + choiceC.height + 5;
choiceE.y = choiceD.y + choiceD.height + 5;
choiceF.y = choiceE.y + choiceE.height + 5;
var curHite:Number = 0;
if (choiceF.visible) {
curHite = choiceF.y + choiceF.height + 5;
}else if (choiceE.visible) {
curHite = choiceE.y + choiceE.height + 5;
}else if (choiceD.visible) {
curHite = choiceD.y + choiceD.height + 5;
}else {
curHite = choiceC.y + choiceC.height + 5;
}
if (curHite > (limit-150)) {
shrinkText();
}
}
private function selectResponse (e:MouseEvent):void {
choiceA.deselect();
choiceB.deselect();
choiceC.deselect();
choiceD.deselect();
choiceE.deselect();
choiceF.deselect();
var letter:String = e.target.parent.getLetter();
dispatchEvent(new ResponseEvent(ResponseEvent.SELECTION, letter));
}
internal function setPriorResponse() {
choiceA.deselect();
choiceB.deselect();
choiceC.deselect();
choiceD.deselect();
choiceE.deselect();
choiceF.deselect();
}
}
}
is it within I need to call getQuestion()? Or within the package that displays the XML data?
Copy link to clipboard
Copied
that's beyond my limit of lines of code to go through trying to figure out what you're doing. you should be able to focus my attention on a handful of lines and direct a question about those lines.
Copy link to clipboard
Copied
well this code is mostly formatting, hilighting and selecting text, I know that. I don't think this is where I need to place the code you mentioned, but still confused as to where that would be. This line is pulling in the text.
private var QObject:Object; //object from XaMLDiplomat, containing necessary text
and this part is choosing the questions to display.
internal function newQuestion (obj:Object, prior:String = ""):void {
//trace(obj.num);
QNumTxt.htmlText = "<p>"+ obj.num + ".</p>";
QTxt.htmlText = "<p>"+ obj.q + "</p>";
Copy link to clipboard
Copied
there's some place where you decide it's time to present the first question and the choices. then you evaluate the answer given by a user and sometime after that you present the next question. when you want to present a question, you call getQuestion(). that returns the question and choices and correct answer. where are you using all that?
Copy link to clipboard
Copied
isn't that being done here?
//method for external classes to acquire text of current exam question
internal function getQuestion (qnum:Number):Object {
var returnObj:Object = new Object();
var randomQ:Number = questionNum(qnum);
returnObj.q = questions[randomQ];
returnObj.ca = choiceA[randomQ];
returnObj.cb = choiceB[randomQ];
returnObj.cc = choiceC[randomQ];
returnObj.cd = choiceD[randomQ];
returnObj.ce = choiceE[randomQ];
returnObj.cf = choiceF[randomQ];
returnObj.num = qnum;
//trace(randomQ);
return returnObj;
}
Copy link to clipboard
Copied
no.
it appears you don't understand that application, at all. you'll need someone to download your file and make the changes you need.
Copy link to clipboard
Copied
then it's right here. This is where the first question is being pulled in.
currentQ = 1;
checkForDisable();
myQMachine = new QMachine(mySkipper.y);
myQMachine.newQuestion(myDiplomat.getQuestion(1));
myQMachine.x = 11;
myQMachine.y = 150;
Copy link to clipboard
Copied
myDiplomat is a class instance (of some class). that class has a getQuestion() method. presumably that's related to the getQuestion() method we've been discussing but it's not clear it's related, at all. you'll have to check that class' method to see.
Copy link to clipboard
Copied
the method for accessing the exam and beggining the process
if bringing in questions is here:
private function accessExam (e:UserEvent) {
if(e.userID != 0 && e.logID != 0) {
//put code here to have ResultsHandler pull from Shared Obj and send
myRecords = new ResultsHandler(e.userID, e.logID);
myRecords.findAndSend(e.userID, e.logID);
}else {
login.removeEventListener(UserEvent.LOGIN, accessExam);
removeChild(login);
removeChild(curtain);
myDiplomat = new XaMLDiplomat();
//must wait for XML to load and parse, then can create Mixer
myDiplomat.addEventListener(MultiSectEvent.SECTIONS, sectionListener);
Copy link to clipboard
Copied
Hi, I am still trying to get this working. Right now with the code I have, I am getting an error "1061: Call to a possibly undefined method questionNum through a reference with static type Function.".
the error is occurring here.
internal function getRealNum (num:Number):Number {
return shuffle.questionNum(num-1);
}
can anyone explain this error to me?
My full code is here:
package exam {
import flash.net.* //to create URLRequest and load XML file
import flash.events.* //for Load events
//import flash.display.* //for testing purposes - remove when testing complete
//This class downloads the XML document, and then inserts info into arrays and variables.
//Also provides text of questions and correct answers when requested.
internal class XaMLDiplomat extends EventDispatcher {
//VARIABLES:
//for loaded XML doc
private var myXML:XML;
//for loading in XML
private var examLoader:URLLoader;
private var numQstns:Number; //count of total questions in a section
private var sectStart:Number;
//contains exam questions - ALL ARRAYS ARE ZERO RELATIVE -> actual question numbers = array index + 1
private var questions:Array;
//contain associated answer choices
private var choiceA:Array;
private var choiceB:Array;
private var choiceC:Array;
private var choiceD:Array;
private var choiceE:Array;
private var choiceF:Array;
//array of the correct answers
private var answers:Array;
private var questionNum:Array=[];
//use custom Mixer class to randomize order
//private var myMixer:Mixer;
//CONSTRUCTOR
public function XaMLDiplomat () { //NEED TO ADD ARGUMENTS (docLocation)
//create URLRequest from argument
var examSite:URLRequest = new URLRequest("protected/exam.xml");
//create a loader for the XML
examLoader = new URLLoader();
//add listener for load completion
examLoader.addEventListener(Event.COMPLETE, fullyLoaded);
examLoader.load(examSite);
//var ugly:Mixer = new Mixer(25);
}
//Load listener - creates XML object, and checks it for multiple sections. If multiple, it asks users
//which section they want - FIRST it needs to check database for any completed sections.
//If single, it goes ahead and starts array creation for first (& only) section
private function fullyLoaded (e:Event):void {
myXML = new XML(examLoader.data);
//myXML.prettyPrinting = false;
//still need to pull out SYSTEM data and pass it along...
var system:XMLList = myXML..SYSTEM;
var sysObj:Object = new Object();
sysObj.examTitle = system.TITLE.toString();
sysObj.totalMin = system.MINUTES.toString();
sysObj.retakePW = system.RETAKEPW.toString();
var numSections:Number = myXML..SECTION.length();
if (numSections == 1) {
generateArrays(1);
}
dispatchEvent(new MultiSectEvent(MultiSectEvent.SECTIONS, numSections, sysObj));
}
//Assigns arrays to instance variables for the selected section
internal function generateArrays (sectn:Number):void {
var whichSection:XMLList = myXML..SECTION.(@id == String(sectn));
var probList:XMLList = whichSection.PROBLEM;
numQstns = probList.length();
sectStart = Number(probList[0].@id);
questions = new Array();
choiceA = new Array();
choiceB = new Array();
choiceC = new Array();
choiceD = new Array();
choiceE = new Array();
choiceF = new Array();
answers = new Array();
for (var i:Number=0; i<numQstns; i++) {
var curProb:XMLList = probList.(@id == String(i+1));
if (curProb.QUESTION.hasSimpleContent()) {
questions = curProb.QUESTION.toString();
}else {
//trace(curProb.QUESTION.toXMLString());
questions = dropTags(curProb.QUESTION[0]);
}
choiceA = curProb.CHOICE.(@letter == "a").toString();
choiceB = curProb.CHOICE.(@letter == "b").toString();
choiceC = curProb.CHOICE.(@letter == "c").toString();
choiceD = curProb.CHOICE.(@letter == "d").toString();
choiceE = curProb.CHOICE.(@letter == "e").toString();
choiceF = curProb.CHOICE.(@letter == "f").toString();
answers = curProb.CHOICE.(hasOwnProperty("@correct") && @correct == "true").@letter.toString();
}
questionNum=shuffle(questionNum)
}
//var questionslimit:Array = shuffle(questions,35);
//method for external classes to acquire text of current exam question
internal function getQuestion (qnum:Number):Object {
var returnObj:Object = new Object();
var randomQ:Number = questionNum[qnum];
returnObj.q = questions[randomQ];
returnObj.ca = choiceA[randomQ];
returnObj.cb = choiceB[randomQ];
returnObj.cc = choiceC[randomQ];
returnObj.cd = choiceD[randomQ];
returnObj.ce = choiceE[randomQ];
returnObj.cf = choiceF[randomQ];
//returnObj.num = 35;
//trace(randomQ);
return returnObj;
}
private function dropTags (txt:XML):String {
var txtString:String = "";
for each (var child:XML in txt.*) {
if (child.nodeKind == "text") {
txtString += child.toString();
}else {
txtString += " " + child.toXMLString();
}
}
//trace(txtString);
return txtString;
}
private function shuffle(a:Array) {
var p:int;
var t:*;
var ivar:int;
for (ivar = a.length-1; ivar>=0; ivar--) {
p=Math.floor((ivar+1)*Math.random());
t = a[ivar];
a[ivar] = a
;
a
= t;
}
}
/*
private function dropTags (txt:String):String {
var sliceStart:Number = txt.indexOf(">");
var sliceStop:Number = txt.lastIndexOf("<");
return txt.slice((sliceStart+1), sliceStop);
}*/
internal function getAnswer (num:Number):String {
return answers[num];
}
internal function getQCount ():Number {
return numQstns;
//trace (numQstns);
}
internal function getSectStart():Number {
return sectStart;
}
internal function getRealNum (num:Number):Number {
return shuffle.questionNum(num-1);
}
}
}

