[gbrainy] Support variables expression in games.xml



commit 1d280c8193e883ec14925a7475f32ed271d963c9
Author: Jordi Mas <jmas softcatala org>
Date:   Mon Jun 14 00:46:20 2010 +0200

    Support variables expression in games.xml

 configure.ac                        |    6 +-
 data/games.xml                      |   23 ++----
 src/Core/Main/Xml/GameXmlFactory.cs |  144 ++++++++++++++++++++++++++++++++++-
 src/Core/Makefile.am                |    1 +
 4 files changed, 156 insertions(+), 18 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index ef95e33..6183bf7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,10 +41,10 @@ else
   AC_MSG_RESULT([found])
 fi
 
-dnl -- check for various mono DLLs that we need.
+dnl -- check for various mono assemblies that we need.
 
-needed_dlls="Mono.Posix Mono.Cairo"
-for i in $needed_dlls; do
+needed_assemblies="Mono.Posix Mono.Cairo Mono.CSharp"
+for i in $needed_assemblies; do
   AC_MSG_CHECKING([for $i.dll])
   if test ! \( -e `$PKG_CONFIG --variable=prefix mono`/lib/mono/2.0/$i.dll -o -e `$PKG_CONFIG --variable=prefix mono`/lib64/mono/2.0//$i.dll \); then
     AC_MSG_ERROR([missing required mono 2.0 DLL: $i.dll])
diff --git a/data/games.xml b/data/games.xml
index 22f3e4c..0346262 100644
--- a/data/games.xml
+++ b/data/games.xml
@@ -16,19 +16,15 @@
 		<_name>Clock Rotation</_name>
 		<type>Logic</type>
 		<difficulty>All</difficulty>
-		<_tip>Think of the items used in the game.</_tip>
+		<variables>
+			int num = random.Next (5) * 10;
+			int rslt = (2 * 360) + (num * 6);
+		</variables>
 		<_rationale>Every hour rotates 360 degrees.</_rationale>
 		<svg file = "clock.svg" x = "0.25" y = "0.25" width = "0.5" height = "0.5"/>
-		<_question>How many degrees rotates the minute hand of a clock in 2 hours 40 minutes?</_question>
-		<answer>960</answer>
-		<_question>How many degrees rotates the minute hand of a clock in 2 hours 30 minutes?</_question>
-		<answer>900</answer>
-		<_question>How many degrees rotates the minute hand of a clock in 1 hours 20 minutes?</_question>
-		<answer>480</answer>
-		<_question>How many degrees rotates the minute hand of a clock in 1 hours 40 minutes?</_question>
-		<answer>600</answer>
+		<_question>How many degrees rotates the minute hand of a clock in 2 hours [num] minutes?</_question>
+		<answer>[rslt]</answer>
 	</game>
-
 	<game>
 		<_name>Family relations</_name>
 		<type>Logic</type>
@@ -36,14 +32,13 @@
 		<svg file = "family.svg" x = "0.25" y = "0.25" width = "0.5" height = "0.5"/>
 		<variant>
 			<_question>A boy has as many brothers as he has sisters. Each brother has twice as many sisters as brothers. How many brothers and sisters the family has in total?</_question>
-			<_answer>7</_answer>
-			<_rationale>He has tree brothers and four sisters.</_rationale>
+			<answer>7</answer>
+			<_rationale>He has three brothers and four sisters.</_rationale>
 		</variant>
 		<variant>
 			<_question>John's age is nowadays 5 times his son's age. 4 years ago John was 9 times older than his son. What's is John's age nowadays?</_question>
-			<_answer>40</_answer>
+			<answer>40</answer>
 		</variant>
 
 	</game>
-
 </games>
diff --git a/src/Core/Main/Xml/GameXmlFactory.cs b/src/Core/Main/Xml/GameXmlFactory.cs
index bc70d21..a7f7017 100644
--- a/src/Core/Main/Xml/GameXmlFactory.cs
+++ b/src/Core/Main/Xml/GameXmlFactory.cs
@@ -20,8 +20,11 @@
 using System;
 using System.Xml;
 using System.IO;
+using System.Text;
 using System.Collections.Generic;
 using System.Globalization;
+using Mono.CSharp;
+using System.Text.RegularExpressions;
 
 using Mono.Unix;
 
@@ -31,6 +34,7 @@ namespace gbrainy.Core.Main
 	{
 		static List <GameXmlDefinition> games;
 		static bool read = false;
+		static bool? monofix_needed;
 
 		static GamesXmlFactory ()
 		{
@@ -69,10 +73,23 @@ namespace gbrainy.Core.Main
 				{
 					name = reader.Name.ToLower ();
 					switch (name) {
+					case "games":
+						break;
+					case "type":
+						break;
 					case "game":
 						if (reader.NodeType == XmlNodeType.Element) {
 							game = new GameXmlDefinition ();
 						} else if (reader.NodeType == XmlNodeType.EndElement) {
+
+							for (int i = 0; i < game.Variants.Count; i++)
+							{
+								game.Variants[i].Question = ReplaceVariables (game.Variants[i].Question);
+								game.Variants[i].Answer = ReplaceVariables (game.Variants[i].Answer);
+							}
+
+							game.Question = ReplaceVariables (game.Question);
+							game.Answer = ReplaceVariables (game.Answer);
 							games.Add (game);
 						}
 						break;
@@ -82,7 +99,7 @@ namespace gbrainy.Core.Main
 
 						game.Name = reader.ReadElementString ();
 						break;
-					case "_difficulty":
+					case "difficulty":
 						if (reader.NodeType != XmlNodeType.Element)
 							break;
 
@@ -189,7 +206,26 @@ namespace gbrainy.Core.Main
 							processing_variant = false;
 						}
 						break;
+					case "variables":
+					{
+						string eval;
+
+						// Using's for the variables section
+						eval = "using System;\n";
+						Mono.CSharp.Evaluator.Run (eval);
+
+						// Infrastructure for the user available
+						eval = "Random random = new Random ();\n";
+						Mono.CSharp.Evaluator.Run (eval);
+
+						eval = reader.ReadElementString ();
+						Mono.CSharp.Evaluator.Run (eval);
+						break;
+					}
 					default:
+						if (String.IsNullOrEmpty (name) == false)
+							Console.WriteLine ("GameXmlFactory. Unsupported tag: {0}", name);
+
 						break;
 					}
 				}
@@ -206,5 +242,111 @@ namespace gbrainy.Core.Main
 				Console.WriteLine ("GameXmlFactory. Error loading: {0}", e.Message);
 			}
 		}
