-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
428 lines (360 loc) · 14.2 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="stylesheet.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- <script type="text/javascript" src="ca.js"></script> -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-39554842-1', 'auto');
ga('send', 'pageview');
</script>
<script>
/*Set up JQuery Variables for the two different boxes:*/
var boxOff=$("<div class=\"buttonOff1\"></div>");
var boxOn=$("<div class=\"buttonOn1\"></div>");
/* Defining what happens when a box is clicked */
boxOff.click(function(){
if (!running){
/* The box classes depend on the color scheme determined by the user */
switch (colors){
case 1:
$(this).toggleClass('buttonOn1 buttonOff1');
break;
case 2:
$(this).toggleClass('buttonOn2 buttonOff2');
break;
case 3:
$(this).toggleClass('buttonOn3 buttonOff3');
break;
case 4:
$(this).toggleClass('buttonOn4 buttonOff4');
break;
}
}
});
/* This is just like the above click function, but for boxes that were already toggled on */
boxOn.click(function(){
if (!running){
switch (colors){
case 1:
$(this).toggleClass('buttonOn1 buttonOff1');
break;
case 2:
$(this).toggleClass('buttonOn2 buttonOff2');
break;
case 3:
$(this).toggleClass('buttonOn3 buttonOff3');
break;
case 4:
$(this).toggleClass('buttonOn4 buttonOff4');
break;
}
}
});
/* Global values */
var running=false;
var colors=1;
/* This produces the default off columns based on the number of columns specified */
function defaultCols(colNumber){
for (var vectorIndex=0; vectorIndex<colNumber; vectorIndex++){
$('.userInputRow').append(boxOff.clone(true));
}
/* To keep the css pretty: */
$('.userInputRow > div:first').css('margin-left', '0px');
$('.userInputRow > div:last').css('margin-right', '0px');
}
/* This function is called when the user clicks select all. It toggles all boxes to on */
function selectAll(){
$('.userInputRow').empty();
for (var vectorIndex=0; vectorIndex<(parseInt($("#cols").val())); vectorIndex++){
$('.userInputRow').append(boxOn.clone(true));
}
/* To keep the css pretty: */
$('.userInputRow > div:first').css('margin-left', '0px');
$('.userInputRow > div:last').css('margin-right', '0px');
}
/* This function is called when the user clicks clear, or when the color scheme is changed. It toggles all boxes to off */
function clearAll(){
$('.userInputRow').empty();
defaultCols(parseInt($("#cols").val()));
}
/* This function stops the animation stepping when the user clicks the stop animation button during an animation */
function stopAnimate(){
/* Stop all currently running timeouts*/
var allTimeouts = window.setTimeout(function() {}, 0);
while (allTimeouts--) {
window.clearTimeout(allTimeouts);
}
/* Then reset all buttions, since we won't get to the last timeout that does this */
$("#submitButton").removeAttr('disabled');
$("#rows").removeAttr('disabled');
$("#ruleNo").removeAttr('disabled');
$("#cols").removeAttr('disabled');
$("#animate").removeAttr('disabled');
$("#stopAnimateButton").hide()
$("#clearAllButton").show();
$("#selectAllButton").show();
running=false;
}
/* This function is called when the user changes the number of desired columns */
function changeCols(colNumber){
/* To keep the css pretty: */
$('.userInputRow > div:first').css('margin-left', '2px');
$('.userInputRow > div:last').css('margin-right', '2px');
/* First count the current number of cols: */
var oldColNumber=$('.userInputRow div').length;
/*Case we're increasing the number of columns:*/
if (oldColNumber<parseInt($('#cols').val())){
/* We want to build around the current boxes, in case the user has input */
for (var vectorIndex=0; vectorIndex<((colNumber-oldColNumber)/2); vectorIndex++){
$('.userInputRow').prepend(boxOff.clone(true));
$('.userInputRow').append(boxOff.clone(true));
}
}
/* Case we're decreasing the number of columns, we remove boxes around the center*/
else
for (var vectorIndex=0; vectorIndex<((oldColNumber-colNumber)/2); vectorIndex++){
$('.userInputRow > div:first').remove();
$('.userInputRow > div:last').remove();
}
/* To keep the css pretty: */
$('.userInputRow > div:first').css('margin-left', '0px');
$('.userInputRow > div:last').css('margin-right', '0px');
}
/* The next four functions are called when the color is changed. They toggle different classes of boxes that have the different color schemes. */
/* This is the blue/pink color scheme */
function changeColor1(){
colors=1;
boxOff.attr('class', 'buttonOff1');
boxOn.attr('class','buttonOn1');
clearAll();
}
/* This is the orange/blue color scheme */
function changeColor2(){
colors=2;
boxOff.attr('class','buttonOff2');
boxOn.attr('class','buttonOn2');
clearAll();
}
/* This is the yellow/green color scheme */
function changeColor3(){
colors=3;
boxOff.attr('class','buttonOff3');
boxOn.attr('class','buttonOn3');
clearAll();
}
/* This is the purple/black color scheme */
function changeColor4(){
colors=4;
boxOff.attr('class','buttonOff4');
boxOn.attr('class','buttonOn4');
clearAll();
}
/*This submitClick function is called when the user hits the button, and calls the encryption python script */
function submitClick(){
// alert("clicked!");
/* First clear out the current rows */
$('.outputRows').empty();
$('.outputRows').append('<p>Encrypting...</p>');
var input="";
var animateBool=false;
var numRows=$('#rows').val();
var ruleNumber=$('#ruleNo').val();
// alert(numRows);
/*We need to determine the input to the python script based on what the user clicked*/
var inputBoxes=$('.userInputRow > div');
/*Loop though each of the input boxes*/
// alert("here!");
// alert(inputBoxes.length);
for (inputIndex=0; inputIndex<inputBoxes.length; inputIndex++){
/*Case that it's a zero...cell is off*/
if (inputBoxes[inputIndex].className=='buttonOff1' || inputBoxes[inputIndex].className=='buttonOff2' || inputBoxes[inputIndex].className=='buttonOff3' || inputBoxes[inputIndex].className=='buttonOff4')
input+="0";
// alert("case 1");
/*Case that it's a one...cell is on*/
if (inputBoxes[inputIndex].className=='buttonOn1' || inputBoxes[inputIndex].className=='buttonOn2' || inputBoxes[inputIndex].className=='buttonOn3' || inputBoxes[inputIndex].className=='buttonOn4')
input+="1";
// alert("case 2");
if (inputIndex!=inputBoxes.length-1)
input+=" ";
// alert("case 3");
}
// alert(ruleNumber);
/* This is so we can communicate with the python script */
var request = $.ajax({
url: "ca.py",
type: "GET",
data: {rule: ruleNumber, numSteps: numRows, inputVector: input},
dataType: "html",
})
.done(function(dat){/* alert("received:",dat) */});
// alert("request opened!");
/* When we're done communicating with the python script, this is where we are: */
request.done(function(msg) {
// alert("here!");
// alert(msg);
running=true;
/* We don't want the user to be able to change the inputs when the code is running: */
$("#submitButton").attr('disabled','disabled');
$("#rows").attr('disabled','disabled');
$("#ruleNo").attr('disabled','disabled');
$("#cols").attr('disabled','disabled');
$("#animate").attr('disabled','disabled');
/* Hide unncessary buttons */
$("#clearAllButton").hide();
$("#selectAllButton").hide();
/* Animation case */
if ($("#animateCheckbox").is(':checked')){
animateBool=true;
$("#stopAnimateButton").show()
}
/* Getting the output of the python code: */
// alert("here!");
// alert(vectorRows);
var vectorRows=msg.split("\n");
/*
alert(vectorRows);
alert(vectorRows.length);
*/
// var NLcount = 0;
var rowIndex=0;
$('.outputRows').empty();
/* This loops through each row of the output */
for (rowIndex=0; rowIndex<vectorRows.length; rowIndex++){
var vectorEntries=vectorRows[rowIndex];
// alert(vectorEntries);
/*This loops through each entry that was outputted in the current row*/
for (var entryIndex=0; entryIndex<vectorEntries.length; entryIndex++){
/* Case that it's a zero: */
if (vectorEntries[entryIndex]=="0"){
// alert("1 case");
if (animateBool){ /*animation requested*/
timeout0=setTimeout(function(){
$('.outputRows').append(boxOff.clone());
}, 500*(rowIndex+1));
}
else
$('.outputRows').append(boxOff.clone());
}
/* Case that it's a one: */
if (vectorEntries[entryIndex]=="1"){
if (animateBool){ /*animation requested*/
timeout1=setTimeout(function(){
$('.outputRows').append(boxOn.clone());
}, 500*(rowIndex+1));
}
else
$('.outputRows').append(boxOn.clone());
}
}
if (animateBool){/*animation requested*/
timeoutNewLine=setTimeout(function(){
$('.outputRows').append('<br>');
}, 500*(rowIndex+1));
}
else{
$('.outputRows').append('<br>');
}
// NLcount+=1;
}
// alert(NLcount);
/* Bring back everything we disabled before */
if (animateBool){/*animation requested*/
setTimeout(function(){
$("#submitButton").removeAttr('disabled');
$("#rows").removeAttr('disabled');
$("#ruleNo").removeAttr('disabled');
$("#cols").removeAttr('disabled');
$("#animate").removeAttr('disabled');
$("#stopAnimateButton").hide()
$("#clearAllButton").show();
$("#selectAllButton").show();
running=false;
}, 500*(rowIndex+1));
}
else{
$("#submitButton").removeAttr('disabled');
$("#rows").removeAttr('disabled');
$("#ruleNo").removeAttr('disabled');
$("#cols").removeAttr('disabled');
$("#animate").removeAttr('disabled');
$("#clearAllButton").show();
$("#selectAllButton").show();
running=false;
}
});
/* case that our communication with the python script didn't work */
request.fail(function(jqXHR, textStatus) {
alert( "Request failed: " + textStatus );
});
}
/***************************************************************/
/* Finally at the document ready function! */
$(document).ready(function(){
/* Set up the default settings: */
defaultCols(9);
$("#stopAnimateButton").hide()
/* This allows the user to press enter rather than the start encryption button while in the rule number form box */
$("input").keypress(function(event) {
if (event.which == 13 && $("#submitButton").attr('disabled')!='disabled') {
$("#submitButton").click();
}
});
/* This calls the changeCols funtion when the user changes the number of columns in the drop-down */
$('#cols').change(function(){
changeCols(parseInt($(this).val()));
});
});
</script>
</head>
<body>
<h1>Cellular Automata Encryption</h1>
<copyright><center>Emilie Menard Barnard</center></copyright>
<h2>About Cellular Automata</h2>
<p>"A cellular automaton (CA) consists of a regular grid of cells, each in one of a finite number of states, such as on and off. For each cell, a set of cells called its neighborhood is defined relative to the specified cell. An initial state is selected by assigning a state for each cell. A new generation is created according to some fixed rule. This rule determines the new state of each cell in terms of the current state of the cell and the states of the cells in its neighborhood."-<a href="http://en.wikipedia.org/wiki/Cellular_automaton">Wikipedia</a><br>
<br>CA are used for many applications, including <a href="http://www.technologyreview.com/view/426536/encrypting-pictures-using-chaotic-cellular-automata/">encrypting pictures</a>.</p>
<h2>This CA Generator</h2>
<p>I designed this CA generator as a final project for my Cryptography course at UC Santa Barbara. It invokes a python script that I wrote to take in a vector input and rule number, and output the resulting CA grid. Each new generation of a given cell depends on the parent cell and the parent's two neighboring cells. Thus, there are 256 different possible rules than can be used. For this reason, any rule number input will taken as mod 256. By clicking on the boxes in the first row, you turn a specific cell on or off. Running the generator on different inputs and rules will give different outputs. You can also set the number of rows and columns for the grid, and your preferred color scheme. If you'd like to see the step-by-step progress of the generator, enable the animation. Enjoy!</p>
<p>Color Scheme:
 
