[gbrainy] Support for options in XML game types



commit 3d18a86385e6140f3a2af25dab09b975e5b3a4a4
Author: Jordi Mas <jmas softcatala org>
Date:   Sun Oct 31 14:06:46 2010 +0100

    Support for options in XML game types

 po/POTFILES.in                                     |    1 +
 src/Core/Core.csproj                               |    9 +
 src/Core/Main/Game.cs                              |    2 +-
 src/Core/Main/Xml/GameXml.cs                       |  286 ++++++++++++++++----
 src/Core/Main/Xml/GameXmlFactory.cs                |   70 +++++-
 src/Core/Main/Xml/OptionDrawingObject.cs           |   80 ++++++
 src/Core/Makefile.am                               |    1 +
 .../Calculation/CalculationGreatestDivisor.cs      |    2 -
 8 files changed, 395 insertions(+), 56 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4b68021..3258ac1 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -24,6 +24,7 @@ src/Core/Main/Verbal/AnalogiesPairOfWordsCompare.cs
 src/Core/Main/Verbal/AnalogiesPairOfWordsOptions.cs
 src/Core/Main/Verbal/AnalogiesQuestionAnswer.cs
 src/Core/Main/Verbal/AnalogiesFactory.cs
+src/Core/Main/Xml/GameXml.cs
 src/Clients/Classical/gbrainy.cs
 src/Clients/Classical/CommandLine.cs
 src/Clients/Classical/Dialogs/AboutDialog.cs
diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj
index 21fd673..30c8f99 100644
--- a/src/Core/Core.csproj
+++ b/src/Core/Core.csproj
@@ -36,10 +36,13 @@
     <Reference Include="Mono.Posix" />
     <Reference Include="System.Xml" />
     <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <Package>gtk-sharp-2.0</Package>
     </Reference>
     <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <Package>gtk-sharp-2.0</Package>
     </Reference>
     <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <Package>gtk-sharp-2.0</Package>
     </Reference>
     <Reference Include="Mono.CSharp" />
     <Reference Include="Mono.Cairo" />
@@ -93,6 +96,12 @@
     <Compile Include="Main\Xml\CodeEvaluation.cs" />
     <Compile Include="Main\GameAnswerCheckAttributes.cs" />
     <Compile Include="Main\GameDifficulty.cs" />
+    <Compile Include="Main\Xml\OptionDrawingObject.cs" />
+    <Compile Include="Main\Xml\GameXmlDefinitionVariant.cs" />
+    <Compile Include="Main\Xml\ImageDrawingObject.cs" />
+    <Compile Include="Main\Xml\LocalizableString.cs" />
+    <Compile Include="Main\Xml\TextDrawingObject.cs" />
+    <Compile Include="Main\Xml\DrawingObject.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ProjectExtensions>
diff --git a/src/Core/Main/Game.cs b/src/Core/Main/Game.cs
index eec8568..6270c6d 100644
--- a/src/Core/Main/Game.cs
+++ b/src/Core/Main/Game.cs
@@ -62,6 +62,7 @@ namespace gbrainy.Core.Main
 
 		protected Game ()
 		{
+			containers = new List <Toolkit.Container> ();
 			difficulty = GameDifficulty.Medium;
 		}
 
@@ -129,7 +130,6 @@ namespace gbrainy.Core.Main
 		{
 			random = new Random ();
 			default_color = new Cairo.Color (0, 0, 0);
-			containers = new List <Toolkit.Container> ();
 			Initialize ();
 		}
 
diff --git a/src/Core/Main/Xml/GameXml.cs b/src/Core/Main/Xml/GameXml.cs
index 384d1e3..23eef4d 100644
--- a/src/Core/Main/Xml/GameXml.cs
+++ b/src/Core/Main/Xml/GameXml.cs
@@ -23,6 +23,8 @@ using System.IO;
 
 using Mono.Unix;
 
