Changeset View
Changeset View
Standalone View
Standalone View
src/activities/ascending_order/ascending_order.js
- This file was added.
1 | /* GCompris - ascending_order.js | ||||
---|---|---|---|---|---|
2 | * | ||||
3 | * Copyright (C) 2016 Rudra Nil Basu <rudra.nil.basu.1996@gmail.com> | ||||
4 | * | ||||
5 | * Authors: | ||||
6 | * Rudra Nil Basu <rudra.nil.basu.1996@gmail.com> (Qt Quick port) | ||||
7 | * | ||||
8 | * This program is free software; you can redistribute it and/or modify | ||||
9 | * it under the terms of the GNU General Public License as published by | ||||
10 | * the Free Software Foundation; either version 3 of the License, or | ||||
11 | * (at your option) any later version. | ||||
12 | * | ||||
13 | * This program is distributed in the hope that it will be useful, | ||||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
16 | * GNU General Public License for more details. | ||||
17 | * | ||||
18 | * You should have received a copy of the GNU General Public License | ||||
19 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
20 | */ | ||||
21 | .pragma library | ||||
22 | .import QtQuick 2.0 as Quick | ||||
23 | | ||||
24 | var currentLevel = 0 | ||||
25 | var numberOfLevel = 4 | ||||
26 | | ||||
27 | var items | ||||
28 | var mode | ||||
29 | | ||||
30 | // num[] will contain the random numbers | ||||
31 | var num = [] | ||||
32 | var originalArrangement = [] | ||||
33 | var alphabets = [] | ||||
34 | | ||||
35 | var ascendingOrder | ||||
36 | var thresholdDistance | ||||
37 | var noOfTilesInPreviousLevel | ||||
38 | | ||||
39 | function start(items_, mode_) { | ||||
40 | items = items_ | ||||
41 | mode = mode_ | ||||
42 | currentLevel = 0 | ||||
43 | items.flow.validMousePress = false | ||||
44 | thresholdDistance = 4000 * items.ratio | ||||
45 | items.score.currentSubLevel = 0 | ||||
46 | items.score.numberOfSubLevels = 4 | ||||
47 | | ||||
48 | if (mode == "alphabets") { | ||||
49 | //: list containing all the characters separated by a "/" | ||||
50 | var letters = qsTr("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z") | ||||
51 | alphabets = letters.split("/") | ||||
52 | } | ||||
53 | | ||||
54 | noOfTilesInPreviousLevel = -1 | ||||
55 | initLevel() | ||||
56 | } | ||||
57 | | ||||
58 | function stop() { | ||||
59 | } | ||||
60 | | ||||
61 | function initLevel() { | ||||
62 | ascendingOrder = items.score.currentSubLevel % 2 == 0 ? true : false | ||||
63 | items.instruction.text = ascendingOrder ? qsTr("Drag and drop the items in correct position in Ascending order") : qsTr("Drag and drop the items in correct position in Descending order") | ||||
64 | items.flow.validMousePress = true | ||||
65 | items.bar.level = currentLevel + 1 | ||||
66 | initGrids() | ||||
67 | } | ||||
68 | | ||||
69 | function initGrids() { | ||||
70 | items.boxes.model = 2 * (items.bar.level)+1 | ||||
71 | | ||||
72 | if(noOfTilesInPreviousLevel != items.boxes.model) { | ||||
73 | /* | ||||
74 | * When the tiles don't automatically rearrange themself | ||||
75 | * manually check the marker off | ||||
76 | */ | ||||
77 | items.flow.onGoingAnimationCount = 0 | ||||
78 | noOfTilesInPreviousLevel = items.boxes.model | ||||
79 | } else { | ||||
80 | restoreGrids() | ||||
81 | } | ||||
82 | | ||||
83 | generateRandomNumbers() | ||||
84 | | ||||
85 | for(var i = 0;i < items.boxes.model;i++) { | ||||
86 | if (mode == "number") { | ||||
87 | items.boxes.itemAt(i).boxValue = num[i].toString() | ||||
88 | } else if (mode == "alphabets") { | ||||
89 | items.boxes.itemAt(i).boxValue = num[i] | ||||
90 | } | ||||
91 | } | ||||
92 | } | ||||
93 | | ||||
94 | function generateRandomNumbers() { | ||||
95 | var n = items.boxes.model | ||||
96 | // generate n random numbers and store it in num[] | ||||
97 | num = [] | ||||
98 | var upperBound | ||||
99 | var lowerBound | ||||
100 | if(mode == "number") { | ||||
101 | upperBound = (items.bar.level)*100 | ||||
102 | lowerBound = 0 | ||||
103 | } else if(mode == "alphabets") { | ||||
104 | upperBound = alphabets.length -1 | ||||
105 | lowerBound = 0 | ||||
106 | } | ||||
107 | while(num.length < n) { | ||||
108 | var randomNumber = Math.ceil(Math.random() * (upperBound - lowerBound) + lowerBound) | ||||
109 | if (( mode == "number" && num.indexOf(randomNumber) > -1) || ( mode == "alphabets" && num.indexOf(alphabets[randomNumber]) > -1)) { | ||||
110 | continue; | ||||
111 | } | ||||
112 | if (mode == "number") { | ||||
113 | num[num.length] = randomNumber | ||||
114 | } else if (mode == "alphabets") { | ||||
115 | num[num.length] = alphabets[randomNumber] | ||||
116 | } | ||||
117 | } | ||||
118 | for(var i = 0;i < num.length;i++) { | ||||
119 | originalArrangement[i] = num[i] | ||||
120 | } | ||||
121 | } | ||||
122 | | ||||
123 | function restoreGrids() { | ||||
124 | /* Restore the grid positions */ | ||||
125 | /* | ||||
126 | * To make sure that the flow is properly indexed | ||||
127 | * before moving on to the next sub level. | ||||
128 | * This is required since if the previous level and | ||||
129 | * current level has the same number of tiles, the | ||||
130 | * indices are not automatically rearranged | ||||
131 | */ | ||||
132 | for(var i = 0;i < items.boxes.model;i++) { | ||||
133 | if(num[i] === originalArrangement[i]) { | ||||
134 | continue | ||||
135 | } | ||||
136 | var currentBlock = findBlockWithLabel(originalArrangement[i]) | ||||
137 | var finalPosition = findBlockWithLabel(num[i]) | ||||
138 | currentBlock.x = finalPosition.x | ||||
139 | currentBlock.y = finalPosition.y | ||||
140 | } | ||||
141 | } | ||||
142 | | ||||
143 | function nextSubLevel() { | ||||
144 | if(items.score.numberOfSubLevels <= ++items.score.currentSubLevel) { | ||||
145 | if(numberOfLevel <= ++currentLevel) { | ||||
146 | currentLevel = 0 | ||||
147 | } | ||||
148 | items.score.currentSubLevel = 0 | ||||
149 | } | ||||
150 | initLevel(); | ||||
151 | } | ||||
152 | | ||||
153 | function nextLevel() { | ||||
154 | if(numberOfLevel <= ++currentLevel) { | ||||
155 | currentLevel = 0 | ||||
156 | } | ||||
157 | items.score.currentSubLevel = 0 | ||||
158 | initLevel() | ||||
159 | } | ||||
160 | | ||||
161 | function previousLevel() { | ||||
162 | if(--currentLevel < 0) { | ||||
163 | currentLevel = numberOfLevel - 1 | ||||
164 | } | ||||
165 | items.score.currentSubLevel = 0 | ||||
166 | initLevel() | ||||
167 | } | ||||
168 | | ||||
169 | function checkOrder() { | ||||
170 | items.flow.validMousePress = false | ||||
171 | for(var i = 0;i < items.boxes.count-1;i++) { | ||||
172 | if( ascendingOrder && ( ( mode == "number" && num[i] > num[i+1]) || (mode == "alphabets" && alphabets.indexOf(num[i]) > alphabets.indexOf(num[i+1]))) ) { | ||||
173 | items.bonus.bad("lion") | ||||
174 | items.flow.validMousePress = true | ||||
175 | return | ||||
176 | } | ||||
177 | if( !ascendingOrder && ( (mode == "number" && num[i] < num[i+1]) || (mode == "alphabets" && alphabets.indexOf(num[i]) < alphabets.indexOf(num[i+1]))) ) { | ||||
178 | items.bonus.bad("lion") | ||||
179 | items.flow.validMousePress = true | ||||
180 | return | ||||
181 | } | ||||
182 | } | ||||
183 | items.bonus.good("lion") | ||||
184 | } | ||||
185 | | ||||
186 | function placeBlock(box, initialPosition) { | ||||
187 | /* | ||||
188 | * find shortest distance from box to other nodes | ||||
189 | * if distance <= threshold distance then put box | ||||
190 | * in that block and that block in "initialPosition" | ||||
191 | */ | ||||
192 | var minDistance = Number.POSITIVE_INFINITY | ||||
193 | var closestBlock | ||||
194 | for(var i = 0;i < items.boxes.model;i++) { | ||||
195 | var currentBlock = items.boxes.itemAt(i) | ||||
196 | if(currentBlock.boxValue === box.boxValue) { | ||||
197 | continue | ||||
198 | } else { | ||||
199 | var blockDistance = distance(box, currentBlock) | ||||
200 | if( blockDistance < minDistance ) { | ||||
201 | minDistance = blockDistance | ||||
202 | closestBlock = currentBlock | ||||
203 | } | ||||
204 | } | ||||
205 | } | ||||
206 | | ||||
207 | if(minDistance < thresholdDistance) { | ||||
208 | | ||||
209 | var item1Pos = -1 | ||||
210 | var item2Pos = num.indexOf(closestBlock.boxValue) | ||||
211 | for (var i = 0;i < num.length; i++) { | ||||
212 | /* | ||||
213 | * var item1Pos = num.indexOf(box.boxValue) | ||||
214 | * var item2Pos = num.indexOf(closestBlock.boxValue) | ||||
215 | * was NOT used since the boxValue is of string type | ||||
216 | * and it will return -1 when strictly compared with | ||||
217 | * int | ||||
218 | */ | ||||
219 | if (box.boxValue == num[i]) { | ||||
220 | item1Pos = i | ||||
221 | } | ||||
222 | if (closestBlock.boxValue == num[i]) { | ||||
223 | item2Pos = i | ||||
224 | } | ||||
225 | } | ||||
226 | | ||||
227 | var oldPositions = [] | ||||
228 | var newPositions = [] | ||||
229 | | ||||
230 | for(var i = 0;i < num.length;i++) { | ||||
231 | oldPositions[i] = num[i] | ||||
232 | newPositions[i] = num[i] | ||||
233 | } | ||||
234 | | ||||
235 | if(item1Pos > item2Pos) { | ||||
236 | // update new position | ||||
237 | var currentBoxValue = newPositions[item1Pos] | ||||
238 | for(var i = item1Pos;i > item2Pos;i--) { | ||||
239 | newPositions[i] = newPositions[i-1] | ||||
240 | } | ||||
241 | newPositions[item2Pos] = currentBoxValue | ||||
242 | } else { | ||||
243 | // update new position | ||||
244 | var currentBoxValue = newPositions[item1Pos] | ||||
245 | for(var i = item1Pos;i < item2Pos;i++) { | ||||
246 | newPositions[i] = newPositions[i+1]; | ||||
247 | } | ||||
248 | newPositions[item2Pos] = currentBoxValue | ||||
249 | } | ||||
250 | rearrange(oldPositions, newPositions, box, initialPosition) | ||||
251 | for(var i = 0;i < num.length;i++) { | ||||
252 | num[i] = newPositions[i] | ||||
253 | } | ||||
254 | } else { | ||||
255 | box.x = initialPosition.x | ||||
256 | box.y = initialPosition.y | ||||
257 | } | ||||
258 | } | ||||
259 | | ||||
260 | function rearrange(oldPositions, newPositions, movingBlock, initialPosition) { | ||||
261 | for(var i = 0;i < newPositions.length;i++) { | ||||
262 | if(oldPositions[i] === newPositions[i]) { | ||||
263 | continue | ||||
264 | } | ||||
265 | var currentBlock = findBlockWithLabel(newPositions[i]) | ||||
266 | var finalPosition = findBlockWithLabel(oldPositions[i]) | ||||
267 | if(finalPosition.boxValue == movingBlock.boxValue) { | ||||
268 | currentBlock.x = initialPosition.x | ||||
269 | currentBlock.y = initialPosition.y | ||||
270 | } else { | ||||
271 | currentBlock.x = finalPosition.x | ||||
272 | currentBlock.y = finalPosition.y | ||||
273 | } | ||||
274 | } | ||||
275 | } | ||||
276 | | ||||
277 | function findBlockWithLabel(label) { | ||||
278 | for(var i = 0;i < items.boxes.model;i++) { | ||||
279 | if(items.boxes.itemAt(i).boxValue == label) { | ||||
280 | return items.boxes.itemAt(i) | ||||
281 | } | ||||
282 | } | ||||
283 | } | ||||
284 | | ||||
285 | function distance(box, currentBlock) { | ||||
286 | return Math.pow((box.x-currentBlock.x),2) + Math.pow((box.y-currentBlock.y),2) | ||||
287 | } |