<img src="images/colors1.png"><input type="radio" name="colorScheme" id=bluePink checked="checked" onclick="changeColor1()"/>
 
<img src="images/colors2.png"><input type="radio" name="colorScheme" id=orangeBlue onclick="changeColor2()" />
 
<img src="images/colors3.png"><input type="radio" name="colorScheme" id=yellowGreen onclick="changeColor3()" />
 
<img src="images/colors4.png"><input type="radio" name="colorScheme" id=purpleGrey onclick="changeColor4()"/></p>
<center>
<div class="userInputParams"><p>
Number of Columns:
<select id="cols">
<option value="9">9</option>
<option value="17">17</option>
<option value="33">33</option>
<option value="65">65</option>
</select>
<br>
Number of Rows:
<select id="rows">
<option value="20">20</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="250">250</option>
<option value="500">500</option>
</select>
<br>Rule Number (mod 256): <input type="text" id="ruleNo" size="4" value="30">
<br>
Animate: <input id="animateCheckbox" type="checkbox"><input id="stopAnimateButton" type="button" onclick="stopAnimate()" value="Stop Animation">
<br><br>
<input id="submitButton" type="button" onclick="submitClick()" value="Start Encryption">
<br><br>
<input id="selectAllButton" type="button" onclick="selectAll()" value="Select All"><input id="clearAllButton" type="button" onclick="clearAll()" value="Clear">
</p></div>
<div class="userInputRow"></div><div class="outputRows"></div>
</center>
</body>
</html>