$data['timerOffset'] = (int)$_POST['timerOffset'];
$data['priceChange'] = (int)$_POST['priceChange'];
$data['discount'] = (int)$_POST['discount'];
+ $data['percentLeft'] = (int)$_POST['percentLeft'];
$data['itemId'] = (int)$_POST['item'];
$data['prefix'] = $_POST['prefix'];
border: 2px solid red;
background-color: rgba(255, 255, 255, 0.7);
}
+s {color: green;}
.clock {
position: relative;
width: 100%;
<input type='radio' id='postfix' name='prefix' value='false'<?php echo $postChecked; ?>>
<input type='text' id='postfix' name='postfixString' value='<?php echo $postfix; ?>'>
- <label for='postfix'> Postfix</label><br>
+ <label for='postfix'> Postfix</label><br><br>
+
+ <input type='number' name='percentLeft' id='percentLeft' value='<?php echo $data['percentLeft']; ?>'>
+ <label for='percentLeft'> Unsold (%)</label>
</div><div class='split'>
Still need to do plenty to both the GFX overlay and this page (and the actual clock):
</p>
<ul>
- <li>Make this notes section a little better? it might actually be useful during the show. Although the arrow is quite difficult to click on</li>
- <li>Add the controls for persentage sold and the relevant display on the GFX side of things</li>
+ <li><s>Make this notes section a little better? it might actually be useful during the show. Although the arrow is quite difficult to click on</s></li>
+ <li><s>Add the controls for persentage sold and the relevant display on the GFX side of things</s></li>
<li><s>Add 2 more timers on both the controls and the GFX page</s></li>
<li>Add the <s>timers and the</s> % sold to the autocue so the presenter can atually see what theyre doing</li>
<li>Add a clock display to the GFX page and the autocue (could just be a gereric time?)</li>
<li>add marquee of the current buyers of the product and figure out how to do this (potentially hard?)</li>
</ul>
<p>
- and then still to do in the admin department: Talk to Joe about the GFX system, ask Ash about the lighting desk sAcn input and to setup things, makerspace the clock, text people about things, arrange screentest with Jack.
+ and then still to do in the admin department: Talk to Joe about the GFX system, ask Ash about the lighting desk sAcn input and to setup things, makerspace the clock, text people about things, <s>arrange screentest with Jack</s>.
</p>
</details>
</body>
var itemId = 0;
function makeTime(t, o, s) {
- let current = Math.round((Date.now() + o) / 1000);
- var time = t - current;
- if (Math.sign(time) == -1) {time = 0;}
- var minutes = Math.floor(time / 60);
- var seconds = (time - (minutes * 60));
+ let current = Math.round((Date.now() + o) / 1000);
+ var time = t - current;
+ if (Math.sign(time) == -1) {time = 0;}
+ var minutes = Math.floor(time / 60);
+ var seconds = (time - (minutes * 60));
- var minutesString = minutes.toString();
- var secondsString = seconds.toString();
- minutesString = minutesString.padStart(2, "0");
- secondsString = secondsString.padStart(2, "0");
- if (s == "true") {
- return `${minutesString}:${secondsString}`;
- } else {
- return `<s>${minutesString}:${secondsString}</s>`;
- }
+ var minutesString = minutes.toString();
+ var secondsString = seconds.toString();
+ minutesString = minutesString.padStart(2, "0");
+ secondsString = secondsString.padStart(2, "0");
+ if (s == "true") {
+ return `${minutesString}:${secondsString}`;
+ } else {
+ return `<s>${minutesString}:${secondsString}</s>`;
+ }
}
function frame() {
-{"topText":["It's here!"],"bottomText":["It's here!"],"bannerText":"It's here!","itemId":2,"currency":{"prefix":"$","postfix":" hairs"},"discount":70,"prefix":"false","round":"true","priceChange":50,"showingMain":"true","showingAll":"true","showingExtra":"true","showingTimer1":"true","showingTimer2":"true","showingTimer3":"true","timer3Main":"false","showingBanner":"true","showingSigil":["false","false","false","false"],"timer1End":1724723324,"timer2End":1724780836,"timer3End":1724781031,"timerOffset":0}
\ No newline at end of file
+{"topText":["It's here!"],"bottomText":["Something bright and radiant for all of you at home!","I take your life and raise you 10 over the hour!","We grab the bullion counterweight and throw ourselves down!","We have been falling for a looong time people!","Let me slip into something less spacious!","Down the side of a large golden pyramid!","So we dress ourselves in your Ballast!","I used to be so unimaginably tall!"],"bannerText":"Discounts on XMDV!","itemId":1,"currency":{"prefix":"$","postfix":" hairs"},"discount":-5000,"percentLeft":20,"prefix":"false","round":"true","priceChange":50,"showingMain":"true","showingAll":"true","showingExtra":"true","showingTimer1":"true","showingTimer2":"false","showingTimer3":"false","timer3Main":"false","showingBanner":"true","showingSigil":["false","false","false","false"],"timer1End":1724849889,"timer2End":1724848450,"timer3End":1724787297,"timerOffset":0}
\ No newline at end of file
opacity: 0;
transition: opacity 1.5s;
}
+.soldBox {
+ margin: 5px;
+ padding: 5px;
+ border-radius: 5px;
+ background-image: var(--background);
+ box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 3px, rgba(0, 0, 0, 0.19) 0px 1px 2px;
+}
+.soldBox > * {
+ margin: 0;
+ font-style: italic;
+}
+.soldBox > * > span {
+ font-weight: bold;
+ font-style: normal;
+}
#raiting {
margin: 5px;
margin-top: 0;
z-index: -1;
transform: translateY(-100%);
padding-top: 2vh;
+ padding-bottom: 1px;
background-image: var(--feature-gradient);
transition: transform 1.5s;
}
.showExtra > .extra {
transform: translateY(0%);
}
-.main > *, .extra > *, .bottom > *, .marquee > * {
+.main > *, .extra > *:not(.soldBox), .bottom > *, .marquee > * {
margin: 0;
padding: 0.5vh 1vh;
}
var newDiscount = 1;
var priceChange = 0;
+var percentLeft = 1;
+
var showingSigils = true;
// helper function for creating price strings
else {return Math.round(seconds * (100 / 60))}
}
}
+
// handles all updates from the server data that are not required to be instantanious (2 times per second)
function update() {
fetch("./data.json", {cache: "no-store"})
.then(data => {
itemId = data.itemId;
- //handle all optional elements showing/hiding
+ // handle all optional elements showing/hiding
+ // All element handling
const all = document.getElementById("all");
if (data.showingAll == "true") {
all.classList.add("show");
all.classList.remove("show");
}
+ // Banner handling
const banner = document.getElementsByClassName("banner")[0];
if (data.showingBanner == "true") {
if (!banner.classList.contains("show")) {
banner.classList.remove("show");
}
+ // Timer 1
const timer1 = document.getElementsByClassName("timer1")[0];
timer1.innerHTML = makeTime(data.timer1End, data.timerOffset);
if (data.showingTimer1 == "true") {
timer1.classList.remove("show");
}
+ // Timer 2
const timer2 = document.getElementsByClassName("timer2")[0];
timer2.innerHTML = makeTime(data.timer2End, data.timerOffset);
if (data.showingTimer2 == "true") {
var property = `conic-gradient(rgb(0,0,0,0) 0deg, rgb(0,0,0,0) ${angle}deg, var(--feature-light) ${angle}.1deg, var(--feature-light) 360deg)`;
timer2.style.background = `${property}, var(--background)`;
+ // Timer 3
const timer3 = document.getElementsByClassName("timer3")[0];
timer3.innerHTML = makeTime(data.timer3End, data.timerOffset);
if (data.showingTimer3 == "true") {
var property = `linear-gradient(rgb(0,0,0,0) 0%, rgb(0,0,0,0) ${radius}%, var(--feature-light) ${radius}.1%, var(--feature-dark) 100%)`;
timer3.style.background = `${property}, var(--background)`;
+ // Side product information
const side = document.getElementsByClassName("side")[0];
if (data.showingMain == "true") {
side.classList.add("show");
banner.classList.add("moved");
timer2.classList.add("moved");
}
+
+ // Product extra information
if (data.showingExtra == "true" && data.showingMain == "true") {
side.classList.add("showExtra");
} else {
side.classList.remove("showExtra");
}
+ // Discount badge
const badgeContainer = document.getElementsByClassName("badgeContainer")[0];
if (discount <= 0.99) {
badgeContainer.classList.add("show");
badgeContainer.classList.remove("show");
}
+ // Sigil handling
const sigilNE = document.getElementById("sigilNE");
if (data.showingSigil[0] == "true") {
sigilNE.classList.add("show");
sigilNW.classList.remove("show");
}
+ // Check for sigil freeze
+ if (data.showingSigil.every(i => i == "false")) {
+ showingSigils = false;
+ } else {
+ showingSigils = true;
+ }
+
// set variables for the frame process to allow it to function without requesting data 200x per second
round = data.round;
priceChange = data.priceChange / 100;
newDiscount = data.discount / 100;
- if (data.showingSigil.every(i => i == "false")) {
- showingSigils = false;
- } else {
- showingSigils = true;
- }
+ percentLeft = data.percentLeft /100;
+
});
// get the requested item data
fetch("./items.json") // this is static so there is no need to request it every time
.then(data => data.json())
.then(data => {
+ // set item properties
document.getElementById("code").innerHTML = data[itemId].code;
document.getElementById("raiting").innerHTML = data[itemId].rating;
document.getElementById("subtext").innerHTML = data[itemId].subtext;
document.getElementById("description").innerHTML = data[itemId].description;
+ // set discount figures
let discountPricePlan = (data[itemId].origionalPrice * discount * 1.1) / 12
document.getElementById("currentPrice").innerHTML = `<em>Now only:</em> ${makePrice(data[itemId].origionalPrice * discount)}`;
document.getElementById("monthlyPrice").innerHTML = `12 monthly payments of <b>${makePrice(discountPricePlan)}</b>`;
document.getElementById("badgeText").innerHTML = `${Math.round((1 - discount) * 100)}% OFF`;
+ document.getElementById("stock").innerHTML = `${data[itemId].stockCount} units`;
+ document.getElementById("sold").innerHTML = `${Math.round(data[itemId].stockCount * (1 - percentLeft))} units`;
+
+ console.log(percentLeft);
+ if (percentLeft < 0.1) { descriptor = "Quick! Only"; }
+ else if (percentLeft < 0.25) { descriptor = "Only"; }
+ else if (percentLeft < 0.5) { descriptor = "Just"; }
+ else { descriptor = ""; }
+
+ if (percentLeft == 0) { document.getElementById("unitsLeft").innerHTML = "Sold out!"; }
+ else { document.getElementById("unitsLeft").innerHTML = `${descriptor} ${Math.round(data[itemId].stockCount * (percentLeft))} left!`;}
+
if (discount <= 0.99) {
document.getElementById("origionalPrice").innerHTML = `<s><em>WAS:</em> ${makePrice(data[itemId].origionalPrice)}</s>`;
} else {
}
});
}
+
// function handles all animated events that are required to look smooth (marquee movement / price changes) (200 times per second)
function frame() {
<div class="container side show">
<div class="box main">
- <h1 id="code"></h1>
- <h3 id="raiting"></h3>
- <h2 class="feature" id="subtext"></h2>
- <h3 id="description"></h3>
+ <h1 id="code">Code</h1>
+ <h3 id="raiting">Raiting</h3>
+ <h2 class="feature" id="subtext">Subtext</h2>
+ <h3 id="description">Description</h3>
<hr>
- <h4 id="origionalPrice"></h4>
+ <h4 id="origionalPrice">Origional Price</h4>
<div class="badgeContainer">
<img class="badge" src="./star.svg"></img>
- <h2 class="badge" id="badgeText">5000000000% OFF</h2>
+ <h2 class="badge" id="badgeText">Percent off</h2>
</div>
- <h3 id="discount"></h3>
</div>
<div class="box extra">
- <h2 style="margin-top: 1vh;"id="currentPrice"></h4>
- <p id="monthlyPrice"></p>
+ <h2 style="margin-top: 1vh;" id="currentPrice">Current Price</h4>
+ <p id="monthlyPrice">Monthly Price</p>
+ <div class="soldBox">
+ <p style="font-size: 1.2em;">In Stock: <span style="margin-right:10px;" id="stock"></span> Sold: <span id="sold"></span></p>
+ <p style="font-size: 1.6em;" class="alert" id="unitsLeft"></p>
+ </div>
</div>
</div>