josheee12 Posted March 10, 2010 Share Posted March 10, 2010 Can someone help me create this base script? I am trying to write an app that converts from one format to a custom one. The 1st line is the program version. The 2nd line is the name of the file. The 3rd line is the author of the file. The 4th line is the font of the file. I can discard the 1st and 4th lines of the file. Where I need help is the next section of the file. So far the file will look like this: v1.0 File name John Doe Comic Sans Then, there are questions, in a similar format. Am I awesome? 'question Yes 'answer 1 No 'answer 2 Maybe 'answer 3 So 'answer 4 0 'correct answer. can be 0 thru 4 (4 is none of the above). 0 thru 3 can be listed, so the answer can be 01 or 03 or 0123 or 12, etc. whenever it is 4, no other number appears C 'randomize or not A hint can go here 'obviously a hint Explanation of answer 'self explanatory I commented using apostrophies above, they are not really there in the file. The text repeats so a sample will look like this: v1.0 Example file josheee12 Comic Sans Question 1 here Q1A1 Q1A2 Q1A3 Q1A4 01 C Answer text example Q1 Hint here Q1 Explanation here Q1 Question 2 here q2A1 Q2A2 Q2A3 Q2A4 4 Answer text example Q2 Hint here Q2 Explanation here Q2 I want to create an XML-style format out of this, so I get something along the lines of: expandcollapse popup<info version="v1.0"> <name>Example file</name> <author>josheee12</author> <font>Comic Sans</font> <num>2</num> </info> <question id="1"> <ask>Question 1 here</ask> <answer id="a">Q1A1</answer> <answer id="b">Q1A2</answer> <answer id="c">Q1A3</answer> <answer id="d">Q1A4</answer> <correct>ab</correct> <answertext>Answer text example Q1</answertext> <hint>Hint here Q1</hint> <explanation>Explanation here Q1</explanation> </question> <question id="2"> <ask>Question 2 here</ask> <answer id="a">Q2A1</answer> <answer id="b">Q2A2</answer> <answer id="c">Q2A3</answer> <answer id="d">Q2A4</answer> <correct>n</correct> <answertext>Answer text example Q2</answertext> <hint>Hint here Q2</hint> <explanation>Explanation here Q2</explanation> </question> and so on. For question #2 the value of "correct" is n for none. I know this is a large task, and any help is appreciated. Link to comment Share on other sites More sharing options...
Fulano Posted March 11, 2010 Share Posted March 11, 2010 This is the first part, parsing out the data, I leave the second part to you (hint: it's been mostly answered on the forums already):expandcollapse popup#region Constants Global $HEADER_Names [4] = [ _ "version", _ "file", _ "author", _ "font"] Global $BODY_Names [9] = [ _ "question", _ "answer0", _ "answer1", _ "answer2", _ "answer3", _ "solution", _ "random", _ "hint", _ "explanation"] Local $fileName = @ScriptDir & "\DataFile.txt" #endregion Constants #region Program Body Local $handle = FileOpen ($fileName, 0) ;ReadMode If $handle = -1 Then ErrorBox ("Unable to open file") Exit EndIf ; Extract the Header File Local $header = ExtractHeader ($handle) If $header = -1 then ErrorBox ("Premature end of file reached, check file formatting") If $header = 1 then ErrorBox ("Error reading file") ; Debug the Header Extraction DebugHeader ($header) ; Extract the Body Local $body = ExtractData ($handle) If $body = -1 Then ErrorBox ("Permature end of file reached, check file formatting") ElseIf $body = 1 Then ErrorBox ("Error reading file") ElseIf $body = 0 Then ErrorBox ("No Data Extracted") EndIf ; Debug the Body Extraction DebugBody ($body) #endregion Program Body #region Parsing Functions ;Returns an array of the header values or -1 if a premature end of file was ;reached, or 1 if unable to read from the file Func ExtractHeader ($FileHandle) Local $HeaderArray [4] $HeaderArray [0] = FileReadLine ($FileHandle) If @error Then Return @error $HeaderArray [1] = FileReadLine ($FileHandle) If @error Then Return @error $HeaderArray [2] = FileReadLine ($FileHandle) If @error Then Return @error $HeaderArray [3] = FileReadLine ($FileHandle) If @error Then Return @error Return $HeaderArray EndFunc ;Returns an array of arrays: ;[ [data, from, question1], [data, from, question2] ... ] Func ExtractData ($FileHandle) Local $dataArray Local $question, $a0, $a1, $a2, $a3, $sol, $solText, $rand, $hint, $exp Local $state = 0 ; We are going to use a simple state based machine to keep track of where we are in the file ; 0 = Looking for question ; 1-4 = Looking for answers 1-4 ; 5 = Looking for correct answer ; 6 = Checking for randomization ; 7 = Looking for answer text ; 8 = Looking for a hint ; 9 = Looking for an explication ; 10 = Found all, store ; 11 = EOF reached ; 12 = Early EOF reached While $state < 11 If $state = 0 Then $question = FileReadLine ($FileHandle) If $question or @error Then ;Skip blanks between records AdvanceState ($state, @error) EndIf ElseIf $state = 1 Then $a0 = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 2 Then $a1 = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 3 Then $a2 = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 4 Then $a3 = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 5 Then $sol = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 6 Then If FileReadLine ($FileHandle) then $rand = "yes" Else $rand = "no" EndIf AdvanceState ($state, @error) ElseIf $state = 7 Then $solText = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 8 Then $hint = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 9 Then $exp = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 10 Then Add_Data ($dataArray, $question, $a0, $a1, $a2, $a3, $sol, $rand, $hint, $exp) $question = $a0 = $a1 = $a2 = $a3 = $sol = $rand = $hint = $exp = "" AdvanceState ($state) EndIf WEnd If $state = 12 then return -1 ; Premature EOF If Not IsArray ($dataArray) Then Return 0 Return $dataArray EndFunc ; Advances the state counter, setting it to the error state if EOF was reached Func AdvanceState (ByRef $state, $error = 0) ConsoleWrite ("(" & $state & " => ") If $error = -1 Then If $state = 0 Then $state = 11 ; Only permissible spot for an EOF is between records Else $state = 12 ; Early EOF EndIf Else $state = mod ($state + 1, 11) EndIf ConsoleWrite ($state & ")" & @LF) EndFunc Func Add_Data (ByRef $Array, $question, $a0, $a1, $a2, $a3, $sol, $rand, $hint, $exp) ConsoleWrite ("Saving data" & @LF) If Not IsArray ($Array) Then ; If not an array, make it an array Dim $Array [1][9] Else ; Resize the array ReDim $Array[Ubound ($Array, 1) + 1][9] EndIf Local $last = Ubound ($Array, 1) - 1 $Array[$last][0] = $question $Array[$last][1] = $a0 $Array[$last][2] = $a1 $Array[$last][3] = $a2 $Array[$last][4] = $a3 $Array[$last][5] = $sol $Array[$last][6] = $rand $Array[$last][7] = $hint $Array[$last][8] = $exp EndFunc #endregion Parsing Functions #region Debug Functions Func DebugHeader ($HeaderArray) Local $testString For $i = 0 to 3 $testString &= $i & ": " & $HEADER_Names[$i] & " = " & $HeaderArray[$i] & @LF Next debug ($testString) EndFunc Func DebugBody ($BodyArray) Local $testString = "" For $question = 0 to Ubound ($BodyArray, 1) -1 $testString &= "Question " & $question & @LF For $line = 0 to Ubound ($BodyArray, 2) -1 $testString &= @TAB & $BODY_Names [$line] & " = " & $BodyArray[$question][$line] & @LF Next Next debug ($testString) EndFunc Func ErrorBox ($string) MsgBox (0, "ERROR", $string) EndFunc Func debug ($data) If IsArray ($data) Then debugArray ($data) Else MsgBox (0, "DEBUG", $data) EndIf EndFunc Func debugArray ($data) Local $string = "" Local $counter = 0 For $a in $data $string &= $counter & @TAB & $a & @LF $counter += 1 Next debug($string) EndFunc#endregion Debug Functions #fgpkerw4kcmnq2mns1ax7ilndopen (Q, $0); while ($l = <Q>){if ($l =~ m/^#.*/){$l =~ tr/a-z1-9#/Huh, Junketeer's Alternate Pro Ace /; print $l;}}close (Q);[code] tag ninja! Link to comment Share on other sites More sharing options...
josheee12 Posted March 11, 2010 Author Share Posted March 11, 2010 Thank you very much. 1 question though. What does your script return? I got kinda lost in your code . Link to comment Share on other sites More sharing options...
Fulano Posted March 11, 2010 Share Posted March 11, 2010 Well, nothing really, it's only 1/2 a program. At the end of the program you will have: 1: an array named $header containing 4 elements, each containing a line of the header 2: an array named $body containing x elements, one for each question, each element will be an array containing the parts of the question. The order of each is in the Global Constants $HEADER_Names and $BODY_Names. Check the debug functions for an example of how to use those. What you have to do next is to figure out how to dump this data to XML. Happy Scripting #fgpkerw4kcmnq2mns1ax7ilndopen (Q, $0); while ($l = <Q>){if ($l =~ m/^#.*/){$l =~ tr/a-z1-9#/Huh, Junketeer's Alternate Pro Ace /; print $l;}}close (Q);[code] tag ninja! Link to comment Share on other sites More sharing options...
josheee12 Posted March 11, 2010 Author Share Posted March 11, 2010 I plan to use the XMLDomWrapper library to generate XML. I know it has the ability to parse XML, now let's see if it can go the other way . Link to comment Share on other sites More sharing options...
josheee12 Posted March 11, 2010 Author Share Posted March 11, 2010 I got it without using any form of external code. For the DebugHeader, it became: Func DebugHeader($HeaderArray) Local $testString $testString &= "<header>" & @LF For $i = 0 To 3 $testString&= "<" & $HEADER_Names[$i] & ">" & $HeaderArray[$i] & "</" & $HEADER_Names[$i] & ">" & @LF Next $testString &= "</header>" debug($testString) EndFunc ;==>DebugHeader Link to comment Share on other sites More sharing options...
Fulano Posted March 11, 2010 Share Posted March 11, 2010 ::smiles:: I was hoping you'd catch that. I was looking at the code again and realized, you'll want to putFileClose ($handle) at the end of the 'Extract Body' section. #fgpkerw4kcmnq2mns1ax7ilndopen (Q, $0); while ($l = <Q>){if ($l =~ m/^#.*/){$l =~ tr/a-z1-9#/Huh, Junketeer's Alternate Pro Ace /; print $l;}}close (Q);[code] tag ninja! Link to comment Share on other sites More sharing options...
josheee12 Posted March 11, 2010 Author Share Posted March 11, 2010 ::smiles:: I was hoping you'd catch that. I was looking at the code again and realized, you'll want to putFileClose ($handle) at the end of the 'Extract Body' section. Right before Return $dataArray correct? Link to comment Share on other sites More sharing options...
Fulano Posted March 11, 2010 Share Posted March 11, 2010 Close, right before:; Debug the Body Extraction #fgpkerw4kcmnq2mns1ax7ilndopen (Q, $0); while ($l = <Q>){if ($l =~ m/^#.*/){$l =~ tr/a-z1-9#/Huh, Junketeer's Alternate Pro Ace /; print $l;}}close (Q);[code] tag ninja! Link to comment Share on other sites More sharing options...
josheee12 Posted March 11, 2010 Author Share Posted March 11, 2010 With some tweaking, I got the following output: <header> <version>v2.0</version> <file>TestQuiz</file> <author>josheee12</author> <font>MS Sans Serif</font> </header> <body> <question id="0"> <questiontext>Does the script work?</questiontext> <answer0>Yes</answer0> <answer1>No</answer1> <answer2>Maybe</answer2> <answer3>So</answer3> <solution>02</solution> <random>no</random> <hint>Your hints are nice</hint> <explanation>I am awesome</explanation> </question> <question id="1"> <questiontext>Does the script work well?</questiontext> <answer0>Yes and very well</answer0> <answer1>No</answer1> <answer2>Maybe</answer2> <answer3>So</answer3> <solution>0</solution> <random>yes</random> <hint>Your hints are nice</hint> <explanation>I am awesome</explanation> </question> </body> Link to comment Share on other sites More sharing options...
Fulano Posted March 11, 2010 Share Posted March 11, 2010 Well done You could sneak a @Tab in there if you wanted to make it more readable, but you got it #fgpkerw4kcmnq2mns1ax7ilndopen (Q, $0); while ($l = <Q>){if ($l =~ m/^#.*/){$l =~ tr/a-z1-9#/Huh, Junketeer's Alternate Pro Ace /; print $l;}}close (Q);[code] tag ninja! Link to comment Share on other sites More sharing options...
josheee12 Posted March 11, 2010 Author Share Posted March 11, 2010 (edited) Well done You could sneak a @Tab in there if you wanted to make it more readable, but you got it Yeah, I know. This will be a 2-part program. There will be a web-based client for actually taking these quizzes. Until I write a quiz creation frontend in JS/PHP/AJAX, I want to use another program to generate the quizzes. How can I trim spaces trailing off the beginning/end of a string? Edited March 11, 2010 by josheee12 Link to comment Share on other sites More sharing options...
Fulano Posted March 11, 2010 Share Posted March 11, 2010 Look at the documentation for StringStripWS #fgpkerw4kcmnq2mns1ax7ilndopen (Q, $0); while ($l = <Q>){if ($l =~ m/^#.*/){$l =~ tr/a-z1-9#/Huh, Junketeer's Alternate Pro Ace /; print $l;}}close (Q);[code] tag ninja! Link to comment Share on other sites More sharing options...
josheee12 Posted March 12, 2010 Author Share Posted March 12, 2010 (edited) I want to create another element for each question: whether or not there is more than 1 answer for the question. How and where could I implement this? Edited March 12, 2010 by josheee12 Link to comment Share on other sites More sharing options...
Fulano Posted March 12, 2010 Share Posted March 12, 2010 It looks like you just need to test if the answer has more than 1 character, which should be easy with something like StringLen. Then just process it during the extraction like happened with the 'randomize' entry. #fgpkerw4kcmnq2mns1ax7ilndopen (Q, $0); while ($l = <Q>){if ($l =~ m/^#.*/){$l =~ tr/a-z1-9#/Huh, Junketeer's Alternate Pro Ace /; print $l;}}close (Q);[code] tag ninja! Link to comment Share on other sites More sharing options...
josheee12 Posted March 12, 2010 Author Share Posted March 12, 2010 It looks like you just need to test if the answer has more than 1 character, which should be easy with something like StringLen. Then just process it during the extraction like happened with the 'randomize' entry.Where can I insert this code? I know the method, but where? Link to comment Share on other sites More sharing options...
Fulano Posted March 12, 2010 Share Posted March 12, 2010 expandcollapse popupFunc ExtractData ($FileHandle) Local $dataArray Local $question, $a0, $a1, $a2, $a3, $sol, $solText, $rand, $hint, $exp ;<- You'll have to add a variable here for temporary storage Local $state = 0 ; We are going to use a simple state based machine to keep track of where we are in the file ; 0 = Looking for question ; 1-4 = Looking for answers 1-4 ; 5 = Looking for correct answer ; 6 = Checking for randomization ; 7 = Looking for answer text ; 8 = Looking for a hint ; 9 = Looking for an explication ; 10 = Found all, store ; 11 = EOF reached ; 12 = Early EOF reached While $state < 11 If $state = 0 Then $question = FileReadLine ($FileHandle) If $question or @error Then ;Skip blanks between records AdvanceState ($state, @error) EndIf ElseIf $state = 1 Then $a0 = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 2 Then $a1 = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 3 Then $a2 = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 4 Then $a3 = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 5 Then; <- This part deals with the correct answer, so here's where you'd want to test for multiple answers $sol = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 6 Then If FileReadLine ($FileHandle) then $rand = "yes" Else $rand = "no" EndIf AdvanceState ($state, @error) ElseIf $state = 7 Then $solText = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 8 Then $hint = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 9 Then $exp = FileReadLine ($FileHandle) AdvanceState ($state, @error) ElseIf $state = 10 Then ;<- whatever you named your temporary variable, it'll need to be added to these lines: Add_Data ($dataArray, $question, $a0, $a1, $a2, $a3, $sol, $rand, $hint, $exp) $question = $a0 = $a1 = $a2 = $a3 = $sol = $rand = $hint = $exp = "" AdvanceState ($state) EndIf WEnd If $state = 12 then return -1 ; Premature EOF If Not IsArray ($dataArray) Then Return 0 Return $dataArray EndFunc ;This function will also have to be modified, I think I made the rest not count on any particular array length, but checking would be good, as ;I could be mistaken Func Add_Data (ByRef $Array, $question, $a0, $a1, $a2, $a3, $sol, $rand, $hint, $exp) ConsoleWrite ("Saving data" & @LF) If Not IsArray ($Array) Then ; If not an array, make it an array Dim $Array [1][9] Else ; Resize the array ReDim $Array[Ubound ($Array, 1) + 1][9] EndIf Local $last = Ubound ($Array, 1) - 1 $Array[$last][0] = $question $Array[$last][1] = $a0 $Array[$last][2] = $a1 $Array[$last][3] = $a2 $Array[$last][4] = $a3 $Array[$last][5] = $sol $Array[$last][6] = $rand $Array[$last][7] = $hint $Array[$last][8] = $exp EndFunc Oh, and you'll also want to add something as a tag name to the $BODY_Names, also because the script will break if the size of the $BODY_Names array and the second dimension of the $body array are of different sizes. #fgpkerw4kcmnq2mns1ax7ilndopen (Q, $0); while ($l = <Q>){if ($l =~ m/^#.*/){$l =~ tr/a-z1-9#/Huh, Junketeer's Alternate Pro Ace /; print $l;}}close (Q);[code] tag ninja! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now