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 | items.hints.text = letters | ||||
52 | alphabets = letters.split("/") | ||||
53 | } | ||||
54 | | ||||
55 | noOfTilesInPreviousLevel = -1 | ||||
56 | initLevel() | ||||
57 | } | ||||
58 | | ||||
59 | function stop() { | ||||
60 | } | ||||
61 | | ||||
62 | function initLevel() { | ||||
63 | ascendingOrder = items.orderMode === 0 ? true : false | ||||
64 | 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") | ||||
65 | items.flow.validMousePress = true | ||||
66 | items.bar.level = currentLevel + 1 | ||||
67 | initGrids() | ||||
68 | } | ||||
69 | | ||||
70 | function initGrids() { | ||||
71 | items.boxes.model = 2 * (items.bar.level)+1 | ||||
72 | | ||||
73 | if(noOfTilesInPreviousLevel != items.boxes.model) { | ||||
74 | /* | ||||
75 | * When the tiles don't automatically rearrange themself | ||||
76 | * manually check the marker off | ||||
77 | */ | ||||
78 | items.flow.onGoingAnimationCount = 0 | ||||
79 | noOfTilesInPreviousLevel = items.boxes.model | ||||
80 | } else { | ||||
81 | restoreGrids() | ||||
82 | } | ||||
83 | | ||||
84 | generateRandomNumbers() | ||||
85 | | ||||
86 | for(var i = 0;i < items.boxes.model;i++) { | ||||
87 | if (mode == "number") { | ||||
88 | items.boxes.itemAt(i).boxValue = num[i].toString() | ||||
89 | } else if (mode == "alphabets") { | ||||
90 | items.boxes.itemAt(i).boxValue = num[i] | ||||
91 | } | ||||
92 | } | ||||
93 | } | ||||
94 | | ||||
95 | function generateRandomNumbers() { | ||||
96 | var n = items.boxes.model | ||||
97 | // generate n random numbers and store it in num[] | ||||
98 | num = [] | ||||
99 | var upperBound | ||||
100 | var lowerBound | ||||
101 | if(mode == "number") { | ||||
102 | upperBound = (items.bar.level)*100 | ||||
103 | lowerBound = 0 | ||||
104 | } else if(mode == "alphabets") { | ||||
105 | upperBound = alphabets.length -1 | ||||
106 | lowerBound = 0 | ||||
107 | } | ||||
108 | while(num.length < n) { | ||||
109 | var randomNumber = Math.ceil(Math.random() * (upperBound - lowerBound) + lowerBound) | ||||
110 | if (( mode == "number" && num.indexOf(randomNumber) > -1) || ( mode == "alphabets" && num.indexOf(alphabets[randomNumber]) > -1)) { | ||||
111 | continue; | ||||
112 | } | ||||
113 | if (mode == "number") { | ||||
114 | num[num.length] = randomNumber | ||||
115 | } else if (mode == "alphabets") { | ||||
116 | num[num.length] = alphabets[randomNumber] | ||||
117 | } | ||||
118 | } | ||||
119 | for(var i = 0;i < num.length;i++) { | ||||
120 | originalArrangement[i] = num[i] | ||||
121 | } | ||||
122 | } | ||||
123 | | ||||
124 | function restoreGrids() { | ||||
125 | /* Restore the grid positions */ | ||||
126 | /* | ||||
127 | * To make sure that the flow is properly indexed | ||||
128 | * before moving on to the next sub level. | ||||
129 | * This is required since if the previous level and | ||||
130 | * current level has the same number of tiles, the | ||||
131 | * indices are not automatically rearranged | ||||
132 | */ | ||||
133 | for(var i = 0;i < items.boxes.model;i++) { | ||||
134 | if(num[i] === originalArrangement[i]) { | ||||
135 | continue | ||||
136 | } | ||||
137 | var currentBlock = findBlockWithLabel(originalArrangement[i]) | ||||
138 | var finalPosition = findBlockWithLabel(num[i]) | ||||
139 | currentBlock.x = finalPosition.x | ||||
140 | currentBlock.y = finalPosition.y | ||||
141 | } | ||||
142 | } | ||||
143 | | ||||
144 | function nextSubLevel() { | ||||
145 | if(items.score.numberOfSubLevels <= ++items.score.currentSubLevel) { | ||||
146 | if(numberOfLevel <= ++currentLevel) { | ||||
147 | currentLevel = 0 | ||||
148 | } | ||||
149 | items.score.currentSubLevel = 0 | ||||
150 | } | ||||
151 | initLevel(); | ||||
152 | } | ||||
153 | | ||||
154 | function nextLevel() { | ||||
155 | if(numberOfLevel <= ++currentLevel) { | ||||
156 | currentLevel = 0 | ||||
157 | } | ||||
158 | items.score.currentSubLevel = 0 | ||||
159 | initLevel() | ||||
160 | } | ||||
161 | | ||||
162 | function previousLevel() { | ||||
163 | if(--currentLevel < 0) { | ||||
164 | currentLevel = numberOfLevel - 1 | ||||
165 | } | ||||
166 | items.score.currentSubLevel = 0 | ||||
167 | initLevel() | ||||
168 | } | ||||
169 | | ||||
170 | function checkOrder() { | ||||
171 | items.flow.validMousePress = false | ||||
172 | for(var i = 0;i < items.boxes.count-1;i++) { | ||||
173 | if( ascendingOrder && ( ( mode == "number" && num[i] > num[i+1]) || (mode == "alphabets" && alphabets.indexOf(num[i]) > alphabets.indexOf(num[i+1]))) ) { | ||||
174 | items.bonus.bad("lion") | ||||
175 | items.flow.validMousePress = true | ||||
176 | return | ||||
177 | } | ||||
178 | if( !ascendingOrder && ( (mode == "number" && num[i] < num[i+1]) || (mode == "alphabets" && alphabets.indexOf(num[i]) < alphabets.indexOf(num[i+1]))) ) { | ||||
179 | items.bonus.bad("lion") | ||||
180 | items.flow.validMousePress = true | ||||
181 | return | ||||
182 | } | ||||
183 | } | ||||
184 | items.bonus.good("lion") | ||||
185 | } | ||||
186 | | ||||
187 | function placeBlock(box, initialPosition) { | ||||
188 | /* | ||||
189 | * find shortest distance from box to other nodes | ||||
190 | * if distance <= threshold distance then put box | ||||
191 | * in that block and that block in "initialPosition" | ||||
192 | */ | ||||
193 | var minDistance = Number.POSITIVE_INFINITY | ||||
194 | var closestBlock | ||||
195 | for(var i = 0;i < items.boxes.model;i++) { | ||||
196 | var currentBlock = items.boxes.itemAt(i) | ||||
197 | if(currentBlock.boxValue === box.boxValue) { | ||||
198 | continue | ||||
199 | } else { | ||||
200 | var blockDistance = distance(box, currentBlock) | ||||
201 | if( blockDistance < minDistance ) { | ||||
202 | minDistance = blockDistance | ||||
203 | closestBlock = currentBlock | ||||
204 | } | ||||
205 | } | ||||
206 | } | ||||
207 | | ||||
208 | if(minDistance < thresholdDistance) { | ||||
209 | | ||||
210 | var item1Pos = -1 | ||||
211 | var item2Pos = num.indexOf(closestBlock.boxValue) | ||||
212 | for (var i = 0;i < num.length; i++) { | ||||
213 | /* | ||||
214 | * var item1Pos = num.indexOf(box.boxValue) | ||||
215 | * var item2Pos = num.indexOf(closestBlock.boxValue) | ||||
216 | * was NOT used since the boxValue is of string type | ||||
217 | * and it will return -1 when strictly compared with | ||||
218 | * int | ||||
219 | */ | ||||
220 | if (box.boxValue == num[i]) { | ||||
221 | item1Pos = i | ||||
222 | } | ||||
223 | if (closestBlock.boxValue == num[i]) { | ||||
224 | item2Pos = i | ||||
225 | } | ||||
226 | } | ||||
227 | | ||||
228 | var oldPositions = [] | ||||
229 | var newPositions = [] | ||||
230 | | ||||
231 | for(var i = 0;i < num.length;i++) { | ||||
232 | oldPositions[i] = num[i] | ||||
233 | newPositions[i] = num[i] | ||||
234 | } | ||||
235 | | ||||
236 | if(item1Pos > item2Pos) { | ||||
237 | // update new position | ||||
238 | var currentBoxValue = newPositions[item1Pos] | ||||
239 | for(var i = item1Pos;i > item2Pos;i--) { | ||||
240 | newPositions[i] = newPositions[i-1] | ||||
241 | } | ||||
242 | newPositions[item2Pos] = currentBoxValue | ||||
243 | } else { | ||||
244 | // update new position | ||||
245 | var currentBoxValue = newPositions[item1Pos] | ||||
246 | for(var i = item1Pos;i < item2Pos;i++) { | ||||
247 | newPositions[i] = newPositions[i+1]; | ||||
248 | } | ||||
249 | newPositions[item2Pos] = currentBoxValue | ||||
250 | } | ||||
251 | rearrange(oldPositions, newPositions, box, initialPosition) | ||||
252 | for(var i = 0;i < num.length;i++) { | ||||
253 | num[i] = newPositions[i] | ||||
254 | } | ||||
255 | } else { | ||||
256 | box.x = initialPosition.x | ||||
257 | box.y = initialPosition.y | ||||
258 | } | ||||
259 | } | ||||
260 | | ||||
261 | function rearrange(oldPositions, newPositions, movingBlock, initialPosition) { | ||||
262 | for(var i = 0;i < newPositions.length;i++) { | ||||
263 | if(oldPositions[i] === newPositions[i]) { | ||||
264 | continue | ||||
265 | } | ||||
266 | var currentBlock = findBlockWithLabel(newPositions[i]) | ||||
267 | var finalPosition = findBlockWithLabel(oldPositions[i]) | ||||
268 | if(finalPosition.boxValue == movingBlock.boxValue) { | ||||
269 | currentBlock.x = initialPosition.x | ||||
270 | currentBlock.y = initialPosition.y | ||||
271 | } else { | ||||
272 | currentBlock.x = finalPosition.x | ||||
273 | currentBlock.y = finalPosition.y | ||||
274 | } | ||||
275 | } | ||||
276 | } | ||||
277 | | ||||
278 | function findBlockWithLabel(label) { | ||||
279 | for(var i = 0;i < items.boxes.model;i++) { | ||||
280 | if(items.boxes.itemAt(i).boxValue == label) { | ||||
281 | return items.boxes.itemAt(i) | ||||
282 | } | ||||
283 | } | ||||
284 | } | ||||
285 | | ||||
286 | function distance(box, currentBlock) { | ||||
287 | return Math.pow((box.x-currentBlock.x),2) + Math.pow((box.y-currentBlock.y),2) | ||||
288 | } |