+using gbrainy.Core.Toolkit;
+
 namespace gbrainy.Core.Main.Xml
 {
 	public class GameXml : Game
@@ -46,9 +48,13 @@ namespace gbrainy.Core.Main.Xml
 		static List <GameXmlDefinition> games;
 		static List <DefinitionLocator> locators;
 
+		static string option_prefix = "[option_prefix]";
+		static string option_answers = "[option_answers]";
+
 		DefinitionLocator current;
 		GameXmlDefinition game;
 		string question, answer, rationale, answer_value;
+		List <OptionDrawingObject> options;
 
 		public override GameAnswerCheckAttributes CheckAttributes  {
 			get {
@@ -196,7 +202,167 @@ namespace gbrainy.Core.Main.Xml
 				answer_value = CodeEvaluation.ReplaceVariables (answer_value);
 			}
 
-			right_answer = answer;
+			if (options != null && options.Count > 0)
+			{
+				string answers = string.Empty;
+
+				foreach (OptionDrawingObject option in options)
+				{
+					if (option.Correct == true)
+					{
+						right_answer = option.Answer;
+						break;
+					}
+				}
+	
+				string q;
+
+				for (int i = 0; i < options.Count - 1; i++)
+					answers += String.Format (Catalog.GetString ("{0}, "), GetPossibleAnswer (i));
+
+				answers += String.Format (Catalog.GetString ("{0}."), GetPossibleAnswer (options.Count - 1));
+
+				// Translators {0}: list of options (A, B, C)
+				answers = String.Format (Catalog.GetString ("Answer {0}"), answers);
+				question = question.Replace (option_answers, answers);					
+			}
+			else
+			{
+				right_answer = answer;
+			}
+		}
+
+		void CreateDrawingObjects (GameXmlDefinitionVariant game)
+		{
+			OptionDrawingObject option;
+			double x = 0, y = 0, width = 0, height = 0;
+			bool first = true;
+			int randomized_options = 0;
+
+			if (game.DrawingObjects == null)
+				return;
+
+			// Calculate the size of container from the options and count the number of random options
+			foreach (DrawingObject draw_object in game.DrawingObjects)
+			{
+				option = draw_object as OptionDrawingObject;
+
+				if (option == null)
+					continue;
+
+				if (option.RandomizedOrder)
+					randomized_options++;
+
+				if (first == true)
+				{
+					x = option.X;
+					y = option.Y;
+					width = option.Width;
+					height = option.Height;
+					first = false;
+					continue;
+				}
+
+				if (option.X < x) 
+					x = option.X;
+
+				if (option.Y < y) 
+					y = option.Y;
+
+				if (option.X + option.Width > width)
+					width = option.X + option.Width;
+
+				if (option.Y + option.Height > height) 
+					height = option.Y + option.Height;
+			}
+
+			if (first == true)
+				return;
+
+			// Randomize the order of the options
+			if (randomized_options > 0)
+			{
+				OptionDrawingObject [] originals;
+				ArrayListIndicesRandom random_indices;
+				DrawingObject temporary;
+				int index = 0;
+
+				random_indices = new ArrayListIndicesRandom (randomized_options);
+				originals = new OptionDrawingObject [randomized_options];
+				random_indices.Initialize ();
+
+				// Backup originals
+				for (int i = 0; i < game.DrawingObjects.Length; i++)
+				{
+					option = game.DrawingObjects[i] as OptionDrawingObject;
+
+					if (option == null)
+						continue;
+
+					originals[index] = option.Copy ();
+					index++;
+				}
+
+				// Swap
+				index = 0;
+				for (int i = 0; i < game.DrawingObjects.Length; i++)
+				{
+					option = game.DrawingObjects[i] as OptionDrawingObject;
+
+					if (option == null)
+						continue;
+
+					option.CopyRandomizedProperties (originals [random_indices [index]]);
+
+					// For randomized options the answer is always the option letter
+					option.Answer = GetPossibleAnswer (index);
+					index++;
+				}
+			}
+
+			Container container = new Container (x, y, width - x, height - y);
+			AddWidget (container);
+
+			if (options == null)
+				options = new List <OptionDrawingObject> ();
+
+			int idx = 0;
+
+			// Create drawing widgets objects
+			foreach (DrawingObject draw_object in game.DrawingObjects)
+			{
+				option = draw_object as OptionDrawingObject;
+
+				if (option == null)
+					continue;
+
+				DrawableArea drawable_area = new DrawableArea (option.Width, option.Height);
+				drawable_area.X = option.X;
+				drawable_area.Y = option.Y; // + i * 0.15;
+				container.AddChild (drawable_area);
+				
+				drawable_area.Data = idx;
+				drawable_area.DataEx = GetPossibleAnswer (idx);
+				options.Add (option);
+
+				idx++;
+				drawable_area.DrawEventHandler += DrawOption;
+			}
+		}
+
+		void DrawOption (object sender, DrawEventArgs e)
+		{
+			int idx = (int) e.Data;
+
+			if (options.Count == 0)
+				return;
+
+			OptionDrawingObject _option = options [idx];
+			Widget widget = (Widget) sender;
+			
+			e.Context.SetPangoLargeFontSize ();
+
+			DrawObjects (e.Context, _option.DrawingObjects, idx);
 		}
 
 		public override int Variants {
@@ -218,6 +384,11 @@ namespace gbrainy.Core.Main.Xml
 				current.Game = locator.Game;
 				current.Variant = locator.Variant;
 				game = games [locator.Game];
+
+				CreateDrawingObjects (game); // Draw objects shared by all variants
+
+				if (game.Variants.Count > 0)
+					CreateDrawingObjects (game.Variants[current.Variant]); // Draw variant specific objects
 			}
 		}
 
