From: Max Value Date: Sat, 26 Jul 2025 17:54:30 +0000 (+0100) Subject: Converted rest of pages to websockets X-Git-Url: https://git.ozva.co.uk/?a=commitdiff_plain;h=5f1ae63e2e62bc043ac6db650413844ad1925703;p=shopping-channel Converted rest of pages to websockets --- diff --git a/TODO b/TODO index cc33ad5..84c8045 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,9 @@ -- websockets for the api - update the doomsday clock repo -- better solution to loading static data +- better solution to loading static data across the board - potentially in the database? - could open it up for sqlite browser + - could build some web editor to allow the user to change stuff +- fix the doomsday control pannel to relay straight to the clock (via the server) +- clean up main GFX css +- check for websockets being secure (for the shout and clock) +- something else that i forgot diff --git a/main.py b/main.py index 887cdb3..be3ba99 100755 --- a/main.py +++ b/main.py @@ -2,7 +2,6 @@ from flask_socketio import SocketIO, emit from flask_httpauth import HTTPBasicAuth -from datetime import datetime, timezone from os import path, environ, system from flask_cors import CORS from flask import Flask,request @@ -71,10 +70,13 @@ app.before_request(teleshopping.check_database) # if the socket is connecting for the first time, send data @socketio.on('connect') def initial(): - print("conected!") request.method = "internal" emit("apiUpdate", teleshopping.data(), json=True) +@socketio.on('shoutUpdate') +def shout_broadcast(data): + emit("shoutUpdate", data, json=True, broadcast=True) + if __name__ == "__main__": socketio.run(app, host='127.0.0.1', port=8000, debug=True) diff --git a/static/display.css b/static/display.css index c85b420..7a34135 100644 --- a/static/display.css +++ b/static/display.css @@ -39,3 +39,13 @@ body { #discountBox.show { opacity: 1; } + +#timer_1 { + background-color: green; +} +#timer_2 { + background-color: purple; +} +#timer_3 { + background-color: blue; +} diff --git a/static/info.json b/static/info.json index 27c46e9..89490bd 100644 --- a/static/info.json +++ b/static/info.json @@ -1,134 +1,78 @@ { "shoot": { - "date": "24th April 2025", - "location": "MediaCity UoS, TV Studio A" + "date": "Forever", + "location": "In our hearts" }, "crew":[ { "name": "William Greenwood (T)", "role": "Producer", "phone": "075 9476 8180", - "email": "W.Greenwood@edu.salford.ac.uk", + "email": "greenwoodw50@gmail.com", "absent": false }, { "name": "Finn Downton (T)", "role": "Narrative engineer", "phone": "079 1003 1116", - "email": "E.Downton@edu.salford.ac.uk", + "email": "edendownton@gmail.com", "absent": false }, { "name": "Jack Christian-Sims (T)", "role": "Director", "phone": "075 4297 4087", - "email": "J.Christian-Sims@edu.salford.ac.uk", + "email": "jackchristiansims@gmail.com", "absent": false }, { "name": "Eleanor Haughton", "role": "Vision Mixer", "phone": "074 9127 2723", - "email": "E.V.Haughton@edu.salford.ac.uk", - "absent": false + "email": "", + "absent": true }, { "name": "Heather Digwood (T)", "role": "Floor manager", "phone": "077 8817 3853", - "email": "H.Digwood@edu.salford.ac.uk", - "absent": false + "email": "", + "absent": true }, { "name": "Olivia Gillett (T)", "role": "Floor manager", "phone": "073 6852 4302", - "email": "O.Gillett@edu.salford.ac.uk", - "absent": false + "email": "", + "absent": true }, { "name": "Leo Garside-Holdich", "role": "Camera operator", "phone": "078 7474 0891", - "email": "L.N.Garside-Holdich@edu.salford.ac.uk", - "absent": false + "email": "", + "absent": true }, { "name": "Rebecca Dixon", "role": "Sound operator", "phone": "074 3400 7701", - "email": "R.Dixon2@edu.salford.ac.uk", - "absent": false - }, - { - "name": "Alex Roberts", - "role": "Lighting operator", - "phone": "074 9660 1832", - "email": "A.Roberts17@edu.salford.ac.uk", - "absent": false - }, - { - "name": "Shan Hackwood", - "role": "Engineer", - "phone": "075 3068 9322", - "email": "S.Hackwood@edu.salford.ac.uk", - "absent": false - }, - { - "name": "Megan Troop", - "role": "Output monitor", - "phone": "079 2659 5100", - "email": "M.Troop@edu.salford.ac.uk", - "absent": false + "email": "", + "absent": true }, { "name": "Tegan Blake-Barnard (T)", "role": "Set-design lead", "phone": "075 4893 0872", - "email": "T.blake-barnard@edu.Salford.ac.uk", - "absent": false - }, - { - "name": "Lydia Wilkinson", - "role": "Set-design", - "phone": "078 0269 0037", - "email": "L.wilkinson14@edu.salford.ac.uk", - "absent": false - }, - { - "name": "Leigha Blanchard", - "role": "Set-design / GFX operator (pricing)", - "phone": "074 7700 0501", - "email": "L.blanchard@salford.ac.uk", - "absent": false - }, - { - "name": "Daisy Devoe", - "role": "Set-design / GFX operator (timer)", - "phone": "079 7056 4500", - "email": "D.Devoe@edu.salford.ac.uk", - "absent": false - }, - { - "name": "Brynn Yates", - "role": "GFX operator (text)", - "phone": "073 7766 9812", - "email": "M.Yates5@edu.salford.ac.uk", - "absent": false - }, - { - "name": "Ben Cousen", - "role": "GFX operator", - "phone": "079 1333 5446", - "email": "B.Cousen@edu.salford.ac.uk", - "absent": false + "email": "", + "absent": true }, { "name": "Eli Clack", "role": "Photographer", "phone": "079 0824 2349", - "email": "G.Clack@edu.salford.ac.uk", - "absent": false + "email": "", + "absent": true } ], "cast":[ @@ -136,114 +80,48 @@ "name": "David Smith", "role": "Anchor", "phone": "078 8839 8003", - "email": "D.Smith51@edu.salford.ac.uk", - "absent": false - }, - { - "name": "Lucas Blackburn", - "role": "Backup Anchor", - "phone": "075 9324 5021", - "email": "ext", + "email": "", "absent": false } ], "schedule":[ { "time": "0900", - "title": "All crew call time for briefing.", - "extra": ["Room 3.08 MediaCity"] - }, - { - "time": "0930", - "title": "Kit picked up from the MediaCity kit store", + "title": "Things happen all the time", "extra": [ - "To be picked up by the vision mixer unless otherwise specified.", - "Kit is: GoPro Hero Kit Bundle (2), Zoom F6 (1), Radio mic (3)" - ] - }, - { - "time": "1000", - "title": "All crew moves to Studio A", - "extra": [ - "Vision mixer, Engineer, Sound, Output monitor and dedicated GFX operators to gallery to setup the cameras and sound kit as instructed by producer in advance.", - "All other personnel to the floor to setup the set. Floor plan is present on the digital docs, both FMs and the Set design lead will have tablets to access this, but the link will work on any device.", - "Lighting to setup and test lighting.", - "As soon as set complete: technical test on all kit including THE THREAT, the Lazy-Susan, the Doomsday Clock, the GFX system and the sound system.", - "Gallery crew should start technical test of the GFX system and the sound system at the instruction of the Narrative Engineer if the producer is still on the floor.", - "Set-design team begin bringing down the products from room 3.08 at the direction of set design lead" - ] + "Things end too", + "Things change", + "Did you ever poorly mix instant coffee?", + "Little specks of black", + "Against milky cream" + ] }, { "time": "1030", - "title": "Crew 15 minute break", - "extra": [ - ] - }, - { - "time": "1045", - "title": "Crew arrive back on set: begin run-throughs of the end", - "extra": [ - "Call time for photographer", - "Full crew run-throughs until happy with the order of operations", - "Should include THE THREAT, so The Anchor must not be present.", - "See production notes document for more details" - ] - }, - { - "time": "1100", - "title": "Anchor arrives, is met by set-design lead in room 3.08 for costuming.", - "extra": [] - }, - { - "time": "1130", - "title": "Prepare for Anchor on the floor", + "title": "If you invert the colors it looks like stars", "extra": [ - "Crew take position for short practice" - ] + "Like a coffee galaxy!", + "Every time I had a coffee I'd flip the colors", + "Look into the coffee night's sky" + ] }, { "time": "1145", - "title": "Practices begin at the direction of the producer", - "extra": [ - "This will be practices of product hand-over with the FMs as well as individual products where necessary." - ] - }, - { - "time": "1200", - "title": "The Backup Anchor arrives, is met by set-design lead and producer in the foyer and taken to room 3.08 for costuming and short brief on timings.", + "title": "I dont feel like this happens anymore", "extra": [ - "This will be practices of product hand-over with the FMs as well as individual products where necessary.", - "After backup is costumed, to be taken to the green room." - ] + "Maybe they changed how they make coffee", + "Things change", + "It just looks uniform brown now", + "I suppose reversed its like I'm the stars themselves" + ] }, { "time": "1215", - "title": "All crew and cast prepare for full run-through", + "title": "Lunchtime", "extra": [] - }, - { - "time": "1230", - "title": "Stream goes live and full run-through begins (latest 1245 for 1h runtime)", - "extra": [ - "Backup anchor to be ready to step in for their product when prompted by the FMs" - ] - }, - { - "time": "1345", - "title": "Last possible time a stream can be started with 30 minute runtime (contingency)", - "extra": [] - }, - { - "time": "1330", - "title": "Stream ends", - "extra": [ - "All crew to the floor for strike", - "When set is de-rigged, all available cast and crew to 3.08 for final words." - ] } ], "notes": [ - "Sioux Sharp (S.Sharp3@salford.ac.uk) and Joe Fowler (J.A.R.Fowler2@salford.ac.uk) will also be in attendance in the gallery, on the floor, or in the green room. To be confirmed with them.", - "Lucas Blackburn's presence (the backup) is to be kept secret from the Anchor, his entrance to the studio is to be facilitated by the cyclorama blocking the Anchors view of the door." + "Rebuilding" ] } diff --git a/static/main.css b/static/main.css new file mode 100644 index 0000000..3c2369a --- /dev/null +++ b/static/main.css @@ -0,0 +1,499 @@ +body { + --magenta: purple; + --blue: violet; + --red: red; + + font-family: "Archivo", sans-serif; + font-size: 1.6vh; + color: var(--black); + + opacity: 0; + transition: opacity 1.5s; + + overflow: hidden; +} +@keyframes spin { + 0% {transform: rotate(0turn) scale(1.2);} + 25% {transform: rotate(0.25turn) scale(1);} + 50% {transform: rotate(0.5turn) scale(1.2);} + 75% {transform: rotate(0.75turn) scale(1);} + 100% {transform: rotate(1turn) scale(1.2);} +} +@keyframes spin1 { + 0% {transform: perspective(100px) rotateY( -25deg ) rotateX(-25deg) rotateZ(0turn) scale(1.2);} + 25% {transform: perspective(100px) rotateY( -25deg ) rotateX(-25deg) rotateZ(0.25turn) scale(1);} + 50% {transform: perspective(100px) rotateY( -25deg ) rotateX(-25deg) rotateZ(0.5turn) scale(1.2);} + 75% {transform: perspective(100px) rotateY( -25deg ) rotateX(-25deg) rotateZ(0.75turn) scale(1);} + 100% {transform: perspective(100px) rotateY( -25deg ) rotateX(-25deg) rotateZ(1turn) scale(1.2);} +} +@keyframes spin2 { + 0% {transform: perspective(100px) rotateY( 20deg ) rotateX(-10deg) rotateZ(0turn) scale(1.2);} + 25% {transform: perspective(100px) rotateY( 20deg ) rotateX(-10deg) rotateZ(0.25turn) scale(1);} + 50% {transform: perspective(100px) rotateY( 20deg ) rotateX(-10deg) rotateZ(0.5turn) scale(1.2);} + 75% {transform: perspective(100px) rotateY( 20deg ) rotateX(-10deg) rotateZ(0.75turn) scale(1);} + 100% {transform: perspective(100px) rotateY( 20deg ) rotateX(-10deg) rotateZ(1turn) scale(1.2);} +} +@keyframes spin3 { + 0% {transform: perspective(100px) rotateY( -20deg ) rotateX(10deg) rotateZ(0turn) scale(1.2);} + 25% {transform: perspective(100px) rotateY( -20deg ) rotateX(10deg) rotateZ(0.25turn) scale(1);} + 50% {transform: perspective(100px) rotateY( -20deg ) rotateX(10deg) rotateZ(0.5turn) scale(1.2);} + 75% {transform: perspective(100px) rotateY( -20deg ) rotateX(10deg) rotateZ(0.75turn) scale(1);} + 100% {transform: perspective(100px) rotateY( -20deg ) rotateX(10deg) rotateZ(1turn) scale(1.2);} +} +@keyframes spin4 { + 0% {transform: perspective(100px) rotateY( 25deg ) rotateX(25deg) rotateZ(0turn) scale(1.2);} + 25% {transform: perspective(100px) rotateY( 25deg ) rotateX(25deg) rotateZ(0.25turn) scale(1);} + 50% {transform: perspective(100px) rotateY( 25deg ) rotateX(25deg) rotateZ(0.5turn) scale(1.2);} + 75% {transform: perspective(100px) rotateY( 25deg ) rotateX(25deg) rotateZ(0.75turn) scale(1);} + 100% {transform: perspective(100px) rotateY( 25deg ) rotateX(25deg) rotateZ(1turn) scale(1.2);} +} +@keyframes spinOffset { + 0% {transform: perspective(200px) translate(-50%, -50%) rotateY( 15deg ) rotateZ(0turn) scale(1.2);} + 25% {transform: perspective(250px) translate(-50%, -50%) rotateY( 15deg ) rotateZ(0.25turn) scale(1);} + 50% {transform: perspective(300px) translate(-50%, -50%) rotateY( 15deg ) rotateZ(0.5turn) scale(1.2);} + 75% {transform: perspective(250px) translate(-50%, -50%) rotateY( 15deg ) rotateZ(0.75turn) scale(1);} + 100% {transform: perspective(200px) translate(-50%, -50%) rotateY( 15deg ) rotateZ(1turn) scale(1.2);} +} +@keyframes spinText { + 0% {transform: rotate(-0.01turn);} + 50% {transform: rotate(0.01turn);} + 100% {transform: rotate(-0.01turn);} +} +@keyframes spinText1 { + 0% {transform: perspective(100px) rotateY( 20deg ) rotateX(-10deg) rotateZ(-0.01turn);} + 50% {transform: perspective(100px) rotateY( 20deg ) rotateX(-10deg) rotateZ(0.01turn);} + 100% {transform: perspective(100px) rotateY( 20deg ) rotateX(-10deg) rotateZ(-0.01turn);} +} +@keyframes spinText2 { + 0% {transform: perspective(100px) rotateY( -20deg ) rotateZ(-0.01turn);} + 50% {transform: perspective(100px) rotateY( -20deg ) rotateZ(0.01turn);} + 100% {transform: perspective(100px) rotateY( -20deg ) rotateZ(-0.01turn);} +} +@keyframes spinText3 { + 0% {transform: perspective(100px) rotateY( 20deg ) rotateZ(-0.01turn);} + 50% {transform: perspective(100px) rotateY( 20deg ) rotateZ(0.01turn);} + 100% {transform: perspective(100px) rotateY( 20deg ) rotateZ(-0.01turn);} +} +@keyframes spinText4 { + 0% {transform: perspective(100px) rotateY( -20deg ) rotateX(10deg) rotateZ(-0.01turn);} + 50% {transform: perspective(100px) rotateY( -20deg ) rotateX(10deg) rotateZ(0.01turn);} + 100% {transform: perspective(100px) rotateY( -20deg ) rotateX(10deg) rotateZ(-0.01turn);} +} +@keyframes spinTextOffset { + 0% {transform: perspective(500px) translateX(-50%) rotateY( -10deg ) rotateZ(-0.01turn);} + 50% {transform: perspective(500px) translateX(-50%) rotateY( -10deg) rotateZ(0.01turn);} + 100% {transform: perspective(500px) translateX(-50%) rotateY( -10deg ) rotateZ(-0.01turn);} +} +@keyframes flicker { + 0% { + color: black; + text-shadow: -2px -2px 0 #FFF, 2px -2px 0 #FFF, -2px 2px 0 #FFF, 2px 2px 0 #FFF; + } + 49.999% { + color: black; + text-shadow: -2px -2px 0 #FFF, 2px -2px 0 #FFF, -2px 2px 0 #FFF, 2px 2px 0 #FFF; + } + 50% { + color: white; + text-shadow: -2px -2px 0 #000, 2px -2px 0 #000, -2px 2px 0 #000, 2px 2px 0 #000; + } + 99.999% { + color: white; + text-shadow: -2px -2px 0 #000, 2px -2px 0 #000, -2px 2px 0 #000, 2px 2px 0 #000; + } + 100% { + color: black; + text-shadow: -2px -2px 0 #FFF, 2px -2px 0 #FFF, -2px 2px 0 #FFF, 2px 2px 0 #FFF; + } +} + +.container { + position: absolute; +} +/*.box { + * box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 3px, rgba(0, 0, 0, 0.24) 0px 1px 2px; + * background-image: var(--background); + } **/ +#side { +left: 6vh; +top: 6vh; +width: 40vh; +opacity: 0; +transition: opacity 1.5s; +} +.soldBox { + margin: 5px; + padding: 5px; + color: blue; + background-color: white; + 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; +font-size: 2em; +line-height: 1em; +color: white; +background-color: var(--magenta); +box-shadow: pink 0px 1px 3px, pink 0px 1px 2px; +} +.main { + background-color: white; + z-index: 0; +} +#subtext { +color: white; +background-color: var(--blue); +} +#banner { +right: 6vh; +top: 6vh; +height: 2em; +width: 0vh; +padding: 0.5vh; +overflow: hidden; +opacity: 0; +transition: opacity 1.5s, width 1.5s, left 1.5s; +color: white; +background-color: var(--magenta); +} +#timer2.moved { +top: 6vh; +} +#timer3.focus { +bottom: calc(50% - 15vh); +right: calc(50% - 15vh); +width: 30vh; +height: 30vh; +border-radius: 15vh; +font-size: 5em; +line-height: 30vh; +} +.extra { + position: relative; + top: -2vh; + z-index: -1; + transform: translateY(-100%); + padding-top: 2vh; + padding-bottom: 1px; + color: white; + background-color: var(--magenta); + transition: transform 1.5s; +} +.showExtra > .extra { + transform: translateY(0%); +} +.main > *, .extra > *:not(.soldBox), .bottom > *, .bottom > div > *, #marquee > * { + margin: 0; + padding: 0.5vh 1vh; +} +#banner > h1 { +width: 49vh; +margin: 0; +font-size: 2em; +line-height: 1; +font-style: italic; +font-weight: bold; +text-align: center; +} +#currentPrice { +color: var(--red); +font-size: 2em; +} +#unitsLeft { +font-size: 3em; +} +#badge1Container { +position: relative; +padding: 0; +transform: translateX(12vh) scale(0%); +transition: transform 1.5s; +} +#badge1Container > img { +position: absolute; +top: -9vh; +left: 36vh; +width: 12vh; +height: 12vh; +padding: 0; +animation: spin1 12s linear 0s infinite; +animation-direction: reverse; +} +#badge1Text { +position: absolute; +top: -7.5vh; +left: 31.5vh; +color: yellow; +width: 22vh; +animation: spinText1 7s linear 0s infinite; +rotate: -0.015turn; +font-size: 2em; +text-align: center; +/*text-shadow: -2px -2px 0 green, 2px -2px 0 green, -2px 2px 0 green, 2px 2px 0 green;*/ +} +#badge2Container { +position: relative; +padding: 0; +transform: translateX(12vh) scale(0%); +transition: transform 1.5s; +} +#badge2Container > img { +position: absolute; +top: -2vh; +left: 32vh; +width: 10vh; +height: 10vh; +padding: 0; +animation: spin2 10s linear 0s infinite; +} +#badge2Text { +position: absolute; +top: -1vh; +left: 26.5vh; +color: black; +width: 20vh; +animation: spinText2 10s linear 0s infinite; +rotate: 0.025turn; +text-align: center; +/*text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;*/ +} +#badge3Container { +position: relative; +padding: 0; +transform: translateX(12vh) scale(0%); +transition: transform 1.5s; +} +#badge3Container > img { +position: absolute; +top: 3vh; +left: 38vh; +width: 10vh; +height: 10vh; +padding: 0; +animation: spin3 10s linear 0s infinite; +animation-direction: reverse; +} +#badge3Text { +position: absolute; +top: 4.9vh; +left: 33.9vh; +color: blue; +width: 20vh; +animation: spinText3 10s linear 0s infinite; +rotate: -0.03turn; +text-align: center; +/*text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;*/ +} +#badge4Container { +position: relative; +padding: 0; +transform: translateX(12vh) scale(0%); +transition: transform 1.5s; +} +#badge4Container > img { +position: absolute; +top: 10vh; +left: 32vh; +width: 14vh; +height: 14vh; +padding: 0; +animation: spin4 10s linear 0s infinite; +} +#badge4Text { +position: absolute; +top: 11.8vh; +left: 28.4vh; +color: #00FF00; +width: 20vh; +animation: spinText4 10s linear 0s infinite; +rotate: 0.025turn; +font-size: 2.2em; +line-height: 0.6em; +text-align: center; +/*text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;*/ +} +#shoutContainer { +position: absolute; +top: 50vh; +left: 50vw; +padding: 0; +} +#shoutBadgeContainer { +opacity: 0; +transform: translateX(-30vw); +transition: opacity 2s ease, transform 2s ease; +} +#shoutContainer.show > #shoutBadgeContainer { +opacity: 1; +transform: translateX(0vw); +} +#shoutTextContainer { +position: absolute; +top: -7vh; +opacity: 0; +transform: translateX(30vw); +transition: opacity 2s ease, transform 2s ease; +animation: flicker 1s linear 0s infinite; +} +#shoutContainer.show > #shoutTextContainer { +opacity: 1; +transform: translateX(0vw); +} +#shoutBadgeContainer > img { +width: 45vh; +height: 45vh; +padding: 0; +animation: spinOffset 10s linear 0s infinite; +} +#shout { +position: absolute; +width: 100vw; +top: 0; +perspective: 400px; +animation: spinTextOffset 10s linear 0s infinite; +rotate: 0.025turn; +font-size: 10em; +text-align: center; +} +#origionalPrice { +line-height: 0.5em; +} +#monthlyPrice { +line-height: 1em; +} +.main > hr, .extra > hr { + margin: 0 1vh; + padding: 0; + border-color: var(--dark); +} +.bottom { + left: 6vh; + bottom: 6vh; + width: 100vh; + background-color: white; +} +.bottom > *:not(#timer1) { + display: inline-block; + vertical-align: top; +} +#topTextBox { +width: calc(100% - 20px); +margin: 5px; +margin-bottom: 0; +padding: 5px; +color: white; +background-color: var(--blue); +box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 3px, rgba(0, 0, 0, 0.19) 0px 1px 2px; +} +#topText { +display: inline-block; +width: 50%; +padding: 0; +} +#idText { +display: inline-block; +width: 50%; +padding: 0; +text-align: right; +font-size: 1.5em; +font-weight: bold; +font-style: italic; +text-shadow: 0 0 3px rgba(0,0,0,0.25); +} +#marquee { +padding: 0; +width: 100%; +mask-image: linear-gradient(0.25turn, transparent, black 5%, black 95%, transparent); +color: var(--magenta); +overflow: hidden; +} +#marqueeText { +white-space: nowrap; +overflow: hidden; +} +#timer1 { +position: absolute; +left: 101vh; +padding: 0.5vh; +opacity: 0; +text-align: center; +color: white; +background-color: var(--magenta); +transition: opacity 1.5s; +} +#timer2 { +position: absolute; +right: calc(6vh + 2px); +top: calc(11.5vh + 2px); +height: 1.2em; +width: 3em; +margin: 0; +text-align: center; +color: black; +font-size: 2em; +font-weight: bold; +line-height: 1.2em; +opacity: 0; +transition: opacity 1.5s, left 1.5s, top 1.5s; +} +#timer3 { +position: absolute; +bottom: 4vh; +right: 4vh; +opacity: 0; +width: 12vh; +height: 12vh; +border-radius: 6vh; +margin: 0; +color: white; +text-align: center; +vertical-align: center; +font-family: "Calculator"; +font-size: 2em; +font-weight: bold; +line-height: 12vh; +opacity: 0; +transition: opacity 1.5s, bottom 1.5s, right 1.5s, width 1.5s, height 1.5s, border-radius 1.5s, font-size 1.5s, line-height 1.5s, transform 1.5s; +animation: spinText 10s linear 0s infinite; +} +.show { + opacity: 1 !important; +} +#badge1Container.show, #badge2Container.show, #badge3Container.show, #badge4Container.show { +transform: translateX(0vh) scale(100%); +} +#banner.show { +width: 50vh; +} +#sigilBox { +opacity: 0; +mix-blend-mode: overlay; +} +#sigilBox.show { +opacity: 1; +} +.sigil { + position: fixed; + top: 50vh; + left: 50vw; + height: 90vh; + transform: translate(-50%, -50%); + opacity: 0; +} +.sigil.show { + opacity: 1; +} +@keyframes spinBox { + 0% {transform: translateY(100%);} + 50% {} + 100% {} + +} diff --git a/static/static.json b/static/static.json index 1aa9009..e83128f 100755 --- a/static/static.json +++ b/static/static.json @@ -50,59 +50,6 @@ "Look", "Doomsday", "It's here!" - ], - "sigil":[ - "anchor", - "thebeast", - "buyitall", - "consumer", - "runners", - "xmdv", - "broadcast", - "bleedout", - "quant", - "bullion", - "adarksun", - "dollar", - "beast" - ], - "square":[ - "110,10", - "90,110", - "50,10", - "70,110", - "30,110", - "10,10", - "10,30", - "90,30", - "70,90", - "50,90", - "30,30", - "110,90", - "110,70", - "30,50", - "70,50", - "50,50", - "90,70", - "10,70", - "10,50", - "30,70", - "70,70", - "50,70", - "90,50", - "110,50", - "10,90", - "90,90", - "50,30", - "70,30", - "30,90", - "110,30", - "110,110", - "30,10", - "50,110", - "70,10", - "90,10", - "10,110" ] }, "items": [ diff --git a/static/utils.js b/static/utils.js index 828e96f..8cc47a2 100644 --- a/static/utils.js +++ b/static/utils.js @@ -1,16 +1,25 @@ -export function makeTime(end, offset, strike) { - let current = Math.round((Date.now() + offset) / 1000); - var time = end - current; +export function makeTime(end) { + let current = Date.now() / 1000; + var time = parseFloat(end) - current; if (Math.sign(time) == -1) {time = 0;} var minutes = Math.floor(time / 60); - var seconds = (time - (minutes * 60)); + var seconds = Math.floor(time - (minutes * 60)); var minutesString = minutes.toString().padStart(2, "0"); var secondsString = seconds.toString().padStart(2, "0"); - if (strike) { - return `${minutesString}:${secondsString}`; - } else { - return `${minutesString}:${secondsString}`; - } + + return `${minutesString}:${secondsString}`; +} + +export function getTime(end) { + let current = Date.now() / 1000; + var time = parseFloat(end) - current; + + if (Math.sign(time) == -1) {time = 0;} + var minutes = Math.floor(time / 60); + var secondsFull = time - (minutes * 60); + var seconds = Math.floor(secondsFull); + + return [minutes, seconds, secondsFull] } diff --git a/teleshopping/admin.py b/teleshopping/admin.py index ad1d1d0..c409b33 100644 --- a/teleshopping/admin.py +++ b/teleshopping/admin.py @@ -1,4 +1,5 @@ from flask import Flask, Response, request, render_template, send_from_directory +from datetime import datetime, timezone from math import radians, cos, sin from .api.data import data as api from flask_socketio import emit diff --git a/teleshopping/api/data.py b/teleshopping/api/data.py index 7be9dc3..47c0571 100644 --- a/teleshopping/api/data.py +++ b/teleshopping/api/data.py @@ -10,37 +10,32 @@ with open(f"{ROOT}/static/static.json", "r", encoding="utf-8") as f: static_data = json.loads(f.read()) def data(): - if request.method in ["GET", "internal"]: - data = database("*") - - focus_extra = {} - for key, value in data.items(): - if key[:4] == "bool": data[key] = bool(value) # if the key starts with "bool" make the data a bool - elif key[:4] == "list": data[key] = literal_eval(value) # if the key starts with "list" make the data a literal list - elif key[:5] == "focus": # if the key starts with "focus" make the data into a bool with an additional dict entry for "showing" bool - data[key] = bool((value-1)+abs(value-1)) # if 2 then True, if 1,0 then False - focus_extra[f"bool_{key[6:]}"] = bool(value) # if 1,2 then True, if 0 then False - data |= focus_extra - - if request.method == "internal": return data - return jsonify(data) - else: - return "", 404 - -def handle_message(message): - send(message) + data = database("*") -def items(): - if request.method == "GET": - return jsonify(static_data) + focus_extra = {} + for key, value in data.items(): + if key[:4] == "bool": + # if the key starts with "bool" make the data a bool + data[key] = bool(value) - else: - return "", 404 + elif key[:4] == "list": + # if the key starts with "list" make the data a literal list + data[key] = literal_eval(value) -def clock(): - if request.method == "GET": - keys = ["current_position", "movement_speed", "movement_function"] - return jsonify(database(keys)) + elif key[:5] == "focus": + # if the key starts with "focus" change the data from a tertiary value representing + # whether the element is showing and whether the element is currently focused + data[key] = bool((value-1)+abs(value-1)) # if 2 then True, if 1,0 then False + focus_extra[f"bool_{key[6:]}"] = bool(value) # if 1,2 then True, if 0 then False + + data |= focus_extra + + if request.method == "internal": return data + return jsonify(data) - else: - return "", 404 +def items(): + return jsonify(static_data) + +def clock(): + keys = ["current_position", "movement_speed", "movement_function"] + return jsonify(database(keys)) diff --git a/teleshopping/api/utils.py b/teleshopping/api/utils.py index b29cf1b..8144e64 100644 --- a/teleshopping/api/utils.py +++ b/teleshopping/api/utils.py @@ -45,10 +45,8 @@ def docs_generate(): with open(f"{docs_path}/documentation.html", "w", encoding="utf-8") as f: f.write(render_template("docs.html", data=static_data, info=static_info, book=True)) - floorplan_path = f"{ROOT}/static/floorplan.png" - cameras_path = f"{ROOT}/static/cameras.png" - system(f"cp '{floorplan_path}' '{docs_path}'") - system(f"cp '{cameras_path}' '{docs_path}'") + system(f"cp '{ROOT}/static/floorplan.png' '{docs_path}'") + system(f"cp '{ROOT}/static/cameras.png' '{docs_path}'") for book_type in ["epub", "mobi"]: system(f""" diff --git a/teleshopping/pages.py b/teleshopping/pages.py index cc56076..fc67b3f 100644 --- a/teleshopping/pages.py +++ b/teleshopping/pages.py @@ -30,7 +30,7 @@ def autocue(): ) def hud(): - return Response(render_template("display.html"), mimetype="text/html") + return Response(render_template("hud.html"), mimetype="text/html") def sounds(): return Response(render_template("sounds.html"), mimetype="text/html") diff --git a/templates/admin.html b/templates/admin.html index 0eb6c93..278e664 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -13,7 +13,7 @@
diff --git a/templates/clock.html b/templates/clock.html index 114892c..b6facb7 100644 --- a/templates/clock.html +++ b/templates/clock.html @@ -4,6 +4,23 @@ XMDV Admin - Doomsday + - + .. Back to admin pannel
@@ -178,66 +195,60 @@ function mainTimer (value) { else {checkbox.checked = false;} } -function update() { - fetch("/api", {cache: "no-store"}) - .then(data => data.json()) - .then(data => { - for (let t = 0; t <= {{positions|length}}; t++) { - const timer = document.getElementById(t); - const incrementTime = Math.round(timeTotal / {{positions|length}}); - - let current = Math.round((Date.now() + data['timer_offset']) / 1000); - var time = (data["end_timer_main"] - current) + (t * incrementTime); - - let negate = ""; - if (time > 0) { - var minutes = Math.floor(time / 60); - var seconds = (time - (minutes * 60)); - } else { - var minutes = Math.ceil(time / 60); - var seconds = -(time - (minutes * 60)); - negate = "-"; - } - if (minutes < 0) {seconds = 60 - seconds;} // reverse tick if in the past - - var minutesString = negate + minutes.toString().padStart(2, "0"); - var secondsString = seconds.toString().padStart(2, "0"); - - timer.innerHTML = `T-${minutesString}:${secondsString}`.replace("--","+"); - if (minutes < 1) { - if (time <= 0) {timer.style.color = "red";} - else if (seconds % 2 == 0) {timer.style.color = "green";} - else {timer.style.color = "orange";} - } else { - timer.style.color = "green"; - } - - if (t == - {% for p in positions %} - {% if p.i == data.current_position %} - {{loop.index}} - {% endif %} - {% endfor %} - ) { - document.getElementById("next").innerHTML = `T-${minutesString}:${secondsString}`.replace("--","+"); - - const nextLabel = document.getElementById("nextLabel"); - if (minutes < 1) { - if (time <= 0) {nextLabel.style.color = "red";} - else if (seconds % 2 == 0) {nextLabel.style.color = "green";} - else {nextLabel.style.color = "orange";} - } else { - nextLabel.style.color = "green"; - } - - var date = new Date(data["end_timer_main"] * 1000); - document.getElementById("start").innerHTML = `${date.getHours()}:${date.getMinutes()}`; - } +function update( data ) { + for (let t = 0; t <= {{positions|length}}; t++) { + const timer = document.getElementById(t); + const incrementTime = Math.round(timeTotal / {{positions|length}}); + + let current = Math.round((Date.now() + data['timer_offset']) / 1000); + var time = (data["end_timer_main"] - current) + (t * incrementTime); + + let negate = ""; + if (time > 0) { + var minutes = Math.floor(time / 60); + var seconds = (time - (minutes * 60)); + } else { + var minutes = Math.ceil(time / 60); + var seconds = -(time - (minutes * 60)); + negate = "-"; + } + if (minutes < 0) {seconds = 60 - seconds;} // reverse tick if in the past + + var minutesString = negate + minutes.toString().padStart(2, "0"); + var secondsString = seconds.toString().padStart(2, "0"); + + timer.innerHTML = `T-${minutesString}:${secondsString}`.replace("--","+"); + if (minutes < 1) { + if (time <= 0) {timer.style.color = "red";} + else if (seconds % 2 == 0) {timer.style.color = "green";} + else {timer.style.color = "orange";} + } else { + timer.style.color = "green"; + } + + if (t == + {% for p in positions %} + {% if p.i == data.current_position %} + {{loop.index}} + {% endif %} + {% endfor %} + ) { + document.getElementById("next").innerHTML = `T-${minutesString}:${secondsString}`.replace("--","+"); + + const nextLabel = document.getElementById("nextLabel"); + if (minutes < 1) { + if (time <= 0) {nextLabel.style.color = "red";} + else if (seconds % 2 == 0) {nextLabel.style.color = "green";} + else {nextLabel.style.color = "orange";} + } else { + nextLabel.style.color = "green"; } - }); -} -setInterval(update, 1000) + var date = new Date(data["end_timer_main"] * 1000); + document.getElementById("start").innerHTML = `${date.getHours()}:${date.getMinutes()}`; + } + } +} diff --git a/templates/display.html b/templates/display.html deleted file mode 100644 index 57be682..0000000 --- a/templates/display.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - XMDV Display - - - - - -
- T1: 00:00 - - T2: 00:00 - - T3: 00:00
- Left: 0 out of 0
- Start price: 0.00 - ⤓00% - ⤈00%
- Discount: 00% (Now 0.00) -
- - - diff --git a/templates/gfx.html b/templates/gfx.html index 5878c58..cb23831 100644 --- a/templates/gfx.html +++ b/templates/gfx.html @@ -4,512 +4,72 @@ XMDV Teleshopping - - + - + @@ -555,7 +115,7 @@ body {

-
+