1 /*
2  * Copyright (C) 2010 Jordi Mas i Hernàndez <jmas@softcatala.org>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public
15  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 using System;
19 
20 using gbrainy.Core.Main;
21 
22 namespace gbrainy.Games.Logic
23 {
24 	public class PuzzleTrains : Game
25 	{
26 		enum GameType
27 		{
28 			Overtake,
29 			Meet,
30 			Apart,
31 			Total
32 		}
33 
34 		string question, answer;
35 		GameType gametype;
36 
37 		public override string Name {
38 			get {return Translations.GetString ("Trains");}
39 		}
40 
41 		public override string Question {
42 			get {return question; }
43 		}
44 
45 		public override string Rationale {
46 			get { return answer;}
47 		}
48 
49 		public override string Tip {
50 			get { return Translations.GetString ("The distance formula is 'distance = rate x time'.");}
51 		}
52 
Initialize()53 		protected override void Initialize ()
54 		{
55 			int ans;
56 			double speed_a, speed_b, rslt;
57 
58 			gametype = (GameType) random.Next ((int) GameType.Total);
59 
60 			switch (gametype)
61 			{
62 			case GameType.Overtake:
63 			{
64 				double hours;
65 
66 				do
67 				{
68 					speed_a = 20 + (5 * random.Next (5));
69 					speed_b = 50 + (5 * random.Next (5));
70 					hours = 2 * (1 + random.Next (3));
71 					rslt = speed_a * hours / (speed_b - speed_a);
72 
73 				}  while (rslt != Math.Truncate (rslt));
74 
75 				question = String.Format (
76 					// Translators:
77 					//  - mph (miles per hour). You must localize this using the right unit of speed for your locale
78 					// - The translated string should not use more characters than the original sentence
79 					Translations.GetPluralString ("A train leaves the station traveling at {0} mph. {1} hour later a second train leaves the station traveling in the same direction at {2} mph. How many hours does it take the second train, since it starts moving, to overtake the first train?",
80 						"A train leaves the station traveling at {0} mph. {1} hours later a second train leaves the station traveling in the same direction at {2} mph. How many hours does it take the second train, since it starts moving, to overtake the first train?", (int) hours),
81 						speed_a, hours, speed_b);
82 
83 				answer = Translations.GetString ("You can calculate the answer by multiplying the speed of the first train by the time and dividing it by the difference of speeds.");
84 				break;
85 			}
86 			case GameType.Meet:
87 			{
88 				double distance, hours;
89 
90 				speed_a = 20 + (5 * random.Next (5));
91 				speed_b = 50 + (5 * random.Next (5));
92 				hours = 2 + random.Next (5);
93 				distance = hours * (speed_b + speed_a);
94 				rslt = hours;
95 
96 				question = String.Format (
97 					// Translators:
98 					//  - mph (miles per hour) and miles must be localized this using the right unit of speed for your locale
99 					Translations.GetPluralString ("Two trains separated by {0} mile are heading towards each other on straight parallel tracks. One travels at {1} mph and the other at {2} mph. In how many hours will they meet?",
100 						"Two trains separated by {0} miles are heading towards each other on straight parallel tracks. One travels at {1} mph and the other at {2} mph. In how many hours will they meet?",
101 						(int) distance),
102 						distance, speed_a, speed_b);
103 
104 				answer = Translations.GetString ("You can calculate the answer by dividing the distance by the sum of both speeds.");
105 				break;
106 			}
107 			case GameType.Apart:
108 			{
109 				double distance;
110 
111 				speed_a = 10 + (2 * random.Next (5));
112 				speed_b = 20 + (2 * random.Next (5));
113 				distance = (speed_a + speed_b) * (2 + random.Next (5));
114 
115 				// Time in hours
116 				rslt = distance / (speed_a + speed_b);
117 
118 				question = String.Format (
119 					// Translators:
120 					//  - mph (miles per hour) and miles must be localized this using the right unit of speed for your locale
121 					Translations.GetPluralString ("Two trains on straight parallel tracks leave from the same point and time traveling in opposite directions at {0} and {1} mph respectively. In how many hours will they be {2} mile apart?",
122 						"Two trains on straight parallel tracks leave from the same point and time traveling in opposite directions at {0} and {1} mph respectively. In how many hours will they be {2} miles apart?",
123 						(int) distance),
124 						speed_a, speed_b, distance);
125 
126 				answer = Translations.GetString ("You can calculate the answer by dividing the distance by the sum of both speeds.");
127 				break;
128 			}
129 			default:
130 				throw new Exception ("Unexpected value");
131 			}
132 
133 			ans = (int) rslt;
134 			Answer.Correct = (ans).ToString ();
135 		}
136 
Draw(CairoContextEx gr, int area_width, int area_height, bool rtl)137 		public override void Draw (CairoContextEx gr, int area_width, int area_height, bool rtl)
138 		{
139 			string train_right = "train_right.svg";
140 			string train_left = "train_left.svg";
141 
142 			base.Draw (gr, area_width, area_height, rtl);
143 
144 			switch (gametype)
145 			{
146 			case GameType.Overtake:
147 				gr.DrawImageFromAssembly (train_right, 0, 0.1, 0.5, 0.55);
148 				gr.MoveTo (0.1, 0.45);
149 				gr.LineTo (0.9, 0.45);
150 				gr.Stroke ();
151 
152 				gr.DrawImageFromAssembly (train_right, 0.5, 0.1, 0.5, 0.55);
153 				break;
154 
155 			case GameType.Meet:
156 				gr.DrawImageFromAssembly (train_right, 0, 0.1, 0.5, 0.55);
157 				gr.MoveTo (0.1, 0.45);
158 				gr.LineTo (0.9, 0.45);
159 				gr.Stroke ();
160 
161 				gr.DrawImageFromAssembly (train_left, 0.55, 0.3, 0.5, 0.55);
162 				gr.MoveTo (0.1, 0.65);
163 				gr.LineTo (0.9, 0.65);
164 				gr.Stroke ();
165 				break;
166 
167 			case GameType.Apart:
168 				gr.DrawImageFromAssembly (train_right, 0.35, 0.1, 0.5, 0.55);
169 				gr.MoveTo (0.1, 0.45);
170 				gr.LineTo (0.9, 0.45);
171 				gr.Stroke ();
172 
173 				gr.DrawImageFromAssembly (train_left, 0.15, 0.3, 0.5, 0.55);
174 				gr.MoveTo (0.1, 0.65);
175 				gr.LineTo (0.9, 0.65);
176 				gr.Stroke ();
177 				break;
178 			default:
179 				throw new Exception ("Unexpected value");
180 			}
181 		}
182 
CheckAnswer(string answer)183 		public override bool CheckAnswer (string answer)
184 		{
185 			string num = string.Empty;
186 
187 			// Clean the answer from every non-numeric values after the numbers (like 5 hours)
188 			for (int c = 0; c < answer.Length; c++)
189 			{
190 				if (answer[c] < '0' || answer[c] > '9')
191 					break;
192 
193 				num += answer[c];
194 			}
195 
196 			return base.CheckAnswer (num);
197 		}
198 	}
199 }
200