aboutsummaryrefslogtreecommitdiff
path: root/utils.js
diff options
context:
space:
mode:
authorFederico Igne <git@federicoigne.com>2022-08-13 11:33:30 +0100
committerFederico Igne <git@federicoigne.com>2022-08-13 11:33:30 +0100
commit2fd9cc46ff2428bb2fa891f47002e9d3e7585583 (patch)
tree81b8b0122a00e9cd06d5f55091a3b087e430ddb0 /utils.js
downloadrubik-2fd9cc46ff2428bb2fa891f47002e9d3e7585583.tar.gz
rubik-2fd9cc46ff2428bb2fa891f47002e9d3e7585583.zip
init: import project
Diffstat (limited to 'utils.js')
-rwxr-xr-xutils.js276
1 files changed, 276 insertions, 0 deletions
diff --git a/utils.js b/utils.js
new file mode 100755
index 0000000..f92d48f
--- /dev/null
+++ b/utils.js
@@ -0,0 +1,276 @@
1
2"use strict";
3
4// Cleans the scene and spawns an instance of a cube (also updates
5// the cubies map).
6function buildCube(data)
7{
8 clearCubies(scene);
9 cubies.clear();
10
11 // Solved configuration
12 cubies.set(0, new Cubie(0,0,[{ key: 0, value: data[0][0] },{ key: 2, value: data[0][1] },{ key: 4, value: data[0][2] }]));
13 cubies.set(1, new Cubie(1,1,[{ key: 0, value: data[1][0] },{ key: 2, value: data[1][1] },{ key: 5, value: data[1][2] }]));
14 cubies.set(2, new Cubie(2,2,[{ key: 1, value: data[2][0] },{ key: 2, value: data[2][1] },{ key: 5, value: data[2][2] }]));
15 cubies.set(3, new Cubie(3,3,[{ key: 1, value: data[3][0] },{ key: 2, value: data[3][1] },{ key: 4, value: data[3][2] }]));
16 cubies.set(4, new Cubie(4,4,[{ key: 0, value: data[4][0] },{ key: 3, value: data[4][1] },{ key: 4, value: data[4][2] }]));
17 cubies.set(5, new Cubie(5,5,[{ key: 0, value: data[5][0] },{ key: 3, value: data[5][1] },{ key: 5, value: data[5][2] }]));
18 cubies.set(6, new Cubie(6,6,[{ key: 1, value: data[6][0] },{ key: 3, value: data[6][1] },{ key: 5, value: data[6][2] }]));
19 cubies.set(7, new Cubie(7,7,[{ key: 1, value: data[7][0] },{ key: 3, value: data[7][1] },{ key: 4, value: data[7][2] }]));
20
21 // Adding cubies to scene
22 for (var i = 0; i < cubies.size; i++)
23 {
24 scene.add(cubies.get(i).mesh);
25 }
26
27 needsRender = true;
28}
29
30var solvedConfig = [
31 ["white", "green", "red"],
32 ["white", "green", "orange"],
33 ["yellow", "green", "orange"],
34 ["yellow", "green", "red"],
35 ["white", "blue", "red"],
36 ["white", "blue", "orange"],
37 ["yellow", "blue", "orange"],
38 ["yellow", "blue", "red"],
39 ];
40
41function solvedCube()
42{
43 buildCube(solvedConfig);
44}
45
46function scramble()
47{
48 var moves = [];
49 var rotations = ["pitchA", "pitchB", "rollA", "rollB", "yawA", "yawB"];
50
51 for(var i = 0; i < Math.random()*10+10; i++)
52 {
53 moves.push({ move: rotations[Math.floor(Math.random() * rotations.length)], dir: (Math.random() < 0.5) ? 1 : -1 });
54 }
55
56 if (! animator)
57 {
58 scramb = true;
59 animator = new Animator(moves);
60 animator.goOn();
61 }
62}
63
64
65function clearCubies(node)
66{
67 cubies.forEach(function(value)
68 {
69 node.remove(value.mesh);
70 });
71}
72
73// Get the contents of the file "fname".
74// Returns an object with two attributes:
75// - succeeded: true if the function was able to retrieve the file.
76// - contents: the contents retrieved or an empty string.
77function getFileContents(fname) {
78 /*
79 // Request file content via HTTP's GET request
80 var xmlhttp = new XMLHttpRequest();
81 xmlhttp.responseType = "text/plain"; // Content is not XML!
82
83 xmlhttp.open("GET", "file:\\\\" + fname, false);
84
85 // NOTE: This can take some time if the server is remote
86 // which means the UI might freeze for some time...
87 xmlhttp.send();
88
89 var status = true;
90 var contents = "";
91
92 if (xmlhttp.status != 200) {
93 status = false;
94 }
95 else
96 {
97 contents = xmlhttp.responseText;
98 }
99
100 return {succeeded: status, contents: contents};
101 */
102}
103
104function loadShaders()
105{
106 var tmp,vs,fs;
107
108 tmp = getFileContents("vs.glsl");
109 if (!tmp.succeeded)
110 {
111 window.alert('Failed to load Blinn-Phong vertex shader: vs.glsl');
112 }
113 vs = tmp.contents;
114
115 tmp = getFileContents("fs.glsl");
116 if (!tmp.succeeded)
117 {
118 window.alert('Failed to load Blinn-Phong fragment shader: fs.glsl');
119 }
120 fs = tmp.contents;
121
122 return { vertex: vs, fragment: fs };
123}
124
125// Updates position after a complete animation.
126// Don't touch it, if you can't understand it!
127function updatePositions()
128{
129 scene.remove(face);
130
131 var temp = cubies.get(current_animation.cubies[0]);
132 for(var i = 0; Math.abs(i) < 4; i += current_animation.dir)
133 {
134 var keys, colors;
135 var c_new, c_old = temp;
136 switch (current_animation.cubies[mod(i+current_animation.dir,4)])
137 {
138 case 0: keys = [0,2,4]; break;
139 case 1: keys = [0,2,5]; break;
140 case 2: keys = [1,2,5]; break;
141 case 3: keys = [1,2,4]; break;
142 case 4: keys = [0,3,4]; break;
143 case 5: keys = [0,3,5]; break;
144 case 6: keys = [1,3,5]; break;
145 case 7: keys = [1,3,4]; break;
146 }
147 switch (current_animation.name)
148 {
149 case "pitch": colors = [0,2,1]; break;
150 case "roll": colors = [1,0,2]; break;
151 case "yaw": colors = [2,1,0]; break;
152 }
153 c_new = new Cubie(c_old.key,
154 current_animation.cubies[mod(i+current_animation.dir,4)],
155 [{ key: keys[0], value: c_old.colors[colors[0]].value },
156 { key: keys[1], value: c_old.colors[colors[1]].value },
157 { key: keys[2], value: c_old.colors[colors[2]].value }
158 ]);
159 temp = cubies.get(current_animation.cubies[mod(i+current_animation.dir,4)]);
160 cubies.set(current_animation.cubies[mod(i+current_animation.dir,4)], c_new);
161 scene.add(c_new.mesh);
162 }
163
164 needsRender = true
165}
166
167// Right module operator.
168// Beware the Javascript module! (it doesn't work with negative integers)
169function mod(n, m)
170{
171 return ((n % m) + m) % m;
172}
173
174// Open a local file.
175function selectFile(loop)
176{
177 var element = document.createElement('div');
178 element.innerHTML = '<input type="file">';
179 var fileInput = element.firstChild;
180
181 fileInput.addEventListener('change', function() {
182 var file = fileInput.files[0];
183 if (file.name.match(/\.(txt)$/))
184 {
185 var reader = new FileReader();
186 reader.onload = function() {
187 var data = parseData(reader.result);
188 buildCube(data.cube);
189 if (data.solutions[0].length > 0) {
190 animator = new Animator(data.solutions[0]);
191 animator.goOn();
192 }
193 };
194 reader.readAsText(file);
195 } else {
196 alert("File not supported, .txt files only");
197 }
198 });
199
200 fileInput.click();
201}
202
203function saveToFile(filename, content) {
204 var elem = document.createElement('a');
205 elem.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(content));
206 elem.setAttribute('download', filename);
207
208 document.body.appendChild(elem);
209 elem.click();
210 document.body.removeChild(elem);
211}
212
213// Parse a local file
214function parseData(text)
215{
216 var data = [], instance;
217 var moves = [], predicates;
218 var i = -1, pred;
219 var lines = text.split("\n");
220
221 instance = new Array(8);
222
223 // Look for the first line with an answer
224 while(lines[++i].search(/Answer:/g) !== 0) { }
225 // Parse answers
226 while(i < lines.length && lines[i++].search(/Answer:/g) === 0)
227 {
228 predicates = lines[i++].split(" ");
229
230 pred = predicates[predicates.length-1];
231 if (pred.search(/solved/i) === 0) {
232 moves = new Array(parseInt(pred.substring(pred.indexOf("(") + 1,pred.indexOf(")"))));
233 }
234
235 for(var j = 0; j < predicates.length; j++)
236 {
237 pred = predicates[j].split(",");
238
239 if(predicates[j].search(/move/i) === 0)
240 {
241 switch (pred[1])
242 {
243 case "pitch": var move = (parseInt(pred[2]) == 0) ? "pitchA" : "pitchB"; break;
244 case "roll": var move = (parseInt(pred[2]) == 0) ? "rollA" : "rollB"; break;
245 case "yaw": var move = (parseInt(pred[2]) == 0) ? "yawA" : "yawB"; break;
246 }
247
248 var ind = parseInt(pred[0].substring(pred[0].indexOf("(")+1));
249 if(ind < moves.length)
250 {
251 moves[ind] =
252 {
253 move: move,
254 dir: parseInt(pred[3].substr(0,pred[3].length-1))
255 };
256 }
257
258 } else if(predicates[j].search(/is/i) === 0) {
259
260 if(parseInt(pred[0].substring(pred[0].indexOf("(")+1)) === 0)
261 {
262 instance[parseInt(pred[1])] = [
263 pred[2],
264 pred[3],
265 pred[4].substr(0,pred[4].length-1)
266 ];
267 }
268 }
269
270 }
271
272 data.push(moves);
273 }
274
275 return { cube: instance, solutions: data };
276}