Spinwheel using .NET Core and Winsheel.js
Hi All,
Recently I had request from one of my friends to create a small application to distribute 1000 gifts among employees of a certain company.
1) There were 5 types of gifts
2) Each type had 200 gifts
3) Gifts must be given in a random way
4) Every employee must get a gift
5) They should not get a gift which is over
So created a small application with a .NET Core backend, html, javascript. I used Winwheel.js to create the spinwheel. Hope you like it.
1) Solution
2) SQL Tables
5) Index View (Index.cshtml)
@model HomeViewModel
@{
ViewData["Title"] = "Click on the Wheel to Play & Win";
}
< <div id="completeModal" class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Competition Finished</h5>
</div>
<div class="modal-body">
<p>Congratulations to all Prize Winners. Have a nice day!</p>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-8">
<table cellpadding="0" cellspacing="0" align="center" valign="center" border="0">
<tr>
<td height="580" class="the_wheel">
<canvas onclick="startSpin();" id="canvas" width="434" height="434">
<p style="{color: white}" align="center">Sorry, your browser doesn't support canvas. Please try another.</p>
</canvas>
</td>
</tr>
</table>
</div>
<div class="col-md-4">
<div class="container">
<div class="card-deck mb-3 text-center">
<div class="card mb-4 box-shadow">
<div class="card-header">
<h4 class="my-0 font-weight-normal">Results</h4>
</div>
<div id="resultBody1" class="card-body">
</div>
<div id="resultFooter" style="display:none" class="card-footer">
<a asp-action="Reset" class="btn btn-lg btn-block btn-primary">Reset</a>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
// Create new wheel object specifying the parameters at creation time.
let theWheel = new Winwheel({
'numSegments': 5, // Specify number of segments.
'outerRadius': 212, // Set outer radius so wheel fits inside the background.
'textFontSize': 28, // Set font size as desired.
//'segments' : // Define segments including colour and text.
//[
// {'fillStyle' : '#888888', 'text' : 'Prize 1'},
// {'fillStyle' : '#89f26e', 'text' : 'Prize 2'},
// {'fillStyle' : '#7de6ef', 'text' : 'Prize 3'},
// {'fillStyle' : '#e7706f', 'text' : 'Prize 4'},
// {'fillStyle' : '#eae56f', 'text' : 'Prize 5'}
//],
'animation': // Specify the animation to use.
{
'type': 'spinToStop',
'duration': 5, // Duration in seconds.
'spins': 12, // Number of complete spins.
'callbackFinished': alertPrize
}
});
// Vars used by the code in this page to do power controls.
let wheelPower = 0;
let wheelSpinning = false;
// -------------------------------------------------------
// Function to handle the onClick on the power buttons.
// -------------------------------------------------------
function powerSelected(powerLevel) {
// Ensure that power can't be changed while wheel is spinning.
if (wheelSpinning == false) {
// Reset all to grey incase this is not the first time the user has selected the power.
// Now light up all cells below-and-including the one selected by changing the class.
// Set wheelPower var used when spin button is clicked.
wheelPower = powerLevel;
}
}
// -------------------------------------------------------
// Click handler for spin button.
// -------------------------------------------------------
function startSpin() {
// Ensure that spinning can't be clicked again while already running.
if (wheelSpinning == false) {
// Based on the power level selected adjust the number of spins for the wheel, the more times is has
// to rotate with the duration of the animation the quicker the wheel spins.
if (wheelPower == 1) {
theWheel.animation.spins = 3;
} else if (wheelPower == 2) {
theWheel.animation.spins = 8;
} else if (wheelPower == 3) {
theWheel.animation.spins = 15;
}
// Disable the spin button so can't click again while wheel is spinning.
//document.getElementById('spin_button').src = "spin_off.png";
//document.getElementById('spin_button').className = "";
// Begin the spin animation by calling startAnimation on the wheel object.
theWheel.startAnimation();
// Set to true so that power can't be changed and spin button re-enabled during
// the current animation. The user will have to reset before spinning again.
wheelSpinning = true;
}
}
// -------------------------------------------------------
// Function for reset button.
// -------------------------------------------------------
function resetWheel() {
theWheel.stopAnimation(false); // Stop the animation, false as param so does not call callback function.
theWheel.rotationAngle = 0; // Re-set the wheel angle to 0 degrees.
theWheel.draw(); // Call draw to render changes to the wheel.
wheelSpinning = false; // Reset to false to power buttons and spin can be clicked again.
}
// -------------------------------------------------------
// Called when the spin animation has finished by the callback feature of the wheel because I specified callback in the parameters
// note the indicated segment is passed in as a parmeter as 99% of the time you will want to know this to inform the user of their prize.
// -------------------------------------------------------
function alertPrize(indicatedSegment) {
// Do basic alert of the segment text. You would probably want to do something more interesting with this information.
bootbox.alert("Congratulations!!! You have won " + indicatedSegment.text, function () {
postResult(indicatedSegment.text);
});
}
function getResult() {
$.get("../Home/GetResults", function (data) {
if (data) {
initWheel(data);
}
});
}
function drawInitialWheel() {
var segments = [
{ 'fillStyle': '#888888', 'text': 'Prize 1' },
{ 'fillStyle': '#89f26e', 'text': 'Prize 2' },
{ 'fillStyle': '#7de6ef', 'text': 'Prize 3' },
{ 'fillStyle': '#e7706f', 'text': 'Prize 4' },
{ 'fillStyle': '#eae56f', 'text': 'Prize 5' }
];
for (var l = 0; l < theWheel.segments.length; l++) {
theWheel.deleteSegment(l);
}
for (var i = 0; i < segments.length; i++) {
theWheel.addSegment({ 'fillStyle': segments[i]["fillStyle"], 'text': segments[i]["text"] });
}
}
function initWheel(data) {
$("#resultBody1").empty();
$("#resultBody1").append("<h1 class='totalCard card-title pricing-card-title'> " + data.totalCount + "/@Model.MaxPrizeTotalCount" + " <small class='text-muted'>Prizes Won</small> </h1>");
if (data.totalCount > 0) {
$("#resultFooter").attr("style", "display:normal");
}
if (data.prizeCounts) {
let tempSegments = theWheel.segments.map((x) => x);
for (var l = 1; l < theWheel.segments.length; l++) {
theWheel.deleteSegment(l);
}
//theWheel.deleteAllSegments();
//theWheel.deleteSegment();
//console.log(theWheel.numSegments);
var segIndex = 1;
var addedSegments = false;
for (var i = 0; i < data.prizeCounts.length; i++) {
$("#resultBody1").append("<h3 class='resultCard card-title pricing-card-title'>" + data.prizeCounts[i].count + " <small class='text-muted'>" + data.prizeCounts[i].prizeName + " Remaining </small> </h3>");
let segment = null;
let dataPrize = null;
for (var l = 0; l < tempSegments.length; l++) {
if (tempSegments[l] && tempSegments[l].text === data.prizeCounts[i].prizeName && data.prizeCounts[i].count > 0) {
segment = tempSegments[l];
dataPrize = data.prizeCounts[i];
break;
}
}
if (segment) {
if (i === 0) {
segment.startAngle = 0;
segment.endAngle = 360 / (5 - data.TotalZeroCount);
theWheel.addSegment(segment, segIndex++);
addedSegments = true;
}
else {
let exSegment = null;
for (var l = 0; l < theWheel.segments.length; l++) {
if (theWheel.segments[l] && theWheel.segments[l].text === segment.text) {
exSegment = theWheel.segments[l];
break;
}
}
if (exSegment === null && data.TotalZeroCount != @Model.PrizeCategoryCount -1) {
theWheel.addSegment({ 'fillStyle': segment.fillStyle, 'text': segment.text }, segIndex++);
addedSegments = true;
}
else {
segment.startAngle = 0;
segment.endAngle = 360 / (@Model.PrizeCategoryCount - data.totalZeroCount);
theWheel.addSegment(segment, segIndex++);
}
}
}
}
if (addedSegments || (data.totalZeroCount === @Model.PrizeCategoryCount -1))
theWheel.deleteSegment(segIndex);
theWheel.draw();
}
if (data.totalCount === @Model.MaxPrizeTotalCount) {
$("#completeModal").modal({
backdrop: 'static',
keyboard: false
});
}
}
function postResult(value) {
$.post("../Home/PostPrize/" + value, function (data) {
if (data) {
initWheel(data);
}
});
resetWheel();
}
drawInitialWheel();
powerSelected(3);
getResult();
</script>
6) In Action
Comments
Post a Comment