+
+		// Before Mono 2.6 (rev. 156533) there is no line separator between vars
+		static string FixGetVars (string str)
+		{
+			if (monofix_needed == null)
+			{
+				string eval, vars;
+
+				eval = "int a = 1; int b = 1;";
+				Evaluator.Run (eval);
+				vars = Evaluator.GetVars ();
+
+				monofix_needed = vars.IndexOf (System.Environment.NewLine) == -1;
+			}
+
+			if (monofix_needed == false)
+				return str;
+
+			// We just guarantee that int, doubles, and float are separated as modern Mono versions do
+			StringBuilder output = new StringBuilder ();
+			string [] keywords = new string [] {"int", "double", "float"};
+			int pos = 0, cur = 0;
+
+			while (pos != -1)
+			{
+				for (int i = 0; i < keywords.Length; i++)
+				{
+					pos = str.IndexOf (keywords [i], cur);
+					if (pos != -1)
+					{
+						output.Append (str.Substring (cur, pos - cur));
+						output.AppendLine ();
+						output.Append (str.Substring (pos, keywords[i].Length));
+						cur = pos + keywords[i].Length;
+						break;
+					}
+				}
+			}
+
+			output.Append (str.Substring (cur, str.Length - cur));
+			return output.ToString ();
+		}
+
+		static string GetVarValue (string vars, string _var)
+		{
+			const string exp = "([a-z0-9._%+-]+) ([a-z0-9._%+-]+) (=) ([0-9]+)";
+			Match match;
+			int idx, cur, newline_len;
+			string line;
+
+			Regex regex = new Regex (exp, RegexOptions.IgnoreCase);
+
+			newline_len = System.Environment.NewLine.Length;
+			cur = 0;
+
+			do
+			{
+				// Process a line
+				idx = vars.IndexOf (System.Environment.NewLine, cur);
+				if (idx == -1) idx = vars.Length;
+
+				line = vars.Substring (cur, idx - cur);
+				cur = idx + newline_len;
+				match = regex.Match (line);
+
+				//  "int num = 2";
+				//   group 1 -> int,  group 2 -> num,  group 3 -> =, group 4 -> 2
+				if (match.Groups.Count == 5)
+				{
+					if (match.Groups[2].Value == _var)
+						return match.Groups[4].Value;
+				}
+
+			} while (cur < vars.Length);
+
+			return string.Empty;
+		}
+
+		static string ReplaceVariables (string str)
+		{
+			const string exp = "\\[[a-z]+\\]+";
+			string eval, var, vars, var_value;
+			Regex regex;
+			Match match;
+
+			if (String.IsNullOrEmpty (str))
+				return str;
+
+			regex = new Regex (exp, RegexOptions.IgnoreCase);
+			match = regex.Match (str);
+
+			while (String.IsNullOrEmpty (match.Value) == false)
+			{
+				var = match.Value.Substring (1, match.Value.Length - 2);
+				vars = Evaluator.GetVars ();
+				vars = FixGetVars (vars);
+
+				var_value = GetVarValue (vars, var);
+
+				if (String.IsNullOrEmpty (var_value) == false)
+					str = str.Replace (match.Value, var_value);
+
+				match = match.NextMatch ();
+			}
+			return str;
+		}
 	}
 }
diff --git a/src/Core/Makefile.am b/src/Core/Makefile.am
index 4e20481..b613a75 100644
--- a/src/Core/Makefile.am
+++ b/src/Core/Makefile.am
@@ -69,6 +69,7 @@ REFS =  \
 	-r:System \
 	-r:Mono.Cairo.dll		\
 	-r:Mono.Posix			\
+	-r:Mono.CSharp.dll		\
 	 $(GBRAINY_LIBS)    		\
 	 $(MONO_ADDINS_LIBS)
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]