1 /* 2 * Copyright (C) 2007 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 using Cairo; 20 21 using gbrainy.Core.Main; 22 using gbrainy.Core.Toolkit; 23 using gbrainy.Core.Services; 24 25 namespace gbrainy.Games.Logic 26 { 27 public class PuzzleMissingSlice : Game 28 { 29 private const int total_slices = 6; 30 private const int half_slices = total_slices / 2; 31 private const int items_per_slice = 3; 32 private const double radius = 0.22; 33 private const double radian = Math.PI / 180; 34 private const double arc_centerx = 0.2, arc_centery = 0.2; 35 private const int possible_answers = 3; 36 private ArrayListIndicesRandom random_indices; 37 private int ans_pos; 38 private int[] bad_answers; 39 private int sum_offset; 40 41 private int [] slices = new int [] 42 { 43 2, 4, 3, 44 2, 3, 6, 45 1, 3, 4, 46 3, 7, 1, 47 6, 3, 2, 48 }; 49 50 private int [] slices_opposite = new int [] 51 { 52 6, 4, 5, 53 6, 5, 2, 54 7, 5, 4, 55 5, 1, 7, 56 2, 5, 6, 57 }; 58 59 public override string Name { 60 get {return Translations.GetString ("Missing slice");} 61 } 62 63 public override string Question { 64 get {return String.Format ( 65 Translations.GetString ("The slices below have some kind of relation. Which is the missing slice in the circle below? Answer {0}, {1} or {2}."), 66 Answer.GetMultiOption (0), Answer.GetMultiOption (1), Answer.GetMultiOption (2));} 67 } 68 69 public override string Tip { 70 get { return Translations.GetString ("Each slice is related to the opposite one.");} 71 } 72 73 public override string Rationale { 74 get { 75 return String.Format (Translations.GetString ("All numbers of each slice, when added to the ones of the opposite slice, add always {0}."), sum_offset + 8); 76 } 77 } 78 Initialize()79 protected override void Initialize () 80 { 81 sum_offset = random.Next (3); 82 random_indices = new ArrayListIndicesRandom (slices.Length / items_per_slice); 83 random_indices.Initialize (); 84 ans_pos = random.Next (possible_answers); 85 86 Answer.CheckAttributes |= GameAnswerCheckAttributes.MultiOption | GameAnswerCheckAttributes.IgnoreSpaces; 87 Answer.SetMultiOptionAnswer (ans_pos, Answer.GetFigureName (ans_pos)); 88 89 bad_answers = new int [possible_answers * items_per_slice]; 90 for (int i = 0; i < bad_answers.Length; i++) { 91 bad_answers[i] = 1 + random.Next (9); 92 } 93 94 HorizontalContainer container = new HorizontalContainer (DrawAreaX, 0.62, 0.8, 0.3); 95 DrawableArea drawable_area; 96 AddWidget (container); 97 98 for (int i = 0; i < possible_answers; i++) 99 { 100 drawable_area = new DrawableArea (0.8 / 3, 0.3); 101 drawable_area.SelectedArea = new Rectangle (0, 0, radius, 0.2); 102 drawable_area.Data = i; 103 drawable_area.DataEx = Answer.GetMultiOption (i); 104 container.AddChild (drawable_area); 105 106 drawable_area.DrawEventHandler += delegate (object sender, DrawEventArgs e) 107 { 108 int n = (int) e.Data; 109 110 DrawSlice (e.Context, 0, 0); 111 if (n == ans_pos) { 112 int pos = random_indices [0]; 113 DrawSliceText (e.Context, 0, 0, 0, (sum_offset + 114 slices [pos * items_per_slice]).ToString (), 115 (sum_offset + slices [1 + (pos * items_per_slice)]).ToString (), 116 (sum_offset + slices [2 + (pos * items_per_slice)]).ToString ()); 117 } else { 118 DrawSliceText (e.Context, 0, 0, 0, 119 bad_answers [n * items_per_slice].ToString (), 120 bad_answers [1 + (n * items_per_slice)].ToString (), 121 bad_answers [2 + (n * items_per_slice)].ToString ()); 122 } 123 124 e.Context.MoveTo (0.0, 0.25); 125 e.Context.DrawTextCentered (radius / 2, 0.25, Answer.GetFigureName (n)); 126 e.Context.Stroke (); 127 }; 128 } 129 } 130 DrawSlice(CairoContextEx gr, double x, double y)131 private static void DrawSlice (CairoContextEx gr, double x, double y) 132 { 133 double degrees, x1, y1; 134 135 degrees = 0; 136 gr.MoveTo (x, y); 137 x1 = x + radius * Math.Cos (degrees); 138 y1 = y + radius * Math.Sin (degrees); 139 gr.LineTo (x1, y1); 140 gr.Stroke (); 141 142 degrees = radian * 60; 143 gr.MoveTo (x, y); 144 x1 = x + radius * Math.Cos (degrees); 145 y1 = y + radius * Math.Sin (degrees); 146 gr.LineTo (x1, y1); 147 gr.Stroke (); 148 149 gr.Arc (x, y, radius, 0, radian * 60); 150 gr.Stroke (); 151 } 152 DrawSliceText(CairoContextEx gr, double x, double y, int slice, string str1, string str2, string str3)153 static private void DrawSliceText (CairoContextEx gr, double x, double y, int slice, string str1, string str2, string str3) 154 { 155 double x0, y0, degrees; 156 157 // Number more near to the center; 158 degrees = radian * (slice * ((360 / total_slices)) + (360 / 12)); 159 x0 = 0.35 * radius * Math.Cos (degrees); 160 y0 = 0.35 * radius * Math.Sin (degrees); 161 gr.DrawTextCentered (x + x0, y + y0, str1); 162 163 // Number opposite to the center and at the top 164 degrees = radian * (slice * ((360 / total_slices)) + (360 / 24)); 165 x0 = 0.8 * radius * Math.Cos (degrees); 166 y0 = 0.8 * radius * Math.Sin (degrees); 167 gr.DrawTextCentered (x + x0, y + y0, str2); 168 169 // Number opposite to the center and at the bottom 170 degrees = radian * (slice * ((360 / total_slices)) + (360 / 8)); 171 x0 = 0.8 * radius * Math.Cos (degrees); 172 y0 = 0.8 * radius * Math.Sin (degrees); 173 gr.DrawTextCentered (x + x0, y + y0, str3); 174 } 175 Draw(CairoContextEx gr, int area_width, int area_height, bool rtl)176 public override void Draw (CairoContextEx gr, int area_width, int area_height, bool rtl) 177 { 178 double x = DrawAreaX + 0.2, y = DrawAreaY; 179 double x0, y0, degrees; 180 int pos; 181 182 base.Draw (gr, area_width, area_height, rtl); 183 184 gr.Arc (x + arc_centerx, y + arc_centery, radius, 0, 2 * Math.PI); 185 gr.Stroke (); 186 187 for (int slice = 0; slice < total_slices; slice++) 188 { 189 degrees = radian * slice * (360 / total_slices); 190 gr.MoveTo (x + arc_centerx, y + arc_centery); 191 gr.LineTo (x + arc_centerx + (radius * Math.Cos (degrees)), y + arc_centery + (radius * Math.Sin (degrees))); 192 193 if (slice > total_slices - 1) continue; 194 195 if (slice == 0) { 196 degrees = radian * (slice * ((360 / total_slices)) + (360 / 12)); 197 x0 = 0.5 * radius * Math.Cos (degrees); 198 y0 = 0.5 * radius * Math.Sin (degrees); 199 gr.DrawTextCentered (x + arc_centerx + x0, y + arc_centery + y0, "?"); 200 continue; 201 } 202 203 if (slice < half_slices) { 204 pos = random_indices [slice]; 205 DrawSliceText (gr, x + arc_centerx, y + arc_centery, slice, (sum_offset + slices [pos * items_per_slice]).ToString (), 206 (sum_offset + slices [1 + (pos * items_per_slice)]).ToString (), (sum_offset + slices [2 + (pos * items_per_slice)]).ToString ()); 207 } 208 else { 209 pos = random_indices [slice - half_slices]; 210 DrawSliceText (gr, x + arc_centerx, y + arc_centery, slice, slices_opposite [pos * items_per_slice].ToString (), 211 slices_opposite [2 + (pos * items_per_slice)].ToString (), slices_opposite [1 + (pos * items_per_slice)].ToString ()); 212 } 213 } 214 215 gr.MoveTo (0.1, 0.55); 216 gr.ShowPangoText (Translations.GetString ("Choose one of the following:")); 217 gr.Stroke (); 218 } 219 } 220 } 221