@@ -225,68 +396,83 @@ namespace gbrainy.Core.Main.Xml
 		{
 			base.Draw (gr, area_width, area_height, rtl);
 
-			DrawObjects (gr, game); // Draw objects shared by all variants
+			DrawObjects (gr, game.DrawingObjects, null); // Draw objects shared by all variants
 
 			if (game.Variants.Count > 0)
-				DrawObjects (gr, game.Variants[current.Variant]); // Draw variant specific objects
+				DrawObjects (gr, game.Variants[current.Variant].DrawingObjects, null); // Draw variant specific objects
 		}
 
-		void DrawObjects (CairoContextEx gr, GameXmlDefinitionVariant definition)
+		static void DrawObjects (CairoContextEx gr, DrawingObject [] drawing_objects, int? option)
 		{
-			if (definition.DrawingObjects != null)
+			if (drawing_objects == null)
+				return;
+
+			foreach (DrawingObject draw_object in drawing_objects)
 			{
-				foreach (DrawingObject draw_object in definition.DrawingObjects)
+				if (draw_object is OptionDrawingObject)
+					continue;
+
+				if (draw_object is TextDrawingObject)
 				{
-					if (draw_object is TextDrawingObject)
-					{
-						string text;
-						TextDrawingObject draw_string = draw_object as TextDrawingObject;
-
-						text = CatalogGetString (draw_string.Text);
-						text = CodeEvaluation.ReplaceVariables (text);
-
-						switch (draw_string.Size) {
-						case TextDrawingObject.Sizes.Small:
-							gr.SetPangoFontSize (0.018);
-							break;
-						case TextDrawingObject.Sizes.Medium:
-							gr.SetPangoNormalFontSize (); // 0.022
-							break;
-						case TextDrawingObject.Sizes.Large:
-							gr.SetPangoLargeFontSize (); // 0.0325
-							break;
-						case TextDrawingObject.Sizes.XLarge:
-							gr.SetPangoFontSize (0.06);
-							break;
-						case TextDrawingObject.Sizes.XXLarge:
-							gr.SetPangoFontSize (0.08);
-							break;
-						default:
-							throw new InvalidOperationException ("Invalid value");
-						}
-
-						if (draw_string.Centered) {
-							gr.DrawTextCentered (draw_string.X, draw_string.Y, text);
-						} else {
-							gr.MoveTo (draw_string.X, draw_string.Y);
+					string text;
+					TextDrawingObject draw_string = draw_object as TextDrawingObject;
+
+					text = CatalogGetString (draw_string.Text);
+					text = CodeEvaluation.ReplaceVariables (text);
+
+					switch (draw_string.Size) {
+					case TextDrawingObject.Sizes.Small:
+						gr.SetPangoFontSize (0.018);
+						break;
+					case TextDrawingObject.Sizes.Medium:
+						gr.SetPangoNormalFontSize (); // 0.022
+						break;
+					case TextDrawingObject.Sizes.Large:
+						gr.SetPangoLargeFontSize (); // 0.0325
+						break;
+					case TextDrawingObject.Sizes.XLarge:
+						gr.SetPangoFontSize (0.06);
+						break;
+					case TextDrawingObject.Sizes.XXLarge:
+						gr.SetPangoFontSize (0.08);
+						break;
+					default:
+						throw new InvalidOperationException ("Invalid value");
+					}
+
+					if (draw_string.Centered) {
+						gr.DrawTextCentered (draw_string.X, draw_string.Y, text);
+					} else {
+						gr.MoveTo (draw_string.X, draw_string.Y);
+						if (option == null)
 							gr.ShowPangoText (text);
-							gr.Stroke ();
-						}
+						else
+							gr.ShowPangoText (GetOptionPrefix (text, (int) option));
+
+						gr.Stroke ();
 					}
-					else if (draw_object is ImageDrawingObject)
-					{
-						ImageDrawingObject image = draw_object as ImageDrawingObject;
+				}
+				else if (draw_object is ImageDrawingObject)
+				{
+					ImageDrawingObject image = draw_object as ImageDrawingObject;
 
-						if (String.IsNullOrEmpty (image.Filename) == false)
-						{
-							gr.DrawImageFromFile (Path.Combine (Defines.DATA_DIR, image.Filename),
-								image.X, image.Y, image.Width, image.Height);
-						}
+					if (String.IsNullOrEmpty (image.Filename) == false)
+					{
+						gr.DrawImageFromFile (Path.Combine (Defines.DATA_DIR, image.Filename),
+							image.X, image.Y, image.Width, image.Height);
 					}
 				}
 			}
 		}
 
+		static string GetOptionPrefix (string str, int option)
+		{
+			string answer;
+			
+			answer = String.Format (Catalog.GetString ("{0}) "), GetPossibleAnswer (option));
+			return str.Replace (option_prefix, answer);
+		}
+
 		void BuildLocationList ()
 		{
 			locators.Clear ();
@@ -300,7 +486,7 @@ namespace gbrainy.Core.Main.Xml
 		}
 
 		// Protect from calling with null (exception)
-		string CatalogGetString (string str)
+		static string CatalogGetString (string str)
 		{
 			if (String.IsNullOrEmpty (str))
 				return str;
@@ -309,7 +495,7 @@ namespace gbrainy.Core.Main.Xml
 		}
 
 		// Protect from calling with null + resolve plurals
-		string CatalogGetString (LocalizableString localizable)
+		static string CatalogGetString (LocalizableString localizable)
 		{
 			if (localizable == null)
 				return string.Empty;
diff --git a/src/Core/Main/Xml/GameXmlFactory.cs b/src/Core/Main/Xml/GameXmlFactory.cs
index a87854d..bf3cc46 100644
--- a/src/Core/Main/Xml/GameXmlFactory.cs
+++ b/src/Core/Main/Xml/GameXmlFactory.cs
@@ -45,6 +45,7 @@ namespace gbrainy.Core.Main.Xml
 			string name, str, plural;
 			bool processing_variant = false;
 			int variant = 0;
+			OptionDrawingObject option = null;			
 
 			if (read == true)
 				return;
@@ -132,10 +133,17 @@ namespace gbrainy.Core.Main.Xml
 
 						TextDrawingObject draw_string = new TextDrawingObject ();
 
-						if (processing_variant)
-							game.Variants[variant].AddDrawingObject (draw_string);
+						if (option != null)
+						{
+							option.AddDrawingObject (draw_string);
+						}
 						else
-							game.AddDrawingObject (draw_string);
+						{
+							if (processing_variant)
+								game.Variants[variant].AddDrawingObject (draw_string);
+							else
+								game.AddDrawingObject (draw_string);
+						}
 
 						draw_string.Text = reader.GetAttribute ("text");
 	
@@ -321,6 +329,62 @@ namespace gbrainy.Core.Main.Xml
 						else
 							game.Variables = reader.ReadElementString ();
 						break;
+					case "option":
+						if (reader.NodeType != XmlNodeType.Element)
+							break;
+
+						OptionDrawingObject option_draw = new OptionDrawingObject ();
+
+						if (reader.NodeType == XmlNodeType.Element) {
+							option = option_draw;
+						} else if (reader.NodeType == XmlNodeType.EndElement) {
+							option = null;
+							break;
+						}
+
+						if (processing_variant)
+							game.Variants[variant].AddDrawingObject (option_draw);
+						else
+							game.AddDrawingObject (option_draw);
+	
+						option_draw.Answer = reader.GetAttribute ("answer");
+	
+						if (String.IsNullOrEmpty (option_draw.Answer))
+							option_draw.Answer = reader.GetAttribute ("_answer");
+
+						str = reader.GetAttribute ("x");
+						if (String.IsNullOrEmpty (str) == false)
+							option_draw.X = Double.Parse (str, CultureInfo.InvariantCulture);
+						else
+							option_draw.X = 0.1;
+
+						str = reader.GetAttribute ("y");
+						if (String.IsNullOrEmpty (str) == false)
+							option_draw.Y = Double.Parse (str, CultureInfo.InvariantCulture);
+						else
+							option_draw.Y = 0.1;
+
+						str = reader.GetAttribute ("width");
+						if (String.IsNullOrEmpty (str) == false)
+							option_draw.Width = Double.Parse (str, CultureInfo.InvariantCulture);
+						else
+							option_draw.Width = 0.1;
+
+						str = reader.GetAttribute ("height");
+						if (String.IsNullOrEmpty (str) == false)
+							option_draw.Height = Double.Parse (str, CultureInfo.InvariantCulture);
+						else
+							option_draw.Height = 0.1;
+
+						str = reader.GetAttribute ("order");
+						if (String.IsNullOrEmpty (str) == false)
+							option_draw.RandomizedOrder = true;
+
+						str = reader.GetAttribute ("correct");
+						if (String.Compare (str, "yes", true) == 0)
+							option_draw.Correct = true;
+
+						break;
 					default:
 						if (String.IsNullOrEmpty (name) == false)
 							Console.WriteLine ("GameXmlFactory. Unsupported tag: {0}", name);
diff --git a/src/Core/Main/Xml/OptionDrawingObject.cs b/src/Core/Main/Xml/OptionDrawingObject.cs
new file mode 100644
index 0000000..2f932e2
--- /dev/null
+++ b/src/Core/Main/Xml/OptionDrawingObject.cs
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 Jordi Mas i Hernàndez <jmas softcatala org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+using System;
+using System.Collections.Generic;
+
+namespace gbrainy.Core.Main.Xml
+{
+	public class OptionDrawingObject : DrawingObject
+	{
+		public double X { get; set; }
+		public double Y { get; set; }
+		public double Width { get; set; }
+		public double Height { get; set; }
+		public string Answer { get; set; }
+		public bool Correct { get; set; }
+		public bool RandomizedOrder { get; set; }
+
+		List <DrawingObject> drawing_objects;
+
+		public DrawingObject [] DrawingObjects {
+			get {
+				if (drawing_objects == null)
+					return null;
+	
+				return drawing_objects.ToArray ();
+			}
+		}
+
+		public void AddDrawingObject (DrawingObject obj)
+		{
+			if (drawing_objects == null)
+				drawing_objects = new List <DrawingObject> ();
+
+			drawing_objects.Add (obj);
+		}
+
+		public void CopyRandomizedProperties (OptionDrawingObject obj)
+		{
+			Answer = obj.Answer;
+			Correct = obj.Correct;
+			drawing_objects = obj.drawing_objects;
+		}
+
+		// Deep copy
+		public OptionDrawingObject Copy ()
+		{
+			OptionDrawingObject option = new OptionDrawingObject ();
+			
+			option.X = X;
+			option.Y = Y;
+			option.Width = Width;
+			option.Height = Height;
+			option.Answer = Answer;
+			option.Correct = Correct;
+			option.RandomizedOrder = RandomizedOrder;
+			
+			foreach (DrawingObject obj in DrawingObjects)
+				option.AddDrawingObject (obj);
+
+			return option;
+		}
+	}
+}
diff --git a/src/Core/Makefile.am b/src/Core/Makefile.am
index ae5108e..cec80e5 100644
--- a/src/Core/Makefile.am
+++ b/src/Core/Makefile.am
@@ -28,6 +28,7 @@ CSDISTFILES =  \
 		$(srcdir)/Main/Xml/GameXmlFactory.cs	\
 		$(srcdir)/Main/Xml/GameXmlDefinition.cs	\
 		$(srcdir)/Main/Xml/GameXmlDefinitionVariant.cs	\
+		$(srcdir)/Main/Xml/OptionDrawingObject.cs \
 		$(srcdir)/Main/Xml/TextDrawingObject.cs	\
 		$(srcdir)/Main/Memory.cs		\
 		$(srcdir)/Main/PlayerHistory.cs		\
diff --git a/src/Games/Calculation/CalculationGreatestDivisor.cs b/src/Games/Calculation/CalculationGreatestDivisor.cs
index fca821f..c968415 100644
--- a/src/Games/Calculation/CalculationGreatestDivisor.cs
+++ b/src/Games/Calculation/CalculationGreatestDivisor.cs
@@ -229,8 +229,6 @@ namespace gbrainy.Games.Calculation
 
 			base.Draw (gr, area_width, area_height, rtl);
 
-			
-
 			gr.MoveTo (0.05, y);
 			gr.SetPangoLargeFontSize ();
 			gr.ShowPangoText (Catalog.GetString ("Numbers"));



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