1
+ let array = [ 1 ]
2
+ let arrayLength = 25
3
+ let modes = { initial : 1 , sorting : 2 , done : 3 }
4
+ let algorithms = {
5
+ quickSort : { key : 2 , name : "Quick Sort" , description : `The time complexity of Quick Sort is O(n^2) in worst case and O(n*Log n) in average and best cases. The in-place version of quicksort has a space complexity of O(log n), even in the worst case. This unstable partition requires O(1) space. <br> <a href="https://youtu.be/Hoixgm4-P4M" target="_blank">Learn more...</a>` } ,
6
+ bubbleSort : { key : 3 , name : "Bubble Sort" , description : `The time complexity of Bubble Sort is O(n^2) in worst and average cases and O(n) in best case. It has the space complexity of O(1). <br> <a href="https://youtu.be/xli_FI7CuzA" target="_blank">Learn more...</a>` } ,
7
+ selectionSort : { key : 4 , name : "Selection Sort" , description : `The time complexity of Selection Sort is O(n^2) in worst and average cases and O(n^2) in best case. It has the space complexity of O(1). <br> <a href="https://youtu.be/g-PGLbMth_g" target="_blank">Learn more...</a>` } ,
8
+ insertionSort : { key : 5 , name : "Insertion Sort" , description : `The time complexity of Insertion Sort is O(n^2) in all the 3 cases (worst, average and best). It has the space complexity of O(1). <br> <a href="https://youtu.be/JU767SDMDvA" target="_blank">Learn more...</a>` } ,
9
+ }
10
+ let indicatorPanelContent = {
11
+ quickSort : `<div class="node node-sorted node-example ml-3" id="sorted_node_example"></div><div class="text-light ml-2">Sorted</div>
12
+ <div class="ml-3 text-light">|</div>
13
+ <div class="node node-unsorted node-example ml-3" id="unsorted_node_example"></div><div class="text-light ml-2">Unsorted</div>
14
+ <div class="ml-3 text-light">|</div>
15
+ <div class="node node-pivot ml-3" id="pivot_node_example"></div><div class="text-light ml-2">Pivot</div>
16
+ <div class="ml-3 text-light">|</div>` ,
17
+ bubbleSort : `<div class="node node-sorted node-example ml-3" id="sorted_node_example"></div><div class="text-light ml-2">Sorted</div>
18
+ <div class="ml-3 text-light">|</div>
19
+ <div class="node node-unsorted node-example ml-3" id="unsorted_node_example"></div><div class="text-light ml-2">Unsorted</div>
20
+ <div class="ml-3 text-light">|</div>` ,
21
+ selectionSort : `<div class="node node-position ml-3" id="position_node_example"></div><div class="text-light ml-2">Position</div>
22
+ <div class="ml-3 text-light">|</div>
23
+ <div class="node node-minimum ml-3" id="minimum_node_example"></div><div class="text-light ml-2">Minimum</div>
24
+ <div class="ml-3 text-light">|</div>` ,
25
+ insertionSort : `<div class="node node-position ml-3" id="position_node_example"></div><div class="text-light ml-2">Position</div>
26
+ <div class="ml-3 text-light">|</div>
27
+ <div class="node node-scanner ml-3" id="scanner_node_example"></div><div class="text-light ml-2">Scanner</div>
28
+ <div class="ml-3 text-light">|</div>` ,
29
+ }
30
+ let mode = modes . initial
31
+ let algorithm = algorithms . quickSort // Updated to quickSort
32
+
33
+ const SEARCH_TIME = 20000
34
+ const RUNNING_SORTING_MESSAGE = "Sorting is ongoing"
35
+
36
+ document . addEventListener ( 'DOMContentLoaded' , ( ) => {
37
+ array = generateArray ( arrayLength )
38
+ showAlgorithmList ( )
39
+ updateVisualizerButton ( )
40
+ updateIndicatorPanel ( )
41
+ updateAlgorithmInfo ( )
42
+ plotGraph ( )
43
+ handleUserEvent ( )
44
+ } )
45
+
46
+ function handleUserEvent ( ) {
47
+ algorithmInputHandler ( )
48
+ visualizerButtonHandler ( )
49
+ resetButtonHandler ( )
50
+ algorithmInfoHandler ( )
51
+ customInputHandler ( )
52
+ }
53
+
54
+ function showAlgorithmList ( ) {
55
+ let algorithmList = document . querySelector ( '#algorithm_list' )
56
+ Object . keys ( algorithms ) . map ( index => {
57
+ algorithmList . insertAdjacentHTML ( 'beforeend' , `<a class="dropdown-item cursor-pointer" id="algorithm_${ algorithms [ index ] . key } ">${ algorithms [ index ] . name } </a>` )
58
+ } )
59
+ }
60
+ function algorithmInputHandler ( ) {
61
+ let quickSortAlgorithm = document . querySelector ( '#algorithm_list' ) . querySelector ( `#algorithm_${ algorithms . quickSort . key } ` )
62
+ quickSortAlgorithm . addEventListener ( 'click' , ( ) => {
63
+ if ( mode === modes . initial || mode === modes . done ) {
64
+ algorithm = algorithms . quickSort
65
+ updateVisualizerButton ( )
66
+ updateIndicatorPanel ( )
67
+ updateAlgorithmInfo ( )
68
+ }
69
+ } )
70
+ let bubbleSortAlgorithm = document . querySelector ( '#algorithm_list' ) . querySelector ( `#algorithm_${ algorithms . bubbleSort . key } ` )
71
+ bubbleSortAlgorithm . addEventListener ( 'click' , ( ) => {
72
+ if ( mode === modes . initial || mode === modes . done ) {
73
+ algorithm = algorithms . bubbleSort
74
+ updateVisualizerButton ( )
75
+ updateIndicatorPanel ( )
76
+ updateAlgorithmInfo ( )
77
+ }
78
+ } )
79
+ let selectionSortAlgorithm = document . querySelector ( '#algorithm_list' ) . querySelector ( `#algorithm_${ algorithms . selectionSort . key } ` )
80
+ selectionSortAlgorithm . addEventListener ( 'click' , ( ) => {
81
+ if ( mode === modes . initial || mode === modes . done ) {
82
+ algorithm = algorithms . selectionSort
83
+ updateVisualizerButton ( )
84
+ updateIndicatorPanel ( )
85
+ updateAlgorithmInfo ( )
86
+ }
87
+ } )
88
+ let insertionSortAlgorithm = document . querySelector ( '#algorithm_list' ) . querySelector ( `#algorithm_${ algorithms . insertionSort . key } ` )
89
+ insertionSortAlgorithm . addEventListener ( 'click' , ( ) => {
90
+ if ( mode === modes . initial || mode === modes . done ) {
91
+ algorithm = algorithms . insertionSort
92
+ updateVisualizerButton ( )
93
+ updateIndicatorPanel ( )
94
+ updateAlgorithmInfo ( )
95
+ }
96
+ } )
97
+ }
98
+
99
+ function visualizerButtonHandler ( ) {
100
+ let visualizerButton = document . querySelector ( '#start_btn' )
101
+ let statusMessage = document . querySelector ( '#status_message' )
102
+ visualizerButton . addEventListener ( 'click' , async event => {
103
+ if ( mode === modes . initial || mode === modes . done ) {
104
+ mode = modes . sorting
105
+ statusMessage . innerHTML = ''
106
+ statusMessage . insertAdjacentHTML ( 'beforeend' , `Sorting <i class="fas fa-spinner"></i>` )
107
+ let animation = [ ]
108
+ let movesCount = 0
109
+ if ( algorithm . key === algorithms . quickSort . key ) {
110
+ quickSort . sort ( [ ...array ] , animation )
111
+ await barVisualizer . quickSort ( animation )
112
+ movesCount = animation . filter ( set => ! set . sorted ) . length
113
+ } else if ( algorithm . key === algorithms . bubbleSort . key ) {
114
+ bubbleSort . sort ( [ ...array ] , animation )
115
+ await barVisualizer . bubbleSort ( animation )
116
+ movesCount = animation . filter ( set => ! set . sorted ) . length
117
+ } else if ( algorithm . key === algorithms . selectionSort . key ) {
118
+ selectionSort . sort ( [ ...array ] , animation )
119
+ await barVisualizer . selectionSort ( animation )
120
+ movesCount = animation . filter ( set => ! set . sorted ) . length
121
+ } else if ( algorithm . key === algorithms . insertionSort . key ) {
122
+ insertionSort . sort ( [ ...array ] , animation )
123
+ await barVisualizer . insertionSort ( animation )
124
+ movesCount = animation . filter ( set => ! set . sorted ) . length
125
+ }
126
+ statusMessage . innerHTML = `Sorting Completed | Total Moves: ${ movesCount } `
127
+ mode = modes . done
128
+ }
129
+ } )
130
+ }
131
+
132
+ function resetButtonHandler ( ) {
133
+ let graphBody = document . querySelector ( '#graph_body' )
134
+ let resetButton = document . querySelector ( '#reset_btn' )
135
+ resetButton . addEventListener ( 'click' , async event => {
136
+ if ( mode === modes . initial || mode === modes . done ) {
137
+ let statusMessage = document . querySelector ( '#status_message' )
138
+ statusMessage . innerHTML = ''
139
+ array = generateArray ( arrayLength )
140
+ graphBody . innerHTML = ''
141
+ plotGraph ( )
142
+ mode = modes . initial
143
+ }
144
+ } )
145
+ }
146
+
147
+ function customInputHandler ( ) {
148
+ let customInputButton = document . querySelector ( '#custom_input_btn' )
149
+ customInputButton . addEventListener ( 'click' , event => {
150
+ if ( mode === modes . initial || mode === modes . done ) {
151
+ let customInput = document . querySelector ( '#custom_input' )
152
+ customInput . style . display = "flex"
153
+ }
154
+ else alert ( RUNNING_SORTING_MESSAGE )
155
+ } )
156
+ let customInputCancelButton = document . querySelector ( '#custom_input_cancel_btn' )
157
+ customInputCancelButton . addEventListener ( 'click' , event => {
158
+ let customInput = document . querySelector ( '#custom_input' )
159
+ customInput . style . display = "none"
160
+ } )
161
+ let customInputSubmitButton = document . querySelector ( '#custom_input_submit_btn' )
162
+ customInputSubmitButton . addEventListener ( 'click' , event => {
163
+ let customInputField = document . querySelector ( '#custom_input_field' )
164
+ let input = customInputField . value
165
+ input = input . split ( ',' ) . map ( value => {
166
+ let number = Number ( value )
167
+ if ( number < 5 ) number = 5
168
+ if ( number > 500 ) number = 500
169
+ return number
170
+ } )
171
+ if ( input . includes ( NaN ) ) alert ( 'Invalid Input' )
172
+ else {
173
+ array = input
174
+ arrayLength = array . length
175
+ plotGraph ( )
176
+ customInputCancelButton . click ( )
177
+ }
178
+ } )
179
+ }
180
+
181
+ function algorithmInfoHandler ( ) {
182
+ let algorithmInfoButton = document . querySelector ( '#graph_header' ) . querySelector ( '.algorithm-info-btn' )
183
+ algorithmInfoButton . addEventListener ( 'click' , event => {
184
+ let algorithmInfo = document . querySelector ( '#algorithm_info' )
185
+ algorithmInfo . style . display = "flex"
186
+ } )
187
+ let algorithmInfoCancelButton = document . querySelector ( '#algorithm_info_cancel_btn' )
188
+ algorithmInfoCancelButton . addEventListener ( 'click' , event => {
189
+ let algorithmInfo = document . querySelector ( '#algorithm_info' )
190
+ algorithmInfo . style . display = "none"
191
+ } )
192
+ }
193
+
194
+ function updateVisualizerButton ( ) {
195
+ let visualizerButton = document . querySelector ( '#start_btn' )
196
+ visualizerButton . innerHTML = `Start ${ algorithm . name } `
197
+ let algorithmMessage = document . querySelector ( '#algorithm_message' )
198
+ algorithmMessage . innerHTML = `${ algorithm . name } Algorithm`
199
+ let statusMessage = document . querySelector ( '#status_message' )
200
+ statusMessage . innerHTML = ``
201
+ }
202
+
203
+ function updateIndicatorPanel ( ) {
204
+ let indicatorPanel = document . querySelector ( '#indicator_panel' )
205
+ indicatorPanel . innerHTML = ''
206
+ let key = 'merge'
207
+ Object . keys ( algorithms ) . map ( index => {
208
+ if ( algorithms [ index ] === algorithm ) key = index
209
+ } )
210
+ indicatorPanel . insertAdjacentHTML ( 'beforeend' , indicatorPanelContent [ key ] )
211
+ }
212
+
213
+ function updateAlgorithmInfo ( ) {
214
+ let algorithmInfoHeader = document . querySelector ( '#algorithm_info_header' )
215
+ let algorithmInfoBody = document . querySelector ( '#algorithm_info_body' )
216
+ algorithmInfoHeader . innerHTML = algorithm . name + " Algorithm"
217
+ algorithmInfoBody . innerHTML = algorithm . description
218
+ }
219
+
220
+ function plotGraph ( unsortedNodes = [ ] ) {
221
+ let graphBody = document . querySelector ( '#graph_body' )
222
+ let nodeWidth = Math . floor ( graphBody . offsetWidth / array . length * 0.6 )
223
+ let barChart = graphBody . querySelector ( '#bar_chart' )
224
+ if ( ! barChart ) graphBody . insertAdjacentHTML ( 'beforeend' , `<div class="bar-chart row m-0" id="bar_chart"></div>` )
225
+ barChart = graphBody . querySelector ( '#bar_chart' )
226
+ barChart . innerHTML = ''
227
+ array . map ( ( number , index ) => {
228
+ barChart . insertAdjacentHTML ( 'beforeend' , `<div class="node text-white text-center" id="node_${ index } ">${ number } </div>` )
229
+ let node = barChart . querySelector ( `#node_${ index } ` )
230
+ node . style . height = number + "px"
231
+ node . style . width = nodeWidth + "px"
232
+ node . style . fontSize = ( nodeWidth / 3 ) + "px"
233
+
234
+ let indices = unsortedNodes . filter ( indices => indices . index === index )
235
+ if ( unsortedNodes . length && indices . length ) {
236
+ node . classList . add ( indices [ 0 ] . className )
237
+ }
238
+ } )
239
+ }
0 commit comments