1 2jQuery(document).ready(function($){ 3 4var spinning = false; 5 6// ââ Prizes (unchanged probabilities from V3) 7var prizes = [ 8 {name:'Hot Air Balloon', probability:33.33, color:'#64C8E8', text:'#fff'}, 9 {name:'One Day Car Free', probability:33.33, color:'#64C8E8', text:'#fff'}, 10 {name:'Limo Ride', probability:0, color:'#E8649B', text:'#fff'}, 11 {name:'Kok Tobe', probability:0, color:'#F0C842', text:'#333'}, 12 {name:'Dinner Voucher', probability:0, color:'#E8649B', text:'#fff'}, 13 {name:'Big Almaty Lake Tour',probability:0, color:'#F0C842', text:'#333'}, 14 {name:'Club Hopping', probability:0, color:'#E8649B', text:'#fff'}, 15 {name:'Lunch Voucher', probability:33.34, color:'#F0C842', text:'#333'}, 16 {name:'Issyk Lake Tour', probability:0, color:'#64C8E8', text:'#fff'}, 17]; 18 19var N = prizes.length; 20var ARC = (2 * Math.PI) / N; 21var angle = 0; 22 23var canvas = document.getElementById('tswCanvas'); 24var ctx = canvas.getContext('2d'); 25 26// ââ Draw wheel on canvas 27function draw(a) { 28 var W = canvas.width; 29 var cx = W / 2, cy = W / 2, R = cx - 14; 30 ctx.clearRect(0, 0, W, W); 31 32 // Outer dark ring 33 ctx.beginPath(); 34 ctx.arc(cx, cy, R + 13, 0, 2 * Math.PI); 35 ctx.fillStyle = '#111'; 36 ctx.fill(); 37 38 // White dots on rim 39 for (var d = 0; d < N * 2; d++) { 40 var da = (d / (N * 2)) * 2 * Math.PI + a; 41 ctx.beginPath(); 42 ctx.arc(cx + (R + 6) * Math.cos(da), cy + (R + 6) * Math.sin(da), 4, 0, 2 * Math.PI); 43 ctx.fillStyle = '#fff'; 44 ctx.fill(); 45 } 46 47 // Slices 48 for (var i = 0; i < N; i++) { 49 var start = a + i * ARC - Math.PI / 2; 50 var end = start + ARC; 51 52 ctx.beginPath(); 53 ctx.moveTo(cx, cy); 54 ctx.arc(cx, cy, R, start, end); 55 ctx.closePath(); 56 ctx.fillStyle = prizes[i].color; 57 ctx.fill(); 58 ctx.strokeStyle = '#fff'; 59 ctx.lineWidth = 2.5; 60 ctx.stroke(); 61 62 // Label (word-wrap) 63 ctx.save(); 64 ctx.translate(cx, cy); 65 ctx.rotate(start + ARC / 2); 66 ctx.font = 'bold 11px Arial, sans-serif'; 67 ctx.fillStyle = prizes[i].text; 68 ctx.textAlign = 'right'; 69 70 var words = prizes[i].name.split(' '); 71 var lines = [], cur = ''; 72 words.forEach(function(w) { 73 var t = cur ? cur + ' ' + w : w; 74 if (t.length > 11 && cur) { lines.push(cur); cur = w; } 75 else cur = t; 76 }); 77 if (cur) lines.push(cur); 78 79 var lh = 14, sy = -(lines.length - 1) * lh / 2; 80 lines.forEach(function(l, li) { 81 ctx.fillText(l, R - 12, sy + li * lh + 4); 82 }); 83 ctx.restore(); 84 } 85 86 // Center white disc 87 ctx.beginPath(); 88 ctx.arc(cx, cy, 50, 0, 2 * Math.PI); 89 ctx.fillStyle = '#fff'; 90 ctx.fill(); 91 ctx.strokeStyle = '#ddd'; 92 ctx.lineWidth = 2; 93 ctx.stroke(); 94 95 ctx.fillStyle = '#333'; 96 ctx.font = 'bold 11px Arial, sans-serif'; 97 ctx.textAlign = 'center'; 98 ctx.textBaseline = 'middle'; 99 ctx.fillText('ALMATY', cx, cy - 5); 100 ctx.font = '9px Arial, sans-serif'; 101 ctx.fillText('.com', cx, cy + 8); 102} 103 104draw(0); 105 106// ââ Pick winner by probability 107function pickPrize() { 108 var rand = Math.random() * 100, cumulative = 0; 109 for (var i = 0; i < prizes.length; i++) { 110 cumulative += prizes[i].probability; 111 if (rand <= cumulative) return i; 112 } 113 return 7; // fallback: Lunch Voucher 114} 115 116// ââ Ease function 117function easeInOutCubic(t) { 118 return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; 119} 120 121// ââ Flight fields toggle (unchanged from V3) 122$('#flightBooking').change(function() { 123 if ($(this).val() === 'Yes') { 124 $('#flightFields').slideDown(); 125 } else { 126 $('#flightFields').slideUp(); 127 } 128}); 129 130// ââ Spin button 131$('#tswSpinBtn').click(function() { 132 if (spinning) return; 133 spinning = true; 134 $(this).prop('disabled', true); 135 136 var won = pickPrize(); 137 138 // FIX V4: Correct angle math â winning slice stops at top (under pointer tip) 139 // Slice i center at angle a: a + (i + 0.5)*ARC - PI/2 140 // For center == top (-PI/2): a = 2*PI*k - (i + 0.5)*ARC 141 var extra = 6 + Math.floor(Math.random() * 3); // 6-8 full extra rotations 142 var target = 2 * Math.PI * extra - (won + 0.5) * ARC; 143 while (target - angle < 4 * 2 * Math.PI) target += 2 * Math.PI; 144 145 var startAngle = angle; 146 var totalRot = target - startAngle; 147 var duration = 5000; 148 var t0 = null; 149 150 function frame(ts) { 151 if (!t0) t0 = ts; 152 var progress = Math.min((ts - t0) / duration, 1); 153 angle = startAngle + totalRot * easeInOutCubic(progress); 154 draw(angle); 155 156 if (progress < 1) { 157 requestAnimationFrame(frame); 158 } else { 159 // Normalise angle to prevent float overflow 160 angle = ((target % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI); 161 spinning = false;
162 163 $('#tswPrize').val(prizes[won].name); 164 $('#tswPrizeText').html('🎉 You won: ' + prizes[won].name); 165 $('#tswPopup').fadeIn(); 166 } 167 } 168 requestAnimationFrame(frame); 169}); 170 171// ââ Popup close (unchanged from V3) 172$('.tsw-close').click(function() { 173 $('#tswPopup').fadeOut(); 174 $('#tswClaimForm')[0].reset(); 175 $('#tswSuccess').hide().html(''); 176 $('#tswFormArea').show(); 177}); 178 179// ââ Form submit / AJAX (unchanged from V3) 180$('#tswClaimForm').submit(function(e) { 181 e.preventDefault(); 182 $.ajax({ 183 url: tsw_ajax.ajax_url, 184 type: 'POST', 185 data: { 186 action: 'tsw_claim_reward', 187 name: $('input[name="name"]').val(), 188 email: $('input[name="email"]').val(), 189 phone: $('input[name="phone"]').val(), 190 flight_booking: $('select[name="flight_booking"]').val(), 191 departure_date: $('input[name="departure_date"]').val(), 192 flight_number: $('input[name="flight_number"]').val(), 193 prize: $('#tswPrize').val() 194 }, 195 success: function(response) { 196 if (response.success) { 197 $('#tswFormArea').hide(); 198 $('#tswSuccess').show().html( 199 '<h2>Coupon Activated</h2>' + 200 '<p><strong>Prize:</strong> ' + response.data.prize + '</p>' + 201 '<p><strong>Coupon:</strong> ' + response.data.coupon + '</p>' + 202 '<p>Coupon sent to your email.</p>' + 203 '<button class="tsw-close-btn">Close</button>' 204 ); 205 $('#tsw-reward-status').text('Claimed \u2705'); 206 } 207 }, 208 error: function(err) { 209 console.log(err); 210 alert('Something went wrong'); 211 } 212 }); 213}); 214 215$(document).on('click', '.tsw-close-btn', function() { 216 $('.tsw-close').click(); 217}); 218 219});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.