From 18aa4fa369b765e93f5e1a3f9b05887126f9cafc Mon Sep 17 00:00:00 2001 From: Florens Douwes Date: Fri, 24 Apr 2020 20:59:27 +0200 Subject: [PATCH] backend in typescript, andere manier van tijdsynchronisatie en syncen van state backend is nu in typescript met de classes georganiseerd de manier van synchronisatie is nu gebaseerd op het synchroniseren van de tijd van de server en client, zodat er minder communicatie nodig is vanuit de server --- backend/Dockerfile | 2 +- backend/data/timeline.js | 2725 --------------------- backend/data/timelines.js | 2733 ++++++++++++++++++++++ backend/package-lock.json | 134 ++ backend/package.json | 9 +- backend/src/Lobby.js | 160 -- backend/src/Room.ts | 186 ++ backend/src/Service.ts | 120 + backend/src/State.js | 59 - backend/src/User.js | 5 - backend/src/User.ts | 77 + backend/src/app.js | 22 - backend/src/index.js | 80 - backend/src/index.ts | 175 ++ backend/src/service.js | 68 - backend/src/{timeline.js => timeline.ts} | 24 +- backend/src/util.js | 15 - backend/src/util.ts | 20 + backend/tsconfig.json | 8 + frontend/package-lock.json | 730 ++---- frontend/package.json | 3 +- frontend/src/components/App.tsx | 5 +- frontend/src/components/Centurion.tsx | 66 +- frontend/src/components/Feed.tsx | 51 +- frontend/src/components/FeedItem.tsx | 33 +- frontend/src/components/Lobby.tsx | 229 +- frontend/src/components/NextShot.tsx | 40 +- frontend/src/components/Player.ts | 32 + frontend/src/components/ShotsTaken.tsx | 20 +- frontend/src/css/index.sass | 2 +- frontend/src/css/lobby.sass | 68 +- frontend/src/lib/Connection.ts | 321 +++ frontend/src/types/types.ts | 41 + frontend/src/util/hooks.ts | 11 + frontend/src/util/socket.ts | 19 - frontend/src/util/sub.ts | 40 + 36 files changed, 4478 insertions(+), 3855 deletions(-) delete mode 100644 backend/data/timeline.js create mode 100644 backend/data/timelines.js delete mode 100644 backend/src/Lobby.js create mode 100644 backend/src/Room.ts create mode 100644 backend/src/Service.ts delete mode 100644 backend/src/State.js delete mode 100644 backend/src/User.js create mode 100644 backend/src/User.ts delete mode 100644 backend/src/app.js delete mode 100644 backend/src/index.js create mode 100644 backend/src/index.ts delete mode 100644 backend/src/service.js rename backend/src/{timeline.js => timeline.ts} (64%) delete mode 100644 backend/src/util.js create mode 100644 backend/src/util.ts create mode 100644 backend/tsconfig.json create mode 100644 frontend/src/components/Player.ts create mode 100644 frontend/src/lib/Connection.ts create mode 100644 frontend/src/util/hooks.ts create mode 100644 frontend/src/util/sub.ts diff --git a/backend/Dockerfile b/backend/Dockerfile index 5074e7d..8635046 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -6,4 +6,4 @@ RUN yarn install COPY src src/ COPY data data/ -CMD ["node", "src/index.js"] +CMD ["npm", "run", "app"] diff --git a/backend/data/timeline.js b/backend/data/timeline.js deleted file mode 100644 index 99857a2..0000000 --- a/backend/data/timeline.js +++ /dev/null @@ -1,2725 +0,0 @@ -module.exports = [ - { - "timestamp": 0, - "events": [ - { - "type": "talk", - "text": [ - "Zet je schrap!", - "We gaan zo beginnen" - ] - } - ] - }, - { - "timestamp": 42, - "events": [ - { - "type": "talk", - "text": [ - "Daar gaan we!", - "Dit was het startsein, je hoeft nog niet te drinken" - ] - }, - { - "type": "song", - "text": [ - "Nena", - "99 Luftballons" - ] - } - ] - }, - { - "timestamp": 108, - "events": [ - { - "type": "shot", - "text": [ - "De eerste!", - "Nog 99 shotjes" - ], - "shotCount": 1 - } - ] - }, - { - "timestamp": 148, - "events": [ - { - "type": "song", - "text": [ - "Hermes House Band", - "Country Roads" - ] - } - ] - }, - { - "timestamp": 167, - "events": [ - { - "type": "shot", - "text": [ - "Nummertje twee!", - "Nog 98 shotjes" - ], - "shotCount": 2 - } - ] - }, - { - "timestamp": 185, - "events": [ - { - "type": "song", - "text": [ - "Vinzzent", - "Dromendans" - ] - } - ] - }, - { - "timestamp": 223, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 97 shotjes" - ], - "shotCount": 3 - }, - { - "type": "song", - "text": [ - "Linda, Roos & Jessica", - "Ademnood" - ] - } - ] - }, - { - "timestamp": 283, - "events": [ - { - "type": "shot", - "text": [ - "Lustrum!", - "Nog 96 shotjes" - ], - "shotCount": 4 - }, - { - "type": "song", - "text": [ - "Peter de Koning", - "Het is altijd lente in de ogen van de tandarts-assistente" - ] - } - ] - }, - { - "timestamp": 340, - "events": [ - { - "type": "shot", - "text": [ - "Niet gooien!", - "Nog 95 shotjes" - ], - "shotCount": 5 - }, - { - "type": "song", - "text": [ - "Liquido", - "Narcotic" - ] - } - ] - }, - { - "timestamp": 412, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 94 shotjes" - ], - "shotCount": 6 - }, - { - "type": "song", - "text": [ - "Snoop Dogg feat. Pharrell", - "Drop It Like It's Hot" - ] - } - ] - }, - { - "timestamp": 449, - "events": [ - { - "type": "song", - "text": [ - "M.O.P.", - "Ante Up" - ] - } - ] - }, - { - "timestamp": 459, - "events": [ - { - "type": "shot", - "text": [ - "Pweeeep!", - "Nog 93 shotjes" - ], - "shotCount": 7 - } - ] - }, - { - "timestamp": 514, - "events": [ - { - "type": "shot", - "text": [ - "Trek een ad!", - "Nog 92 shotjes" - ], - "shotCount": 8 - }, - { - "type": "song", - "text": [ - "Los Del Rio", - "Macarena" - ] - } - ] - }, - { - "timestamp": 560, - "events": [ - { - "type": "song", - "text": [ - "Spice Girls", - "Wannabe" - ] - } - ] - }, - { - "timestamp": 574, - "events": [ - { - "type": "shot", - "text": [ - "We zijn er nog lang niet!", - "Nog 91 shotjes" - ], - "shotCount": 9 - } - ] - }, - { - "timestamp": 617, - "events": [ - { - "type": "song", - "text": [ - "Major Lazer feat. Busy Signal, The Flexican & FS Green", - "Watch Out For This (Bumaye)" - ] - } - ] - }, - { - "timestamp": 635, - "events": [ - { - "type": "shot", - "text": [ - "Nummer tien!", - "Nog 90 shotjes" - ], - "shotCount": 10 - } - ] - }, - { - "timestamp": 647, - "events": [ - { - "type": "time", - "text": [ - "Nog 90 minuten!", - "Geef alles, behalve op" - ] - } - ] - }, - { - "timestamp": 684, - "events": [ - { - "type": "song", - "text": [ - "Kabouter Plop", - "Kabouterdans" - ] - } - ] - }, - { - "timestamp": 699, - "events": [ - { - "type": "shot", - "text": [ - "Met vriendelijke toet!", - "Nog 89 shotjes" - ], - "shotCount": 11 - } - ] - }, - { - "timestamp": 725, - "events": [ - { - "type": "song", - "text": [ - "K3", - "Alle kleuren" - ] - } - ] - }, - { - "timestamp": 756, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 88 shotjes" - ], - "shotCount": 12 - } - ] - }, - { - "timestamp": 757, - "events": [ - { - "type": "song", - "text": [ - "Kinderen voor Kinderen", - "Tietenlied" - ] - } - ] - }, - { - "timestamp": 812, - "events": [ - { - "type": "shot", - "text": [ - "Ongeluksshotje 13!", - "Nog 87 shotjes" - ], - "shotCount": 13 - } - ] - }, - { - "timestamp": 814, - "events": [ - { - "type": "song", - "text": [ - "Guus Meeuwis", - "Het dondert en het bliksemt" - ] - } - ] - }, - { - "timestamp": 820, - "events": [ - { - "type": "talk", - "text": [ - "Carnaval is prachtig!", - "Schrijf je snel in op svia.nl/carnaval" - ] - } - ] - }, - { - "timestamp": 874, - "events": [ - { - "type": "shot", - "text": [ - "Pweeeep!", - "Nog 86 shotjes" - ], - "shotCount": 14 - } - ] - }, - { - "timestamp": 876, - "events": [ - { - "type": "song", - "text": [ - "Harry Vermeegen", - "1-2-3-4 Dennis bier" - ] - } - ] - }, - { - "timestamp": 906, - "events": [ - { - "type": "song", - "text": [ - "Puhdys", - "Hey, wir woll’n die Eisbär'n sehn!" - ] - } - ] - }, - { - "timestamp": 935, - "events": [ - { - "type": "shot", - "text": [ - "Fünfzehn!", - "Nog 85 shotjes" - ], - "shotCount": 15 - } - ] - }, - { - "timestamp": 966, - "events": [ - { - "type": "song", - "text": [ - "DJ Ötzi", - "Burger Dance" - ] - } - ] - }, - { - "timestamp": 995, - "events": [ - { - "type": "shot", - "text": [ - "Toet!", - "Nog 84 shotjes" - ], - "shotCount": 16 - } - ] - }, - { - "timestamp": 996, - "events": [ - { - "type": "song", - "text": [ - "Mickie Krause", - "Hütte auf der Alm" - ] - } - ] - }, - { - "timestamp": 1030, - "events": [ - { - "type": "song", - "text": [ - "Ali B & Yes-R & The Partysquad", - "Rampeneren" - ] - } - ] - }, - { - "timestamp": 1046, - "events": [ - { - "type": "shot", - "text": [ - "Zuipen!", - "Nog 83 shotjes" - ], - "shotCount": 17 - } - ] - }, - { - "timestamp": 1107, - "events": [ - { - "type": "shot", - "text": [ - "Met dank aan bestuur 18; super 'vo", - "Nog 82 shotjes" - ], - "shotCount": 18 - }, - { - "type": "song", - "text": [ - "Martin Solveig", - "Intoxicated" - ] - } - ] - }, - { - "timestamp": 1137, - "events": [ - { - "type": "song", - "text": [ - "Nicki Minaj", - "Starships" - ] - } - ] - }, - { - "timestamp": 1173, - "events": [ - { - "type": "shot", - "text": [ - "Laatste shotje als tiener!", - "Nog 81 shotjes" - ], - "shotCount": 19 - } - ] - }, - { - "timestamp": 1222, - "events": [ - { - "type": "song", - "text": [ - "2Unlimited", - "Get Ready For This" - ] - } - ] - }, - { - "timestamp": 1233, - "events": [ - { - "type": "time", - "text": [ - "Nog 80 minuten!", - "Al 19 shotjes achter de rug" - ] - } - ] - }, - { - "timestamp": 1235, - "events": [ - { - "type": "shot", - "text": [ - "Adje!", - "Nog 80 shotjes" - ], - "shotCount": 20 - } - ] - }, - { - "timestamp": 1275, - "events": [ - { - "type": "song", - "text": [ - "The Village People", - "YMCA" - ] - } - ] - }, - { - "timestamp": 1288, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 79 shotjes" - ], - "shotCount": 21 - } - ] - }, - { - "timestamp": 1348, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 78 shotjes" - ], - "shotCount": 22 - } - ] - }, - { - "timestamp": 1350, - "events": [ - { - "type": "song", - "text": [ - "Carly Rae Jepsen ft Owl City", - "It's Always A Good Time" - ] - } - ] - }, - { - "timestamp": 1395, - "events": [ - { - "type": "song", - "text": [ - "Avicii", - "Levels" - ] - } - ] - }, - { - "timestamp": 1411, - "events": [ - { - "type": "shot", - "text": [ - "Claxon!", - "Nog 77 shotjes" - ], - "shotCount": 23 - } - ] - }, - { - "timestamp": 1456, - "events": [ - { - "type": "song", - "text": [ - "Flo-Rida feat. T-Pain", - "Low" - ] - } - ] - }, - { - "timestamp": 1471, - "events": [ - { - "type": "shot", - "text": [ - "En nu even op standje maximaal!", - "Nog 76 shotjes" - ], - "shotCount": 24 - } - ] - }, - { - "timestamp": 1486, - "events": [ - { - "type": "song", - "text": [ - "Taio Cruz", - "Hangover" - ] - } - ] - }, - { - "timestamp": 1522, - "events": [ - { - "type": "talk", - "text": [ - "Dit is nog het rustige stukje!", - "Zet hem maar op de bonk-bonk" - ] - } - ] - }, - { - "timestamp": 1530, - "events": [ - { - "type": "shot", - "text": [ - "Halve Abraham!", - "Nog 75 shotjes" - ], - "shotCount": 25 - } - ] - }, - { - "timestamp": 1545, - "events": [ - { - "type": "song", - "text": [ - "LMFAO", - "Party Rock Anthem" - ] - } - ] - }, - { - "timestamp": 1594, - "events": [ - { - "type": "shot", - "text": [ - "Hoch die Hände!", - "Nog 74 shotjes" - ], - "shotCount": 26 - }, - { - "type": "song", - "text": [ - "Hans Entertainment vs. Finger & Kadel", - "Hoch die Hände" - ] - } - ] - }, - { - "timestamp": 1623, - "events": [ - { - "type": "song", - "text": [ - "Galantis", - "No Money" - ] - } - ] - }, - { - "timestamp": 1653, - "events": [ - { - "type": "shot", - "text": [ - "Voel je 'm al?", - "Nog 73 shotjes" - ], - "shotCount": 27 - } - ] - }, - { - "timestamp": 1683, - "events": [ - { - "type": "song", - "text": [ - "Kid Cudi", - "Pursuit of Happiness (Steve Aoki remix)" - ] - } - ] - }, - { - "timestamp": 1712, - "events": [ - { - "type": "shot", - "text": [ - "Project X!", - "Nog 72 shotjes" - ], - "shotCount": 28 - } - ] - }, - { - "timestamp": 1741, - "events": [ - { - "type": "song", - "text": [ - "Yeah Yeah Yeahs", - "Heads Will Roll (A-Trak remix)" - ] - } - ] - }, - { - "timestamp": 1769, - "events": [ - { - "type": "shot", - "text": [ - "Pweeeep!", - "Nog 71 shotjes" - ], - "shotCount": 29 - } - ] - }, - { - "timestamp": 1814, - "events": [ - { - "type": "song", - "text": [ - "Michael Calfan", - "Resurrection" - ] - } - ] - }, - { - "timestamp": 1825, - "events": [ - { - "type": "time", - "text": [ - "Nog 70 minuten!", - "Half uurtje zit erop" - ] - } - ] - }, - { - "timestamp": 1829, - "events": [ - { - "type": "shot", - "text": [ - "Toet!", - "Nog 70 shotjes" - ], - "shotCount": 30 - } - ] - }, - { - "timestamp": 1858, - "events": [ - { - "type": "song", - "text": [ - "Basto!", - "Again and Again" - ] - } - ] - }, - { - "timestamp": 1887, - "events": [ - { - "type": "shot", - "text": [ - "Over de dertig!", - "Nog 69 (hehe) shotjes" - ], - "shotCount": 31 - } - ] - }, - { - "timestamp": 1916, - "events": [ - { - "type": "song", - "text": [ - "David Guetaa feat. Sia", - "Titanium" - ] - } - ] - }, - { - "timestamp": 1945, - "events": [ - { - "type": "shot", - "text": [ - "Trek een ad!", - "Nog 68 shotjes" - ], - "shotCount": 32 - } - ] - }, - { - "timestamp": 1959, - "events": [ - { - "type": "song", - "text": [ - "Gala", - "Freed From Desire" - ] - } - ] - }, - { - "timestamp": 2004, - "events": [ - { - "type": "shot", - "text": [ - "Nummertje 33!", - "Nog 67 shotjes!" - ], - "shotCount": 33 - } - ] - }, - { - "timestamp": 2034, - "events": [ - { - "type": "song", - "text": [ - "Wolter Kroes", - "Viva Hollandia" - ] - } - ] - }, - { - "timestamp": 2064, - "events": [ - { - "type": "shot", - "text": [ - "Voor het vaderland!", - "Nog 66 shotjes" - ], - "shotCount": 34 - } - ] - }, - { - "timestamp": 2125, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 65 shotjes" - ], - "shotCount": 35 - } - ] - }, - { - "timestamp": 2128, - "events": [ - { - "type": "song", - "text": [ - "Westlife", - "Uptown Girl" - ] - } - ] - }, - { - "timestamp": 2179, - "events": [ - { - "type": "song", - "text": [ - "Aqua", - "Barbie Girl" - ] - } - ] - }, - { - "timestamp": 2194, - "events": [ - { - "type": "shot", - "text": [ - "Pweeeep!", - "Nog 64 shotjes" - ], - "shotCount": 36 - } - ] - }, - { - "timestamp": 2225, - "events": [ - { - "type": "song", - "text": [ - "Guillerma & Tropical Danny", - "Toppertje" - ] - } - ] - }, - { - "timestamp": 2245, - "events": [ - { - "type": "shot", - "text": [ - "In dat keelgaatje!", - "Nog 63 shotjes" - ], - "shotCount": 37 - } - ] - }, - { - "timestamp": 2305, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 62 shotjes" - ], - "shotCount": 38 - }, - { - "type": "song", - "text": [ - "The Bloody Beetroots feat. Steve Aoki", - "Warp 1.9" - ] - } - ] - }, - { - "timestamp": 2374, - "events": [ - { - "type": "shot", - "text": [ - "Toet!", - "Nog 61 shotjes" - ], - "shotCount": 39 - }, - { - "type": "song", - "text": [ - "David Guetta & Showtek feat. Vassy", - "Bad" - ] - } - ] - }, - { - "timestamp": 2431, - "events": [ - { - "type": "shot", - "text": [ - "40 alweer!", - "Nog 60 shotjes" - ], - "shotCount": 40 - }, - { - "type": "song", - "text": [ - "Showtek & Justin Prime", - "Cannonball" - ] - } - ] - }, - { - "timestamp": 2444, - "events": [ - { - "type": "time", - "text": [ - "Nog 60 minuten!", - "Een klein uurtje" - ] - } - ] - }, - { - "timestamp": 2460, - "events": [ - { - "type": "song", - "text": [ - "Die Atzen", - "Disco Pogo" - ] - } - ] - }, - { - "timestamp": 2489, - "events": [ - { - "type": "shot", - "text": [ - "Zuipen!", - "Nog 59 shotjes" - ], - "shotCount": 41 - } - ] - }, - { - "timestamp": 2534, - "events": [ - { - "type": "song", - "text": [ - "Lorenz Büffel", - "Johnny Däpp" - ] - } - ] - }, - { - "timestamp": 2555, - "events": [ - { - "type": "shot", - "text": [ - "Dab dat glas naar je mond!", - "Nog 58 shotjes" - ], - "shotCount": 42 - } - ] - }, - { - "timestamp": 2587, - "events": [ - { - "type": "song", - "text": [ - "Zware Jongens", - "Jodeljump" - ] - } - ] - }, - { - "timestamp": 2606, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 57 shotjes" - ], - "shotCount": 43 - } - ] - }, - { - "timestamp": 2635, - "events": [ - { - "type": "song", - "text": [ - "Parla & Pardoux", - "Liberté" - ] - } - ] - }, - { - "timestamp": 2664, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 56 shotjes" - ], - "shotCount": 44 - } - ] - }, - { - "timestamp": 2695, - "events": [ - { - "type": "song", - "text": [ - "Markus Becker", - "Das rote Pferd" - ] - } - ] - }, - { - "timestamp": 2729, - "events": [ - { - "type": "shot", - "text": [ - "Pweeeep!", - "Nog 55 shotjes" - ], - "shotCount": 45 - } - ] - }, - { - "timestamp": 2743, - "events": [ - { - "type": "song", - "text": [ - "Olaf Henning", - "Cowboy und Indianer" - ] - } - ] - }, - { - "timestamp": 2784, - "events": [ - { - "type": "shot", - "text": [ - "Adje!", - "Nog 54 shotjes" - ], - "shotCount": 46 - } - ] - }, - { - "timestamp": 2785, - "events": [ - { - "type": "song", - "text": [ - "Ch!pz", - "Cowboy" - ] - } - ] - }, - { - "timestamp": 2824, - "events": [ - { - "type": "song", - "text": [ - "Toy-Box", - "Tarzan & Jane" - ] - } - ] - }, - { - "timestamp": 2850, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 53 shotjes" - ], - "shotCount": 47 - } - ] - }, - { - "timestamp": 2879, - "events": [ - { - "type": "song", - "text": [ - "Toy-Box", - "Sailor Song" - ] - } - ] - }, - { - "timestamp": 2919, - "events": [ - { - "type": "shot", - "text": [ - "Bijna op de helft!", - "Nog 52 shotjes" - ], - "shotCount": 48 - } - ] - }, - { - "timestamp": 2921, - "events": [ - { - "type": "song", - "text": [ - "Vengaboys", - "Boom, Boom, Boom, Boom!!" - ] - } - ] - }, - { - "timestamp": 2975, - "events": [ - { - "type": "shot", - "text": [ - "Bam!", - "Nog 51 shotjes" - ], - "shotCount": 49 - } - ] - }, - { - "timestamp": 2998, - "events": [ - { - "type": "song", - "text": [ - "Vengaboys", - "To Brazil!" - ] - } - ] - }, - { - "timestamp": 3024, - "events": [ - { - "type": "time", - "text": [ - "Nog 50 minuten!", - "We zijn op de helft!" - ] - } - ] - }, - { - "timestamp": 3039, - "events": [ - { - "type": "shot", - "text": [ - "Abraham!", - "Nog 50 shotjes" - ], - "shotCount": 50 - } - ] - }, - { - "timestamp": 3070, - "events": [ - { - "type": "song", - "text": [ - "Snollebollekes", - "Bam bam (bam)" - ] - } - ] - }, - { - "timestamp": 3104, - "events": [ - { - "type": "shot", - "text": [ - "Tweede helft!", - "Nog 49 shotjes" - ], - "shotCount": 51 - } - ] - }, - { - "timestamp": 3120, - "events": [ - { - "type": "song", - "text": [ - "Def Rhymz", - "Schudden" - ] - } - ] - }, - { - "timestamp": 3160, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 48 shotjes" - ], - "shotCount": 52 - } - ] - }, - { - "timestamp": 3190, - "events": [ - { - "type": "song", - "text": [ - "Cooldown Café", - "Hey baby" - ] - } - ] - }, - { - "timestamp": 3215, - "events": [ - { - "type": "shot", - "text": [ - "Pweeeep!", - "Nog 47 shotjes" - ], - "shotCount": 53 - } - ] - }, - { - "timestamp": 3232, - "events": [ - { - "type": "song", - "text": [ - "Gebroeders Ko", - "Schatje, mag ik je foto" - ] - } - ] - }, - { - "timestamp": 3279, - "events": [ - { - "type": "shot", - "text": [ - "Zuipen!", - "Nog 46 shotjes" - ], - "shotCount": 54 - }, - { - "type": "song", - "text": [ - "Guus Meeuwis", - "Het is een nacht" - ] - } - ] - }, - { - "timestamp": 3341, - "events": [ - { - "type": "shot", - "text": [ - "Adje!", - "Nog 45 shotjes" - ], - "shotCount": 55 - } - ] - }, - { - "timestamp": 3356, - "events": [ - { - "type": "song", - "text": [ - "Tom Waes", - "Dos cervezas" - ] - } - ] - }, - { - "timestamp": 3398, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 44 shotjes" - ], - "shotCount": 56 - } - ] - }, - { - "timestamp": 3412, - "events": [ - { - "type": "song", - "text": [ - "Peter Wackel", - "Vollgas" - ] - } - ] - }, - { - "timestamp": 3439, - "events": [ - { - "type": "song", - "text": [ - "Peter Wackel", - "Scheiß drauf!" - ] - } - ] - }, - { - "timestamp": 3465, - "events": [ - { - "type": "shot", - "text": [ - "Hard gaan!", - "Nog 43 shotjes" - ], - "shotCount": 57 - } - ] - }, - { - "timestamp": 3467, - "events": [ - { - "type": "song", - "text": [ - "Ikke Hüftgold", - "Dicke titten, kartoffelsalat" - ] - } - ] - }, - { - "timestamp": 3520, - "events": [ - { - "type": "shot", - "text": [ - "Hap, slok, weg!", - "Nog 42 shotjes" - ], - "shotCount": 58 - } - ] - }, - { - "timestamp": 3521, - "events": [ - { - "type": "song", - "text": [ - "Tim Toupet", - "Fliegerlied (So ein schöner Tag)" - ] - } - ] - }, - { - "timestamp": 3564, - "events": [ - { - "type": "song", - "text": [ - "Cooldown Café", - "Met z'n allen" - ] - } - ] - }, - { - "timestamp": 3577, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 41 shotjes" - ], - "shotCount": 59 - } - ] - }, - { - "timestamp": 3636, - "events": [ - { - "type": "time", - "text": [ - "Nog 40 minuten!", - "Uurtje achter de rug" - ] - } - ] - }, - { - "timestamp": 3643, - "events": [ - { - "type": "shot", - "text": [ - "Glas 60!", - "Nog 40 shotjes" - ], - "shotCount": 60 - } - ] - }, - { - "timestamp": 3659, - "events": [ - { - "type": "song", - "text": [ - "The Partysquad feat. Jayh, Sjaak & Reverse", - "Helemaal naar de klote" - ] - } - ] - }, - { - "timestamp": 3687, - "events": [ - { - "type": "song", - "text": [ - "K-Liber", - "Viben" - ] - } - ] - }, - { - "timestamp": 3700, - "events": [ - { - "type": "shot", - "text": [ - "Adje!", - "Nog 39 shotjes" - ], - "shotCount": 61 - } - ] - }, - { - "timestamp": 3753, - "events": [ - { - "type": "shot", - "text": [ - "Pweeeep!", - "Nog 38 shotjes" - ], - "shotCount": 62 - } - ] - }, - { - "timestamp": 3755, - "events": [ - { - "type": "song", - "text": [ - "FeestDJRuud & Dirtcaps feat. Sjaak & Kraantje Pappie", - "Weekend" - ] - } - ] - }, - { - "timestamp": 3808, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 37 shotjes" - ], - "shotCount": 63 - }, - { - "type": "song", - "text": [ - "Lawineboys", - "Joost" - ] - } - ] - }, - { - "timestamp": 3860, - "events": [ - { - "type": "song", - "text": [ - "Gebroeders Ko", - "Ik heb een toeter op mijn waterscooter" - ] - } - ] - }, - { - "timestamp": 3874, - "events": [ - { - "type": "shot", - "text": [ - "Toe-toe-toeter!", - "Nog 36 shotjes" - ], - "shotCount": 64 - } - ] - }, - { - "timestamp": 3904, - "events": [ - { - "type": "song", - "text": [ - "Gebroeders Ko", - "Tringeling" - ] - } - ] - }, - { - "timestamp": 3931, - "events": [ - { - "type": "shot", - "text": [ - "Tringeling!", - "Nog 35 shotjes" - ], - "shotCount": 65 - } - ] - }, - { - "timestamp": 3975, - "events": [ - { - "type": "song", - "text": [ - "Basshunter", - "Boten Anna" - ] - } - ] - }, - { - "timestamp": 3988, - "events": [ - { - "type": "shot", - "text": [ - "Zuipen!", - "Nog 34 shotjes" - ], - "shotCount": 66 - } - ] - }, - { - "timestamp": 4029, - "events": [ - { - "type": "song", - "text": [ - "Lawineboys", - "Wat zullen we drinken" - ] - } - ] - }, - { - "timestamp": 4050, - "events": [ - { - "type": "shot", - "text": [ - "Dorst!", - "Nog 33 shotjes" - ], - "shotCount": 67 - } - ] - }, - { - "timestamp": 4081, - "events": [ - { - "type": "song", - "text": [ - "Lamme Frans", - "Wakker met een biertje!" - ] - } - ] - }, - { - "timestamp": 4113, - "events": [ - { - "type": "shot", - "text": [ - "Biertje in de hand...", - "Nog 32 shotjes" - ], - "shotCount": 68 - } - ] - }, - { - "timestamp": 4124, - "events": [ - { - "type": "song", - "text": [ - "Lawineboys feat. DJ Jerome", - "Seks met die kale" - ] - } - ] - }, - { - "timestamp": 4175, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 31 shotjes" - ], - "shotCount": 69 - } - ] - }, - { - "timestamp": 4177, - "events": [ - { - "type": "song", - "text": [ - "Zombie Nation", - "Kernkraft 400" - ] - } - ] - }, - { - "timestamp": 4214, - "events": [ - { - "type": "time", - "text": [ - "Nog 30 minuten!", - "Half uurtje nog maar" - ] - } - ] - }, - { - "timestamp": 4228, - "events": [ - { - "type": "shot", - "text": [ - "Pweeeep!", - "Nog 30 shotjes" - ], - "shotCount": 70 - } - ] - }, - { - "timestamp": 4230, - "events": [ - { - "type": "song", - "text": [ - "DJ Boozywoozy", - "Party Affair" - ] - } - ] - }, - { - "timestamp": 4280, - "events": [ - { - "type": "shot", - "text": [ - "Tik maar achterover!", - "Nog 29 shotjes" - ], - "shotCount": 71 - } - ] - }, - { - "timestamp": 4289, - "events": [ - { - "type": "song", - "text": [ - "2Unlimited", - "No Limit" - ] - } - ] - }, - { - "timestamp": 4341, - "events": [ - { - "type": "shot", - "text": [ - "Alcoholic party!", - "Nog 28 shotjes" - ], - "shotCount": 72 - } - ] - }, - { - "timestamp": 4343, - "events": [ - { - "type": "song", - "text": [ - "DJ Kicken vs. MC-Q", - "Ain't No Party" - ] - } - ] - }, - { - "timestamp": 4408, - "events": [ - { - "type": "shot", - "text": [ - "Toet!", - "Nog 27 shotjes" - ], - "shotCount": 73 - } - ] - }, - { - "timestamp": 4411, - "events": [ - { - "type": "song", - "text": [ - "Jan Wayne", - "Becuase the Night" - ] - } - ] - }, - { - "timestamp": 4455, - "events": [ - { - "type": "song", - "text": [ - "Cascada", - "Everytime We Touch" - ] - } - ] - }, - { - "timestamp": 4467, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 26 shotjes" - ], - "shotCount": 74 - } - ] - }, - { - "timestamp": 4510, - "events": [ - { - "type": "song", - "text": [ - "Gigi D'Agostino", - "L'amour toujours" - ] - } - ] - }, - { - "timestamp": 4521, - "events": [ - { - "type": "shot", - "text": [ - "Shotje 75!", - "Nog 25 shotjes" - ], - "shotCount": 75 - } - ] - }, - { - "timestamp": 4573, - "events": [ - { - "type": "song", - "text": [ - "Jason Paige", - "Gotta Catch 'M All" - ] - } - ] - }, - { - "timestamp": 4578, - "events": [ - { - "type": "shot", - "text": [ - "Trek een ad!", - "Nog 24 shotjes" - ], - "shotCount": 76 - } - ] - }, - { - "timestamp": 4636, - "events": [ - { - "type": "song", - "text": [ - "Scooter", - "How Much Is The Fish" - ] - } - ] - }, - { - "timestamp": 4645, - "events": [ - { - "type": "shot", - "text": [ - "Pweeeep!", - "Nog 23 shotjes" - ], - "shotCount": 77 - } - ] - }, - { - "timestamp": 4675, - "events": [ - { - "type": "song", - "text": [ - "Scooter", - "Weekend" - ] - } - ] - }, - { - "timestamp": 4701, - "events": [ - { - "type": "shot", - "text": [ - "scToeter!", - "Nog 22 shotjes" - ], - "shotCount": 78 - } - ] - }, - { - "timestamp": 4714, - "events": [ - { - "type": "song", - "text": [ - "Scooter", - "One (Always Hardcore)" - ] - } - ] - }, - { - "timestamp": 4764, - "events": [ - { - "type": "shot", - "text": [ - "En door!", - "Nog 21 shotjes" - ], - "shotCount": 79 - } - ] - }, - { - "timestamp": 4766, - "events": [ - { - "type": "song", - "text": [ - "Scooter", - "Maria (I Like It Loud)" - ] - } - ] - }, - { - "timestamp": 4815, - "events": [ - { - "type": "time", - "text": [ - "Nog 20 minuten!", - "Geef alles, behalve over" - ] - } - ] - }, - { - "timestamp": 4818, - "events": [ - { - "type": "song", - "text": [ - "Scooter", - "J'adore Hardcore" - ] - } - ] - }, - { - "timestamp": 4829, - "events": [ - { - "type": "shot", - "text": [ - "Al 80 in de mik!", - "Nog 20 shotjes" - ], - "shotCount": 80 - } - ] - }, - { - "timestamp": 4860, - "events": [ - { - "type": "song", - "text": [ - "Wildstylez feat. Niels Geusebroek", - "Year of Summer" - ] - } - ] - }, - { - "timestamp": 4888, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 19 shotjes" - ], - "shotCount": 81 - } - ] - }, - { - "timestamp": 4929, - "events": [ - { - "type": "song", - "text": [ - "Brennan Heart & Wildstylez", - "Lose My Mind" - ] - } - ] - }, - { - "timestamp": 4953, - "events": [ - { - "type": "shot", - "text": [ - "Bakken vouwen!", - "Nog 18 shotjes" - ], - "shotCount": 82 - } - ] - }, - { - "timestamp": 5004, - "events": [ - { - "type": "shot", - "text": [ - "Pweeeep!", - "Nog 17 shotjes" - ], - "shotCount": 83 - } - ] - }, - { - "timestamp": 5006, - "events": [ - { - "type": "song", - "text": [ - "Starkoo", - "Ik wil je" - ] - } - ] - }, - { - "timestamp": 5059, - "events": [ - { - "type": "song", - "text": [ - "Feestteam", - "Let It Be" - ] - } - ] - }, - { - "timestamp": 5071, - "events": [ - { - "type": "shot", - "text": [ - "Let it bier!", - "Nog 16 shotjes" - ], - "shotCount": 84 - } - ] - }, - { - "timestamp": 5125, - "events": [ - { - "type": "shot", - "text": [ - "Adje numero 85!", - "Nog 15 shotjes" - ], - "shotCount": 85 - } - ] - }, - { - "timestamp": 5179, - "events": [ - { - "type": "song", - "text": [ - "DJ Nikolai & DJ Mike van Dijk", - "Piano Man" - ] - } - ] - }, - { - "timestamp": 5188, - "events": [ - { - "type": "shot", - "text": [ - "Toet!", - "Nog 14 shotjes" - ], - "shotCount": 86 - } - ] - }, - { - "timestamp": 5190, - "events": [ - { - "type": "talk", - "text": [ - "Gewoon doorgaan!", - "Deze Piano Man telt niet" - ] - } - ] - }, - { - "timestamp": 5237, - "events": [ - { - "type": "song", - "text": [ - "Robbie Williams", - "Angels" - ] - } - ] - }, - { - "timestamp": 5243, - "events": [ - { - "type": "shot", - "text": [ - "Drinken!", - "Nog 13 shotjes" - ], - "shotCount": 87 - } - ] - }, - { - "timestamp": 5278, - "events": [ - { - "type": "song", - "text": [ - "Enrique Iglesias", - "Hero" - ] - } - ] - }, - { - "timestamp": 5308, - "events": [ - { - "type": "shot", - "text": [ - "I can't be your biero!", - "Nog 12 shotjes" - ], - "shotCount": 88 - } - ] - }, - { - "timestamp": 5331, - "events": [ - { - "type": "song", - "text": [ - "Whitney Houston", - "I Will Always Love You" - ] - } - ] - }, - { - "timestamp": 5374, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 11 shotjes" - ], - "shotCount": 89 - } - ] - }, - { - "timestamp": 5380, - "events": [ - { - "type": "song", - "text": [ - "Mariah Carey", - "All I Want For Christmas" - ] - } - ] - }, - { - "timestamp": 5431, - "events": [ - { - "type": "shot", - "text": [ - "90 in de keel, hierna niet veel!", - "Nog 10 shotjes" - ], - "shotCount": 90 - } - ] - }, - { - "timestamp": 5441, - "events": [ - { - "type": "time", - "text": [ - "Nog 10 minuten!", - "De laatste loodjes" - ] - } - ] - }, - { - "timestamp": 5444, - "events": [ - { - "type": "song", - "text": [ - "Kraantje Pappie", - "Feesttent (FeestDJRuud remix)" - ] - } - ] - }, - { - "timestamp": 5488, - "events": [ - { - "type": "shot", - "text": [ - "Zuip je uit de dubbele cijfers!", - "Nog 9 shotjes" - ], - "shotCount": 91 - } - ] - }, - { - "timestamp": 5490, - "events": [ - { - "type": "song", - "text": [ - "New Kids feat. DJ Paul Elstak", - "Turbo" - ] - } - ] - }, - { - "timestamp": 5556, - "events": [ - { - "type": "shot", - "text": [ - "Zuipen!", - "Nog 8 shotjes" - ], - "shotCount": 92 - } - ] - }, - { - "timestamp": 5558, - "events": [ - { - "type": "song", - "text": [ - "Lipstick", - "I'm a Raver" - ] - } - ] - }, - { - "timestamp": 5591, - "events": [ - { - "type": "song", - "text": [ - "Nakatomi", - "Children of the Night" - ] - } - ] - }, - { - "timestamp": 5612, - "events": [ - { - "type": "shot", - "text": [ - "Pweeeep!", - "Nog 7 shotjes" - ], - "shotCount": 93 - } - ] - }, - { - "timestamp": 5614, - "events": [ - { - "type": "song", - "text": [ - "Charly Lownoise & Mental Theo", - "Wonderful Days" - ] - } - ] - }, - { - "timestamp": 5659, - "events": [ - { - "type": "song", - "text": [ - "DJ Paul Elstak", - "Luv You More" - ] - } - ] - }, - { - "timestamp": 5667, - "events": [ - { - "type": "shot", - "text": [ - "Bijna daar!", - "Nog 6 shotjes" - ], - "shotCount": 94 - } - ] - }, - { - "timestamp": 5704, - "events": [ - { - "type": "song", - "text": [ - "DJ Paul Elstak", - "Rainbow In The Sky" - ] - } - ] - }, - { - "timestamp": 5716, - "events": [ - { - "type": "time", - "text": [ - "Nog 5 minuten!", - "Zet de shotjes maar klaar" - ] - } - ] - }, - { - "timestamp": 5731, - "events": [ - { - "type": "shot", - "text": [ - "Toeter!", - "Nog 5 shotjes" - ], - "shotCount": 95 - } - ] - }, - { - "timestamp": 5733, - "events": [ - { - "type": "song", - "text": [ - "Evil Activities", - "Nobody Said It Was Easy" - ] - } - ] - }, - { - "timestamp": 5783, - "events": [ - { - "type": "shot", - "text": [ - "Slok 96!", - "Nog 4 shotjes" - ], - "shotCount": 96 - } - ] - }, - { - "timestamp": 5827, - "events": [ - { - "type": "song", - "text": [ - "Melrose", - "O" - ] - } - ] - }, - { - "timestamp": 5846, - "events": [ - { - "type": "shot", - "text": [ - "Voor de 97e keer!", - "Nog 3 shotjes" - ], - "shotCount": 97 - } - ] - }, - { - "timestamp": 5855, - "events": [ - { - "type": "song", - "text": [ - "Backstreet Boys", - "I Want It That Way" - ] - } - ] - }, - { - "timestamp": 5902, - "events": [ - { - "type": "shot", - "text": [ - "Nummer 98!", - "Nog 2 shotjes" - ], - "shotCount": 98 - } - ] - }, - { - "timestamp": 5933, - "events": [ - { - "type": "song", - "text": [ - "R. Kelly", - "The World's Greatest" - ] - } - ] - }, - { - "timestamp": 5970, - "events": [ - { - "type": "shot", - "text": [ - "Nummer 99!", - "Nog 1 shotje" - ], - "shotCount": 99 - } - ] - }, - { - "timestamp": 6020, - "events": [ - { - "type": "shot", - "text": [ - "CENTURION!", - "Geen shots meer" - ], - "shotCount": 100 - } - ] - } -] diff --git a/backend/data/timelines.js b/backend/data/timelines.js new file mode 100644 index 0000000..801091b --- /dev/null +++ b/backend/data/timelines.js @@ -0,0 +1,2733 @@ +module.exports = { + 'timelines': [ + { + 'name': 'Centurion', + 'feed': [ + + { + "timestamp": 0, + "events": [ + { + "type": "talk", + "text": [ + "Zet je schrap!", + "We gaan zo beginnen" + ] + } + ] + }, + { + "timestamp": 42, + "events": [ + { + "type": "talk", + "text": [ + "Daar gaan we!", + "Dit was het startsein, je hoeft nog niet te drinken" + ] + }, + { + "type": "song", + "text": [ + "Nena", + "99 Luftballons" + ] + } + ] + }, + { + "timestamp": 108, + "events": [ + { + "type": "shot", + "text": [ + "De eerste!", + "Nog 99 shotjes" + ], + "shotCount": 1 + } + ] + }, + { + "timestamp": 148, + "events": [ + { + "type": "song", + "text": [ + "Hermes House Band", + "Country Roads" + ] + } + ] + }, + { + "timestamp": 167, + "events": [ + { + "type": "shot", + "text": [ + "Nummertje twee!", + "Nog 98 shotjes" + ], + "shotCount": 2 + } + ] + }, + { + "timestamp": 185, + "events": [ + { + "type": "song", + "text": [ + "Vinzzent", + "Dromendans" + ] + } + ] + }, + { + "timestamp": 223, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 97 shotjes" + ], + "shotCount": 3 + }, + { + "type": "song", + "text": [ + "Linda, Roos & Jessica", + "Ademnood" + ] + } + ] + }, + { + "timestamp": 283, + "events": [ + { + "type": "shot", + "text": [ + "Lustrum!", + "Nog 96 shotjes" + ], + "shotCount": 4 + }, + { + "type": "song", + "text": [ + "Peter de Koning", + "Het is altijd lente in de ogen van de tandarts-assistente" + ] + } + ] + }, + { + "timestamp": 340, + "events": [ + { + "type": "shot", + "text": [ + "Niet gooien!", + "Nog 95 shotjes" + ], + "shotCount": 5 + }, + { + "type": "song", + "text": [ + "Liquido", + "Narcotic" + ] + } + ] + }, + { + "timestamp": 412, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 94 shotjes" + ], + "shotCount": 6 + }, + { + "type": "song", + "text": [ + "Snoop Dogg feat. Pharrell", + "Drop It Like It's Hot" + ] + } + ] + }, + { + "timestamp": 449, + "events": [ + { + "type": "song", + "text": [ + "M.O.P.", + "Ante Up" + ] + } + ] + }, + { + "timestamp": 459, + "events": [ + { + "type": "shot", + "text": [ + "Pweeeep!", + "Nog 93 shotjes" + ], + "shotCount": 7 + } + ] + }, + { + "timestamp": 514, + "events": [ + { + "type": "shot", + "text": [ + "Trek een ad!", + "Nog 92 shotjes" + ], + "shotCount": 8 + }, + { + "type": "song", + "text": [ + "Los Del Rio", + "Macarena" + ] + } + ] + }, + { + "timestamp": 560, + "events": [ + { + "type": "song", + "text": [ + "Spice Girls", + "Wannabe" + ] + } + ] + }, + { + "timestamp": 574, + "events": [ + { + "type": "shot", + "text": [ + "We zijn er nog lang niet!", + "Nog 91 shotjes" + ], + "shotCount": 9 + } + ] + }, + { + "timestamp": 617, + "events": [ + { + "type": "song", + "text": [ + "Major Lazer feat. Busy Signal, The Flexican & FS Green", + "Watch Out For This (Bumaye)" + ] + } + ] + }, + { + "timestamp": 635, + "events": [ + { + "type": "shot", + "text": [ + "Nummer tien!", + "Nog 90 shotjes" + ], + "shotCount": 10 + } + ] + }, + { + "timestamp": 647, + "events": [ + { + "type": "time", + "text": [ + "Nog 90 minuten!", + "Geef alles, behalve op" + ] + } + ] + }, + { + "timestamp": 684, + "events": [ + { + "type": "song", + "text": [ + "Kabouter Plop", + "Kabouterdans" + ] + } + ] + }, + { + "timestamp": 699, + "events": [ + { + "type": "shot", + "text": [ + "Met vriendelijke toet!", + "Nog 89 shotjes" + ], + "shotCount": 11 + } + ] + }, + { + "timestamp": 725, + "events": [ + { + "type": "song", + "text": [ + "K3", + "Alle kleuren" + ] + } + ] + }, + { + "timestamp": 756, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 88 shotjes" + ], + "shotCount": 12 + } + ] + }, + { + "timestamp": 757, + "events": [ + { + "type": "song", + "text": [ + "Kinderen voor Kinderen", + "Tietenlied" + ] + } + ] + }, + { + "timestamp": 812, + "events": [ + { + "type": "shot", + "text": [ + "Ongeluksshotje 13!", + "Nog 87 shotjes" + ], + "shotCount": 13 + } + ] + }, + { + "timestamp": 814, + "events": [ + { + "type": "song", + "text": [ + "Guus Meeuwis", + "Het dondert en het bliksemt" + ] + } + ] + }, + { + "timestamp": 820, + "events": [ + { + "type": "talk", + "text": [ + "Carnaval is prachtig!", + "Leve de vervoerie" + ] + } + ] + }, + { + "timestamp": 874, + "events": [ + { + "type": "shot", + "text": [ + "Pweeeep!", + "Nog 86 shotjes" + ], + "shotCount": 14 + } + ] + }, + { + "timestamp": 876, + "events": [ + { + "type": "song", + "text": [ + "Harry Vermeegen", + "1-2-3-4 Dennis bier" + ] + } + ] + }, + { + "timestamp": 906, + "events": [ + { + "type": "song", + "text": [ + "Puhdys", + "Hey, wir woll’n die Eisbär'n sehn!" + ] + } + ] + }, + { + "timestamp": 935, + "events": [ + { + "type": "shot", + "text": [ + "Fünfzehn!", + "Nog 85 shotjes" + ], + "shotCount": 15 + } + ] + }, + { + "timestamp": 966, + "events": [ + { + "type": "song", + "text": [ + "DJ Ötzi", + "Burger Dance" + ] + } + ] + }, + { + "timestamp": 995, + "events": [ + { + "type": "shot", + "text": [ + "Toet!", + "Nog 84 shotjes" + ], + "shotCount": 16 + } + ] + }, + { + "timestamp": 996, + "events": [ + { + "type": "song", + "text": [ + "Mickie Krause", + "Hütte auf der Alm" + ] + } + ] + }, + { + "timestamp": 1030, + "events": [ + { + "type": "song", + "text": [ + "Ali B & Yes-R & The Partysquad", + "Rampeneren" + ] + } + ] + }, + { + "timestamp": 1046, + "events": [ + { + "type": "shot", + "text": [ + "Zuipen!", + "Nog 83 shotjes" + ], + "shotCount": 17 + } + ] + }, + { + "timestamp": 1107, + "events": [ + { + "type": "shot", + "text": [ + "Met dank aan bestuur 19; super 'vo", + "Nog 82 shotjes" + ], + "shotCount": 18 + }, + { + "type": "song", + "text": [ + "Martin Solveig", + "Intoxicated" + ] + } + ] + }, + { + "timestamp": 1137, + "events": [ + { + "type": "song", + "text": [ + "Nicki Minaj", + "Starships" + ] + } + ] + }, + { + "timestamp": 1173, + "events": [ + { + "type": "shot", + "text": [ + "Laatste shotje als tiener!", + "Nog 81 shotjes" + ], + "shotCount": 19 + } + ] + }, + { + "timestamp": 1222, + "events": [ + { + "type": "song", + "text": [ + "2Unlimited", + "Get Ready For This" + ] + } + ] + }, + { + "timestamp": 1233, + "events": [ + { + "type": "time", + "text": [ + "Nog 80 minuten!", + "Al 19 shotjes achter de rug" + ] + } + ] + }, + { + "timestamp": 1235, + "events": [ + { + "type": "shot", + "text": [ + "Adje!", + "Nog 80 shotjes" + ], + "shotCount": 20 + } + ] + }, + { + "timestamp": 1275, + "events": [ + { + "type": "song", + "text": [ + "The Village People", + "YMCA" + ] + } + ] + }, + { + "timestamp": 1288, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 79 shotjes" + ], + "shotCount": 21 + } + ] + }, + { + "timestamp": 1348, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 78 shotjes" + ], + "shotCount": 22 + } + ] + }, + { + "timestamp": 1350, + "events": [ + { + "type": "song", + "text": [ + "Carly Rae Jepsen ft Owl City", + "It's Always A Good Time" + ] + } + ] + }, + { + "timestamp": 1395, + "events": [ + { + "type": "song", + "text": [ + "Avicii", + "Levels" + ] + } + ] + }, + { + "timestamp": 1411, + "events": [ + { + "type": "shot", + "text": [ + "Claxon!", + "Nog 77 shotjes" + ], + "shotCount": 23 + } + ] + }, + { + "timestamp": 1456, + "events": [ + { + "type": "song", + "text": [ + "Flo-Rida feat. T-Pain", + "Low" + ] + } + ] + }, + { + "timestamp": 1471, + "events": [ + { + "type": "shot", + "text": [ + "En nu even op standje maximaal!", + "Nog 76 shotjes" + ], + "shotCount": 24 + } + ] + }, + { + "timestamp": 1486, + "events": [ + { + "type": "song", + "text": [ + "Taio Cruz", + "Hangover" + ] + } + ] + }, + { + "timestamp": 1522, + "events": [ + { + "type": "talk", + "text": [ + "Dit is nog het rustige stukje!", + "Zet hem maar op de bonk-bonk" + ] + } + ] + }, + { + "timestamp": 1530, + "events": [ + { + "type": "shot", + "text": [ + "Halve Abraham!", + "Nog 75 shotjes" + ], + "shotCount": 25 + } + ] + }, + { + "timestamp": 1545, + "events": [ + { + "type": "song", + "text": [ + "LMFAO", + "Party Rock Anthem" + ] + } + ] + }, + { + "timestamp": 1594, + "events": [ + { + "type": "shot", + "text": [ + "Hoch die Hände!", + "Nog 74 shotjes" + ], + "shotCount": 26 + }, + { + "type": "song", + "text": [ + "Hans Entertainment vs. Finger & Kadel", + "Hoch die Hände" + ] + } + ] + }, + { + "timestamp": 1623, + "events": [ + { + "type": "song", + "text": [ + "Galantis", + "No Money" + ] + } + ] + }, + { + "timestamp": 1653, + "events": [ + { + "type": "shot", + "text": [ + "Voel je 'm al?", + "Nog 73 shotjes" + ], + "shotCount": 27 + } + ] + }, + { + "timestamp": 1683, + "events": [ + { + "type": "song", + "text": [ + "Kid Cudi", + "Pursuit of Happiness (Steve Aoki remix)" + ] + } + ] + }, + { + "timestamp": 1712, + "events": [ + { + "type": "shot", + "text": [ + "Project X!", + "Nog 72 shotjes" + ], + "shotCount": 28 + } + ] + }, + { + "timestamp": 1741, + "events": [ + { + "type": "song", + "text": [ + "Yeah Yeah Yeahs", + "Heads Will Roll (A-Trak remix)" + ] + } + ] + }, + { + "timestamp": 1769, + "events": [ + { + "type": "shot", + "text": [ + "Pweeeep!", + "Nog 71 shotjes" + ], + "shotCount": 29 + } + ] + }, + { + "timestamp": 1814, + "events": [ + { + "type": "song", + "text": [ + "Michael Calfan", + "Resurrection" + ] + } + ] + }, + { + "timestamp": 1825, + "events": [ + { + "type": "time", + "text": [ + "Nog 70 minuten!", + "Half uurtje zit erop" + ] + } + ] + }, + { + "timestamp": 1829, + "events": [ + { + "type": "shot", + "text": [ + "Toet!", + "Nog 70 shotjes" + ], + "shotCount": 30 + } + ] + }, + { + "timestamp": 1858, + "events": [ + { + "type": "song", + "text": [ + "Basto!", + "Again and Again" + ] + } + ] + }, + { + "timestamp": 1887, + "events": [ + { + "type": "shot", + "text": [ + "Over de dertig!", + "Nog 69 (hehe) shotjes" + ], + "shotCount": 31 + } + ] + }, + { + "timestamp": 1916, + "events": [ + { + "type": "song", + "text": [ + "David Guetaa feat. Sia", + "Titanium" + ] + } + ] + }, + { + "timestamp": 1945, + "events": [ + { + "type": "shot", + "text": [ + "Trek een ad!", + "Nog 68 shotjes" + ], + "shotCount": 32 + } + ] + }, + { + "timestamp": 1959, + "events": [ + { + "type": "song", + "text": [ + "Gala", + "Freed From Desire" + ] + } + ] + }, + { + "timestamp": 2004, + "events": [ + { + "type": "shot", + "text": [ + "Nummertje 33!", + "Nog 67 shotjes!" + ], + "shotCount": 33 + } + ] + }, + { + "timestamp": 2034, + "events": [ + { + "type": "song", + "text": [ + "Wolter Kroes", + "Viva Hollandia" + ] + } + ] + }, + { + "timestamp": 2064, + "events": [ + { + "type": "shot", + "text": [ + "Voor het vaderland!", + "Nog 66 shotjes" + ], + "shotCount": 34 + } + ] + }, + { + "timestamp": 2125, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 65 shotjes" + ], + "shotCount": 35 + } + ] + }, + { + "timestamp": 2128, + "events": [ + { + "type": "song", + "text": [ + "Westlife", + "Uptown Girl" + ] + } + ] + }, + { + "timestamp": 2179, + "events": [ + { + "type": "song", + "text": [ + "Aqua", + "Barbie Girl" + ] + } + ] + }, + { + "timestamp": 2194, + "events": [ + { + "type": "shot", + "text": [ + "Pweeeep!", + "Nog 64 shotjes" + ], + "shotCount": 36 + } + ] + }, + { + "timestamp": 2225, + "events": [ + { + "type": "song", + "text": [ + "Guillerma & Tropical Danny", + "Toppertje" + ] + } + ] + }, + { + "timestamp": 2245, + "events": [ + { + "type": "shot", + "text": [ + "In dat keelgaatje!", + "Nog 63 shotjes" + ], + "shotCount": 37 + } + ] + }, + { + "timestamp": 2305, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 62 shotjes" + ], + "shotCount": 38 + }, + { + "type": "song", + "text": [ + "The Bloody Beetroots feat. Steve Aoki", + "Warp 1.9" + ] + } + ] + }, + { + "timestamp": 2374, + "events": [ + { + "type": "shot", + "text": [ + "Toet!", + "Nog 61 shotjes" + ], + "shotCount": 39 + }, + { + "type": "song", + "text": [ + "David Guetta & Showtek feat. Vassy", + "Bad" + ] + } + ] + }, + { + "timestamp": 2431, + "events": [ + { + "type": "shot", + "text": [ + "40 alweer!", + "Nog 60 shotjes" + ], + "shotCount": 40 + }, + { + "type": "song", + "text": [ + "Showtek & Justin Prime", + "Cannonball" + ] + } + ] + }, + { + "timestamp": 2444, + "events": [ + { + "type": "time", + "text": [ + "Nog 60 minuten!", + "Een klein uurtje" + ] + } + ] + }, + { + "timestamp": 2460, + "events": [ + { + "type": "song", + "text": [ + "Die Atzen", + "Disco Pogo" + ] + } + ] + }, + { + "timestamp": 2489, + "events": [ + { + "type": "shot", + "text": [ + "Zuipen!", + "Nog 59 shotjes" + ], + "shotCount": 41 + } + ] + }, + { + "timestamp": 2534, + "events": [ + { + "type": "song", + "text": [ + "Lorenz Büffel", + "Johnny Däpp" + ] + } + ] + }, + { + "timestamp": 2555, + "events": [ + { + "type": "shot", + "text": [ + "Dab dat glas naar je mond!", + "Nog 58 shotjes" + ], + "shotCount": 42 + } + ] + }, + { + "timestamp": 2587, + "events": [ + { + "type": "song", + "text": [ + "Zware Jongens", + "Jodeljump" + ] + } + ] + }, + { + "timestamp": 2606, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 57 shotjes" + ], + "shotCount": 43 + } + ] + }, + { + "timestamp": 2635, + "events": [ + { + "type": "song", + "text": [ + "Parla & Pardoux", + "Liberté" + ] + } + ] + }, + { + "timestamp": 2664, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 56 shotjes" + ], + "shotCount": 44 + } + ] + }, + { + "timestamp": 2695, + "events": [ + { + "type": "song", + "text": [ + "Markus Becker", + "Das rote Pferd" + ] + } + ] + }, + { + "timestamp": 2729, + "events": [ + { + "type": "shot", + "text": [ + "Pweeeep!", + "Nog 55 shotjes" + ], + "shotCount": 45 + } + ] + }, + { + "timestamp": 2743, + "events": [ + { + "type": "song", + "text": [ + "Olaf Henning", + "Cowboy und Indianer" + ] + } + ] + }, + { + "timestamp": 2784, + "events": [ + { + "type": "shot", + "text": [ + "Adje!", + "Nog 54 shotjes" + ], + "shotCount": 46 + } + ] + }, + { + "timestamp": 2785, + "events": [ + { + "type": "song", + "text": [ + "Ch!pz", + "Cowboy" + ] + } + ] + }, + { + "timestamp": 2824, + "events": [ + { + "type": "song", + "text": [ + "Toy-Box", + "Tarzan & Jane" + ] + } + ] + }, + { + "timestamp": 2850, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 53 shotjes" + ], + "shotCount": 47 + } + ] + }, + { + "timestamp": 2879, + "events": [ + { + "type": "song", + "text": [ + "Toy-Box", + "Sailor Song" + ] + } + ] + }, + { + "timestamp": 2919, + "events": [ + { + "type": "shot", + "text": [ + "Bijna op de helft!", + "Nog 52 shotjes" + ], + "shotCount": 48 + } + ] + }, + { + "timestamp": 2921, + "events": [ + { + "type": "song", + "text": [ + "Vengaboys", + "Boom, Boom, Boom, Boom!!" + ] + } + ] + }, + { + "timestamp": 2975, + "events": [ + { + "type": "shot", + "text": [ + "Bam!", + "Nog 51 shotjes" + ], + "shotCount": 49 + } + ] + }, + { + "timestamp": 2998, + "events": [ + { + "type": "song", + "text": [ + "Vengaboys", + "To Brazil!" + ] + } + ] + }, + { + "timestamp": 3024, + "events": [ + { + "type": "time", + "text": [ + "Nog 50 minuten!", + "We zijn op de helft!" + ] + } + ] + }, + { + "timestamp": 3039, + "events": [ + { + "type": "shot", + "text": [ + "Abraham!", + "Nog 50 shotjes" + ], + "shotCount": 50 + } + ] + }, + { + "timestamp": 3070, + "events": [ + { + "type": "song", + "text": [ + "Snollebollekes", + "Bam bam (bam)" + ] + } + ] + }, + { + "timestamp": 3104, + "events": [ + { + "type": "shot", + "text": [ + "Tweede helft!", + "Nog 49 shotjes" + ], + "shotCount": 51 + } + ] + }, + { + "timestamp": 3120, + "events": [ + { + "type": "song", + "text": [ + "Def Rhymz", + "Schudden" + ] + } + ] + }, + { + "timestamp": 3160, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 48 shotjes" + ], + "shotCount": 52 + } + ] + }, + { + "timestamp": 3190, + "events": [ + { + "type": "song", + "text": [ + "Cooldown Café", + "Hey baby" + ] + } + ] + }, + { + "timestamp": 3215, + "events": [ + { + "type": "shot", + "text": [ + "Pweeeep!", + "Nog 47 shotjes" + ], + "shotCount": 53 + } + ] + }, + { + "timestamp": 3232, + "events": [ + { + "type": "song", + "text": [ + "Gebroeders Ko", + "Schatje, mag ik je foto" + ] + } + ] + }, + { + "timestamp": 3279, + "events": [ + { + "type": "shot", + "text": [ + "Zuipen!", + "Nog 46 shotjes" + ], + "shotCount": 54 + }, + { + "type": "song", + "text": [ + "Guus Meeuwis", + "Het is een nacht" + ] + } + ] + }, + { + "timestamp": 3341, + "events": [ + { + "type": "shot", + "text": [ + "Adje!", + "Nog 45 shotjes" + ], + "shotCount": 55 + } + ] + }, + { + "timestamp": 3356, + "events": [ + { + "type": "song", + "text": [ + "Tom Waes", + "Dos cervezas" + ] + } + ] + }, + { + "timestamp": 3398, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 44 shotjes" + ], + "shotCount": 56 + } + ] + }, + { + "timestamp": 3412, + "events": [ + { + "type": "song", + "text": [ + "Peter Wackel", + "Vollgas" + ] + } + ] + }, + { + "timestamp": 3439, + "events": [ + { + "type": "song", + "text": [ + "Peter Wackel", + "Scheiß drauf!" + ] + } + ] + }, + { + "timestamp": 3465, + "events": [ + { + "type": "shot", + "text": [ + "Hard gaan!", + "Nog 43 shotjes" + ], + "shotCount": 57 + } + ] + }, + { + "timestamp": 3467, + "events": [ + { + "type": "song", + "text": [ + "Ikke Hüftgold", + "Dicke titten, kartoffelsalat" + ] + } + ] + }, + { + "timestamp": 3520, + "events": [ + { + "type": "shot", + "text": [ + "Hap, slok, weg!", + "Nog 42 shotjes" + ], + "shotCount": 58 + } + ] + }, + { + "timestamp": 3521, + "events": [ + { + "type": "song", + "text": [ + "Tim Toupet", + "Fliegerlied (So ein schöner Tag)" + ] + } + ] + }, + { + "timestamp": 3564, + "events": [ + { + "type": "song", + "text": [ + "Cooldown Café", + "Met z'n allen" + ] + } + ] + }, + { + "timestamp": 3577, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 41 shotjes" + ], + "shotCount": 59 + } + ] + }, + { + "timestamp": 3636, + "events": [ + { + "type": "time", + "text": [ + "Nog 40 minuten!", + "Uurtje achter de rug" + ] + } + ] + }, + { + "timestamp": 3643, + "events": [ + { + "type": "shot", + "text": [ + "Glas 60!", + "Nog 40 shotjes" + ], + "shotCount": 60 + } + ] + }, + { + "timestamp": 3659, + "events": [ + { + "type": "song", + "text": [ + "The Partysquad feat. Jayh, Sjaak & Reverse", + "Helemaal naar de klote" + ] + } + ] + }, + { + "timestamp": 3687, + "events": [ + { + "type": "song", + "text": [ + "K-Liber", + "Viben" + ] + } + ] + }, + { + "timestamp": 3700, + "events": [ + { + "type": "shot", + "text": [ + "Adje!", + "Nog 39 shotjes" + ], + "shotCount": 61 + } + ] + }, + { + "timestamp": 3753, + "events": [ + { + "type": "shot", + "text": [ + "Pweeeep!", + "Nog 38 shotjes" + ], + "shotCount": 62 + } + ] + }, + { + "timestamp": 3755, + "events": [ + { + "type": "song", + "text": [ + "FeestDJRuud & Dirtcaps feat. Sjaak & Kraantje Pappie", + "Weekend" + ] + } + ] + }, + { + "timestamp": 3808, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 37 shotjes" + ], + "shotCount": 63 + }, + { + "type": "song", + "text": [ + "Lawineboys", + "Joost" + ] + } + ] + }, + { + "timestamp": 3860, + "events": [ + { + "type": "song", + "text": [ + "Gebroeders Ko", + "Ik heb een toeter op mijn waterscooter" + ] + } + ] + }, + { + "timestamp": 3874, + "events": [ + { + "type": "shot", + "text": [ + "Toe-toe-toeter!", + "Nog 36 shotjes" + ], + "shotCount": 64 + } + ] + }, + { + "timestamp": 3904, + "events": [ + { + "type": "song", + "text": [ + "Gebroeders Ko", + "Tringeling" + ] + } + ] + }, + { + "timestamp": 3931, + "events": [ + { + "type": "shot", + "text": [ + "Tringeling!", + "Nog 35 shotjes" + ], + "shotCount": 65 + } + ] + }, + { + "timestamp": 3975, + "events": [ + { + "type": "song", + "text": [ + "Basshunter", + "Boten Anna" + ] + } + ] + }, + { + "timestamp": 3988, + "events": [ + { + "type": "shot", + "text": [ + "Zuipen!", + "Nog 34 shotjes" + ], + "shotCount": 66 + } + ] + }, + { + "timestamp": 4029, + "events": [ + { + "type": "song", + "text": [ + "Lawineboys", + "Wat zullen we drinken" + ] + } + ] + }, + { + "timestamp": 4050, + "events": [ + { + "type": "shot", + "text": [ + "Dorst!", + "Nog 33 shotjes" + ], + "shotCount": 67 + } + ] + }, + { + "timestamp": 4081, + "events": [ + { + "type": "song", + "text": [ + "Lamme Frans", + "Wakker met een biertje!" + ] + } + ] + }, + { + "timestamp": 4113, + "events": [ + { + "type": "shot", + "text": [ + "Biertje in de hand...", + "Nog 32 shotjes" + ], + "shotCount": 68 + } + ] + }, + { + "timestamp": 4124, + "events": [ + { + "type": "song", + "text": [ + "Lawineboys feat. DJ Jerome", + "Seks met die kale" + ] + } + ] + }, + { + "timestamp": 4175, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 31 shotjes" + ], + "shotCount": 69 + } + ] + }, + { + "timestamp": 4177, + "events": [ + { + "type": "song", + "text": [ + "Zombie Nation", + "Kernkraft 400" + ] + } + ] + }, + { + "timestamp": 4214, + "events": [ + { + "type": "time", + "text": [ + "Nog 30 minuten!", + "Half uurtje nog maar" + ] + } + ] + }, + { + "timestamp": 4228, + "events": [ + { + "type": "shot", + "text": [ + "Pweeeep!", + "Nog 30 shotjes" + ], + "shotCount": 70 + } + ] + }, + { + "timestamp": 4230, + "events": [ + { + "type": "song", + "text": [ + "DJ Boozywoozy", + "Party Affair" + ] + } + ] + }, + { + "timestamp": 4280, + "events": [ + { + "type": "shot", + "text": [ + "Tik maar achterover!", + "Nog 29 shotjes" + ], + "shotCount": 71 + } + ] + }, + { + "timestamp": 4289, + "events": [ + { + "type": "song", + "text": [ + "2Unlimited", + "No Limit" + ] + } + ] + }, + { + "timestamp": 4341, + "events": [ + { + "type": "shot", + "text": [ + "Alcoholic party!", + "Nog 28 shotjes" + ], + "shotCount": 72 + } + ] + }, + { + "timestamp": 4343, + "events": [ + { + "type": "song", + "text": [ + "DJ Kicken vs. MC-Q", + "Ain't No Party" + ] + } + ] + }, + { + "timestamp": 4408, + "events": [ + { + "type": "shot", + "text": [ + "Toet!", + "Nog 27 shotjes" + ], + "shotCount": 73 + } + ] + }, + { + "timestamp": 4411, + "events": [ + { + "type": "song", + "text": [ + "Jan Wayne", + "Becuase the Night" + ] + } + ] + }, + { + "timestamp": 4455, + "events": [ + { + "type": "song", + "text": [ + "Cascada", + "Everytime We Touch" + ] + } + ] + }, + { + "timestamp": 4467, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 26 shotjes" + ], + "shotCount": 74 + } + ] + }, + { + "timestamp": 4510, + "events": [ + { + "type": "song", + "text": [ + "Gigi D'Agostino", + "L'amour toujours" + ] + } + ] + }, + { + "timestamp": 4521, + "events": [ + { + "type": "shot", + "text": [ + "Shotje 75!", + "Nog 25 shotjes" + ], + "shotCount": 75 + } + ] + }, + { + "timestamp": 4573, + "events": [ + { + "type": "song", + "text": [ + "Jason Paige", + "Gotta Catch 'M All" + ] + } + ] + }, + { + "timestamp": 4578, + "events": [ + { + "type": "shot", + "text": [ + "Trek een ad!", + "Nog 24 shotjes" + ], + "shotCount": 76 + } + ] + }, + { + "timestamp": 4636, + "events": [ + { + "type": "song", + "text": [ + "Scooter", + "How Much Is The Fish" + ] + } + ] + }, + { + "timestamp": 4645, + "events": [ + { + "type": "shot", + "text": [ + "Pweeeep!", + "Nog 23 shotjes" + ], + "shotCount": 77 + } + ] + }, + { + "timestamp": 4675, + "events": [ + { + "type": "song", + "text": [ + "Scooter", + "Weekend" + ] + } + ] + }, + { + "timestamp": 4701, + "events": [ + { + "type": "shot", + "text": [ + "scToeter!", + "Nog 22 shotjes" + ], + "shotCount": 78 + } + ] + }, + { + "timestamp": 4714, + "events": [ + { + "type": "song", + "text": [ + "Scooter", + "One (Always Hardcore)" + ] + } + ] + }, + { + "timestamp": 4764, + "events": [ + { + "type": "shot", + "text": [ + "En door!", + "Nog 21 shotjes" + ], + "shotCount": 79 + } + ] + }, + { + "timestamp": 4766, + "events": [ + { + "type": "song", + "text": [ + "Scooter", + "Maria (I Like It Loud)" + ] + } + ] + }, + { + "timestamp": 4815, + "events": [ + { + "type": "time", + "text": [ + "Nog 20 minuten!", + "Geef alles, behalve over" + ] + } + ] + }, + { + "timestamp": 4818, + "events": [ + { + "type": "song", + "text": [ + "Scooter", + "J'adore Hardcore" + ] + } + ] + }, + { + "timestamp": 4829, + "events": [ + { + "type": "shot", + "text": [ + "Al 80 in de mik!", + "Nog 20 shotjes" + ], + "shotCount": 80 + } + ] + }, + { + "timestamp": 4860, + "events": [ + { + "type": "song", + "text": [ + "Wildstylez feat. Niels Geusebroek", + "Year of Summer" + ] + } + ] + }, + { + "timestamp": 4888, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 19 shotjes" + ], + "shotCount": 81 + } + ] + }, + { + "timestamp": 4929, + "events": [ + { + "type": "song", + "text": [ + "Brennan Heart & Wildstylez", + "Lose My Mind" + ] + } + ] + }, + { + "timestamp": 4953, + "events": [ + { + "type": "shot", + "text": [ + "Bakken vouwen!", + "Nog 18 shotjes" + ], + "shotCount": 82 + } + ] + }, + { + "timestamp": 5004, + "events": [ + { + "type": "shot", + "text": [ + "Pweeeep!", + "Nog 17 shotjes" + ], + "shotCount": 83 + } + ] + }, + { + "timestamp": 5006, + "events": [ + { + "type": "song", + "text": [ + "Starkoo", + "Ik wil je" + ] + } + ] + }, + { + "timestamp": 5059, + "events": [ + { + "type": "song", + "text": [ + "Feestteam", + "Let It Be" + ] + } + ] + }, + { + "timestamp": 5071, + "events": [ + { + "type": "shot", + "text": [ + "Let it bier!", + "Nog 16 shotjes" + ], + "shotCount": 84 + } + ] + }, + { + "timestamp": 5125, + "events": [ + { + "type": "shot", + "text": [ + "Adje numero 85!", + "Nog 15 shotjes" + ], + "shotCount": 85 + } + ] + }, + { + "timestamp": 5179, + "events": [ + { + "type": "song", + "text": [ + "DJ Nikolai & DJ Mike van Dijk", + "Piano Man" + ] + } + ] + }, + { + "timestamp": 5188, + "events": [ + { + "type": "shot", + "text": [ + "Toet!", + "Nog 14 shotjes" + ], + "shotCount": 86 + } + ] + }, + { + "timestamp": 5190, + "events": [ + { + "type": "talk", + "text": [ + "Gewoon doorgaan!", + "Deze Piano Man telt niet" + ] + } + ] + }, + { + "timestamp": 5237, + "events": [ + { + "type": "song", + "text": [ + "Robbie Williams", + "Angels" + ] + } + ] + }, + { + "timestamp": 5243, + "events": [ + { + "type": "shot", + "text": [ + "Drinken!", + "Nog 13 shotjes" + ], + "shotCount": 87 + } + ] + }, + { + "timestamp": 5278, + "events": [ + { + "type": "song", + "text": [ + "Enrique Iglesias", + "Hero" + ] + } + ] + }, + { + "timestamp": 5308, + "events": [ + { + "type": "shot", + "text": [ + "I can't be your biero!", + "Nog 12 shotjes" + ], + "shotCount": 88 + } + ] + }, + { + "timestamp": 5331, + "events": [ + { + "type": "song", + "text": [ + "Whitney Houston", + "I Will Always Love You" + ] + } + ] + }, + { + "timestamp": 5374, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 11 shotjes" + ], + "shotCount": 89 + } + ] + }, + { + "timestamp": 5380, + "events": [ + { + "type": "song", + "text": [ + "Mariah Carey", + "All I Want For Christmas" + ] + } + ] + }, + { + "timestamp": 5431, + "events": [ + { + "type": "shot", + "text": [ + "90 in de keel, hierna niet veel!", + "Nog 10 shotjes" + ], + "shotCount": 90 + } + ] + }, + { + "timestamp": 5441, + "events": [ + { + "type": "time", + "text": [ + "Nog 10 minuten!", + "De laatste loodjes" + ] + } + ] + }, + { + "timestamp": 5444, + "events": [ + { + "type": "song", + "text": [ + "Kraantje Pappie", + "Feesttent (FeestDJRuud remix)" + ] + } + ] + }, + { + "timestamp": 5488, + "events": [ + { + "type": "shot", + "text": [ + "Zuip je uit de dubbele cijfers!", + "Nog 9 shotjes" + ], + "shotCount": 91 + } + ] + }, + { + "timestamp": 5490, + "events": [ + { + "type": "song", + "text": [ + "New Kids feat. DJ Paul Elstak", + "Turbo" + ] + } + ] + }, + { + "timestamp": 5556, + "events": [ + { + "type": "shot", + "text": [ + "Zuipen!", + "Nog 8 shotjes" + ], + "shotCount": 92 + } + ] + }, + { + "timestamp": 5558, + "events": [ + { + "type": "song", + "text": [ + "Lipstick", + "I'm a Raver" + ] + } + ] + }, + { + "timestamp": 5591, + "events": [ + { + "type": "song", + "text": [ + "Nakatomi", + "Children of the Night" + ] + } + ] + }, + { + "timestamp": 5612, + "events": [ + { + "type": "shot", + "text": [ + "Pweeeep!", + "Nog 7 shotjes" + ], + "shotCount": 93 + } + ] + }, + { + "timestamp": 5614, + "events": [ + { + "type": "song", + "text": [ + "Charly Lownoise & Mental Theo", + "Wonderful Days" + ] + } + ] + }, + { + "timestamp": 5659, + "events": [ + { + "type": "song", + "text": [ + "DJ Paul Elstak", + "Luv You More" + ] + } + ] + }, + { + "timestamp": 5667, + "events": [ + { + "type": "shot", + "text": [ + "Bijna daar!", + "Nog 6 shotjes" + ], + "shotCount": 94 + } + ] + }, + { + "timestamp": 5704, + "events": [ + { + "type": "song", + "text": [ + "DJ Paul Elstak", + "Rainbow In The Sky" + ] + } + ] + }, + { + "timestamp": 5716, + "events": [ + { + "type": "time", + "text": [ + "Nog 5 minuten!", + "Zet de shotjes maar klaar" + ] + } + ] + }, + { + "timestamp": 5731, + "events": [ + { + "type": "shot", + "text": [ + "Toeter!", + "Nog 5 shotjes" + ], + "shotCount": 95 + } + ] + }, + { + "timestamp": 5733, + "events": [ + { + "type": "song", + "text": [ + "Evil Activities", + "Nobody Said It Was Easy" + ] + } + ] + }, + { + "timestamp": 5783, + "events": [ + { + "type": "shot", + "text": [ + "Slok 96!", + "Nog 4 shotjes" + ], + "shotCount": 96 + } + ] + }, + { + "timestamp": 5827, + "events": [ + { + "type": "song", + "text": [ + "Melrose", + "O" + ] + } + ] + }, + { + "timestamp": 5846, + "events": [ + { + "type": "shot", + "text": [ + "Voor de 97e keer!", + "Nog 3 shotjes" + ], + "shotCount": 97 + } + ] + }, + { + "timestamp": 5855, + "events": [ + { + "type": "song", + "text": [ + "Backstreet Boys", + "I Want It That Way" + ] + } + ] + }, + { + "timestamp": 5902, + "events": [ + { + "type": "shot", + "text": [ + "Nummer 98!", + "Nog 2 shotjes" + ], + "shotCount": 98 + } + ] + }, + { + "timestamp": 5933, + "events": [ + { + "type": "song", + "text": [ + "R. Kelly", + "The World's Greatest" + ] + } + ] + }, + { + "timestamp": 5970, + "events": [ + { + "type": "shot", + "text": [ + "Nummer 99!", + "Nog 1 shotje" + ], + "shotCount": 99 + } + ] + }, + { + "timestamp": 6020, + "events": [ + { + "type": "shot", + "text": [ + "CENTURION!", + "Geen shots meer" + ], + "shotCount": 100 + } + ] + } + ] + } + ] +} diff --git a/backend/package-lock.json b/backend/package-lock.json index b21d805..da37201 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -4,12 +4,81 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", + "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.6.tgz", + "integrity": "sha512-n/mr9tZI83kd4azlPG5y997C/M4DNABK9yErhFM6hKdym4kkmd9j0vtsJyjFIwfRBxtrxZtAfGZCNRIBMFLK5w==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.4.tgz", + "integrity": "sha512-dPs6CaRWxsfHbYDVU51VjEJaUJEcli4UI0fFMT4oWmgCvHj+j7oIxz5MLHVL0Rv++N004c21ylJNdWQvPkkb5w==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/range-parser": "*" + } + }, + "@types/mime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", + "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==", + "dev": true + }, "@types/node": { "version": "13.11.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.0.tgz", "integrity": "sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ==", "dev": true }, + "@types/qs": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.1.tgz", + "integrity": "sha512-lhbQXx9HKZAPgBkISrBcmAcMpZsmpe/Cd/hY7LGZS5OfkySUBItnPZHgQPssWYUET8elF+yCFBbP1Q0RZPTdaw==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz", + "integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==", + "dev": true, + "requires": { + "@types/express-serve-static-core": "*", + "@types/mime": "*" + } + }, "@types/socket.io": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.4.tgz", @@ -33,6 +102,12 @@ "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -93,6 +168,12 @@ "type-is": "~1.6.17" } }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -159,6 +240,12 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -379,6 +466,12 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -663,6 +756,22 @@ } } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -678,6 +787,19 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "ts-node": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.8.2.tgz", + "integrity": "sha512-duVj6BpSpUpD/oM4MfhO98ozgkp3Gt9qIp3jGxwU2DFvl/3IRaEAvbLa8G60uS7C77457e/m5TMowjedeRxI1Q==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "3.1.1" + } + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -687,6 +809,12 @@ "mime-types": "~2.1.24" } }, + "typescript": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -716,6 +844,12 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true } } } diff --git a/backend/package.json b/backend/package.json index 11de22f..4f83c0d 100644 --- a/backend/package.json +++ b/backend/package.json @@ -4,8 +4,8 @@ "description": "", "main": "./src/index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "app": "node src/index.js" + "build": "tsc", + "app": "ts-node src/index.ts" }, "author": "", "license": "ISC", @@ -14,6 +14,9 @@ "socket.io": "^2.3.0" }, "devDependencies": { - "@types/socket.io": "^2.1.4" + "@types/express": "^4.17.6", + "@types/socket.io": "^2.1.4", + "ts-node": "^8.8.2", + "typescript": "^3.8.3" } } diff --git a/backend/src/Lobby.js b/backend/src/Lobby.js deleted file mode 100644 index 536207b..0000000 --- a/backend/src/Lobby.js +++ /dev/null @@ -1,160 +0,0 @@ -const User = require("./User.js"); -const timeline = require("./timeline.js"); - -module.exports = class Lobby { - /** - * @type {User[]} - */ - users = []; - /** - * @type {string|undefined} - */ - leaderId = undefined; - - running = false; - startTime = 0; - currentSeconds = 0; - timelineIndex = 0; - - // For debugging purposes - speedFactor = 1; - - constructor(name) { - this.name = name; - } - - run(io) { - this.running = true; - this.startTime = Date.now(); - - const doTick = () => { - if (this.users.length === 0) { - // this lobby is over. - return; - } - - const timestamp = timeline.getIndex(this.timelineIndex); - const nextShot = timeline.getNextShot(this.timelineIndex); - - if (!timestamp) { - // We are done. - io.to(this.name + "").emit('tick_event', { - current: this.currentSeconds - }); - console.log("Done"); - this.running = false; - return; - } - - console.log("ticking", this.currentSeconds); - - io.to(this.name + "").emit('tick_event', { - current: this.currentSeconds, - next: timestamp, - nextShot: nextShot - }); - - if (this.currentSeconds >= timestamp.timestamp) { - this.timelineIndex += 1; - } - - this.currentSeconds += 1; - // We spend some time processing, wait a bit less than 1000ms - const nextTickTime = this.startTime + (1000 * this.currentSeconds / this.speedFactor); - const waitTime = nextTickTime - Date.now(); - console.log("waiting", waitTime); - setTimeout(doTick, Math.floor(waitTime / this.speedFactor)); - }; - - doTick(); - } - - /** - * - * @param io - * @param {number} time - */ - seek(io, time) { - this.currentSeconds = time; - this.startTime = Date.now() - time * 1000; - this.timelineIndex = timeline.indexForTime(this.currentSeconds); - io.to(this.name + "").emit('seek', time); - } - - /** - * - * @returns {boolean} - */ - hasUsers() { - return this.users.length !== 0; - } - - - setRandomLeader() { - if (this.hasUsers()) { - this.leaderId = this.users[0].id; - } - } - - /** - * - * @param {User} user - */ - addUser(user) { - this.users.push(user); - } - - /** - * - * @param id - * @returns {User|undefined} - */ - getUser(id) { - return this.users.find(u => u.id === id); - } - - /** - * - * @param {string} id - */ - removeUser(id) { - this.users = this.users.filter(u => u.id !== id); - } - - /** - * - * @returns {boolean} - */ - hasLeader() { - return !!this.leaderId; - } - - /** - * - * @param {string} id - * @returns {boolean} - */ - isLeader(id) { - return this.leaderId === id; - } - - /** - * - * @param {string} id - */ - setLeader(id) { - if (!this.getUser(id)) { - throw new Error('user_not_in_lobby'); - } - - this.leaderId = id; - } - - /** - * - * @returns {User|undefined} - */ - getLeader() { - return this.users.find(u => u.id === this.leaderId) - } -}; diff --git a/backend/src/Room.ts b/backend/src/Room.ts new file mode 100644 index 0000000..d9aa685 --- /dev/null +++ b/backend/src/Room.ts @@ -0,0 +1,186 @@ +import {Socket} from "socket.io"; + +import User from "./User"; +import {getIndex, getNextShot, getTimeline, indexForTime} from "./timeline"; +import {getCurrentTime} from "./util"; + +export default class Room { + id: number = 0; + users: User[] = []; + leader: User | null = null; + + running = false; + startTime = 0; + currentSeconds = 0; + timelineIndex: number = 0; + + timelineName: string = 'Centurion'; + + // For debugging purposes + speedFactor = 1; + + constructor(name: number) { + this.id = name; + } + + serialize(user: User) { + return { + 'id': this.id, + 'userCount': this.users.length, + 'isLeader': this.leader == user, + 'running': this.running, + 'startTime': this.startTime, + 'timelineName': this.timelineName, + } + } + + serializeTimeline(user: User) { + return getTimeline(this.timelineName); + } + + sync() { + this.users.forEach(u => u.sync()); + } + + join(user: User) { + this.users.push(user); + user.setRoom(this); + + if (!this.hasLeader()) { + this.setLeader(user); + } + + this.sync(); + } + + leave(user: User) { + this.users.splice(this.users.indexOf(user), 1); + user.setRoom(null); + + if (this.leader == user) { + this.setRandomLeader(); + } + + this.sync(); + } + + onBeforeDelete() { + } + + start() { + this.running = true; + this.startTime = getCurrentTime() - 1400 * 1000 + + this.sync(); + } + + run(io: Socket) { + this.running = true; + this.startTime = Date.now(); + + // io.to(this.id.toString()).emit('timeline', { + // 'timeline': { + // } + // }); + + const doTick = () => { + if (this.users.length === 0) { + // this room is over. + return; + } + + const timestamp = getIndex(this.timelineIndex); + const nextShot = getNextShot(this.timelineIndex); + + if (!timestamp) { + // We are done. + io.to(this.id.toString()).emit('tick_event', { + tick: { + current: this.currentSeconds + } + }); + console.log("Done"); + this.running = false; + return; + } + + console.log("ticking", this.currentSeconds); + + io.to(this.id.toString()).emit('tick_event', { + tick: { + current: this.currentSeconds, + next: timestamp, + nextShot: nextShot + } + }); + + if (this.currentSeconds >= timestamp.timestamp) { + this.timelineIndex += 1; + } + + this.currentSeconds += 1; + // We spend some time processing, wait a bit less than 1000ms + const nextTickTime = this.startTime + (1000 * this.currentSeconds / this.speedFactor); + const waitTime = nextTickTime - Date.now(); + console.log("waiting", waitTime); + setTimeout(doTick, Math.floor(waitTime / this.speedFactor)); + }; + + doTick(); + } + + /** + * + * @param io + * @param {number} time + */ + seek(io: Socket, time: number) { + this.currentSeconds = time; + this.startTime = Date.now() - time * 1000; + this.timelineIndex = indexForTime(this.currentSeconds); + io.to(this.id.toString()).emit('seek', time); + } + + /** + * + * @returns {boolean} + */ + hasUsers() { + return this.users.length !== 0; + } + + setRandomLeader() { + if (this.hasUsers()) { + this.leader = this.users[0]; + } + } + + /** + * + * @param id + * @returns {User|undefined} + */ + getUser(id: string) { + return this.users.find(u => u.id === id); + } + + /** + * + * @param {string} id + */ + removeUser(id: string) { + this.users = this.users.filter(u => u.id !== id); + } + + hasLeader(): boolean { + return this.leader != null; + } + + setLeader(user: User) { + this.leader = user; + } + + getLeader(): User | null { + return this.leader; + } +}; diff --git a/backend/src/Service.ts b/backend/src/Service.ts new file mode 100644 index 0000000..b3e3c41 --- /dev/null +++ b/backend/src/Service.ts @@ -0,0 +1,120 @@ +import {Socket} from "socket.io"; + +import User from './User' +import Room from './Room' +import {getCurrentTime, randomInt} from "./util"; + +export default class Service { + private roomIdToRooms = new Map(); + private socketsToUsers = new Map(); + + onSocketConnect(socket: Socket) { + let user = new User(socket); + this.socketsToUsers.set(socket.id, user); + } + + onSocketDisconnect(socket: Socket) { + let user = this.getUser(socket); + + if (user.room != null) { + user.room.leave(user); + } + + this.deleteEmptyRooms(); + + user.onDisconnect(); + } + + onTimeSync(socket: Socket, requestId: number, clientTime: number) { + let user = this.getUser(socket); + + let now = getCurrentTime(); + user.emit('time_sync', { + 'requestId': requestId, + 'clientDiff': now - clientTime, + 'serverTime': now + }) + } + + onRequestStart(socket: Socket) { + let user = this.getUser(socket); + + if (user.room?.getLeader() == user) { + user.room!!.start(); + } + } + + onRequestJoin(socket: Socket, roomId: number): boolean { + let user = this.getUser(socket); + if (!this.roomIdToRooms.has(roomId)) return false; + if (user.room && user.room.id == roomId) return false; + + if (user.room) { + user.room.leave(user); + this.deleteEmptyRooms(); + } + + let room = this.roomIdToRooms.get(roomId)!!; + room.join(user); + return true; + } + + onRequestJoinRandom(socket: Socket) { + let user = this.getUser(socket); + + if (user.room) { + user.room.leave(user); + this.deleteEmptyRooms(); + } + + const room = this.createRandomRoom(); + if (!room) throw Error('Too many rooms active'); + room.join(user); + } + + hasRoomId(roomId: number): boolean { + return this.roomIdToRooms.has(roomId); + } + + private getUser(socket: Socket): User { + let user = this.socketsToUsers.get(socket.id); + if (!user) { + throw new Error('User not found'); + } + return user; + } + + private deleteEmptyRooms() { + for (let room of this.roomIdToRooms.values()) { + if (room.users.length == 0) { + this.deleteRoom(room); + } + } + } + + private createRandomRoom(): Room | null { + let tries = 0; + while (tries++ < 1000) { + const randomId = randomInt(100, Math.max(1000, this.roomIdToRooms.size * 2)); + if (this.roomIdToRooms.has(randomId)) continue; + + return this.createRoomWithId(randomId); + } + return null; + } + + private createRoomWithId(roomId: number): Room { + if (this.roomIdToRooms.has(roomId)) { + throw new Error('A room with the given id already exists'); + } + + let room = new Room(roomId); + this.roomIdToRooms.set(roomId, room); + return room; + } + + private deleteRoom(room: Room) { + this.roomIdToRooms.get(room.id)!!.onBeforeDelete(); + this.roomIdToRooms.delete(room.id) + } +} diff --git a/backend/src/State.js b/backend/src/State.js deleted file mode 100644 index b078181..0000000 --- a/backend/src/State.js +++ /dev/null @@ -1,59 +0,0 @@ -const Lobby = require("./Lobby.js"); -const {getRandomInt} = require("./util.js"); - -class State { - /** - * @type {Object.} - */ - lobbies = {}; - - constructor() { - } - - /** - * @returns {Lobby} - */ - createRandomLobby() { - let lobby = undefined; - - while (!lobby) { - const lobbyCount = Object.keys(this.lobbies).length; - const id = getRandomInt(100, Math.max(1000, lobbyCount * 2)); - lobby = this.createLobby(id); - } - - return lobby; - } - - /** - * - * @param lobbyId - * @returns {Lobby|undefined} - */ - getLobby(lobbyId) { - if (!lobbyId || !this.lobbies.hasOwnProperty(lobbyId)) { - return undefined; - } - - return this.lobbies[lobbyId]; - } - - /** - * Returns undefined when the lobby already exists. - * @param {number} lobbyId - * @returns {Lobby|undefined} - */ - createLobby(lobbyId) { - if (this.lobbies.hasOwnProperty(lobbyId)) { - return undefined; - } - - return new Lobby(lobbyId); - } - - removeLobby(lobbyId) { - delete this.lobbies[lobbyId]; - } -} - -module.exports = new State(); diff --git a/backend/src/User.js b/backend/src/User.js deleted file mode 100644 index b071f72..0000000 --- a/backend/src/User.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = class User { - constructor(id) { - this.id = id; - } -}; \ No newline at end of file diff --git a/backend/src/User.ts b/backend/src/User.ts new file mode 100644 index 0000000..290ddc6 --- /dev/null +++ b/backend/src/User.ts @@ -0,0 +1,77 @@ +import {Socket} from "socket.io"; + +import Room from "./Room"; + +export default class User { + socket: Socket; + id: string; + + room: Room | null = null; + + constructor(socket: Socket) { + this.socket = socket; + this.id = socket.id; + } + + onDisconnect() { + if (this.room != null) { + + } + } + + setRoom(room: Room | null) { + if (this.room === room) return; + + if (this.room != null) { + this.socket.leave(this.room.id.toString()); + } + + this.room = room; + + if (this.room != null) { + this.socket.join(this.room.id.toString()); + } + + this.sync(); + } + + sentRoom: any = null; + sentTimelineName: string | null = null; + + sync() { + if (!this.shallowEquals(this.sentRoom, this.room?.serialize(this))) { + this.sentRoom = this.room?.serialize(this); + this.emit('room', { + 'room': this.sentRoom + }) + } + + if (!this.shallowEquals(this.sentTimelineName, this.room?.timelineName)) { + this.sentTimelineName = this.room?.timelineName || null; + this.emit('timeline', { + 'timeline': this.sentTimelineName == null ? null : this.room!!.serializeTimeline(this) + }) + } + } + + emit(eventName: string, obj: any) { + this.socket.emit(eventName, obj); + } + + shallowEquals(obj1: any, obj2: any) { + if (obj1 === null && obj2 === null) + return true; + + if ((obj1 === null && obj2 !== null) || (obj1 !== null && obj2 === null)) + return false; + + if (typeof (obj1) != typeof (obj2)) + return false; + + if (Object.keys(obj1).length !== Object.keys(obj2).length) return false + + return Object.keys(obj1).every(key => + obj2.hasOwnProperty(key) && obj1[key] === obj2[key] + ); + } +} diff --git a/backend/src/app.js b/backend/src/app.js deleted file mode 100644 index fbbe8b1..0000000 --- a/backend/src/app.js +++ /dev/null @@ -1,22 +0,0 @@ -const express = require("express"); -const socketIO = require("socket.io"); -const state = require("./State.js"); -const path = require("path"); - -const HOST = '0.0.0.0'; -const PORT = 3001; - -const app = express(); -const server = app.listen(PORT, HOST,() => console.log(`Centurion listening on port ${PORT}!`)); -app.use(express.static(path.join(__dirname, '../public'))); - -const io = socketIO(server); - -app.get('/state', (req, res) => res.send('
' + JSON.stringify(state) + '
')); - -process.on('SIGINT', () => process.exit()); -process.on('SIGTERM', () => process.exit()); - -module.exports = { - app, server, io -}; diff --git a/backend/src/index.js b/backend/src/index.js deleted file mode 100644 index 27d757c..0000000 --- a/backend/src/index.js +++ /dev/null @@ -1,80 +0,0 @@ -const service = require("./service.js"); -const state = require("./State.js"); - -const {io} = require('./app.js'); - -io.on('connection', socket => { - const socketId = socket.id; - - console.log('a user connected', socketId); - - const lobby = state.createRandomLobby(); - service.joinLobby(socketId, lobby.name); - socket.join(lobby.name); - socket.emit('welcome', {lobby: lobby}); - - socket.on('disconnect', (reason) => { - console.log('Disconnected:', socketId); - service.leaveLobby(socketId); - }); - - socket.on('join_lobby', (lobbyId, callback) => { - if (!callback || typeof callback !== 'function') { - console.error("Join: Callback not a function."); - return - } - - if (!lobbyId) { - return callback('no_lobby_id_given'); - } - - if (!Number.isSafeInteger(+lobbyId)) { - return callback('lobby_id_not_integer'); - } - - console.log(`${socketId} wants to join '${lobbyId}'.`); - - // Leave current lobby first - service.leaveLobby(socketId); - const lobby = service.joinLobby(socketId, lobbyId); - - socket.join(lobby.name); - - callback(null, { - status: 'ok', - lobby: lobby - }); - }); - - socket.on('lobby_info', callback => { - if (!callback || typeof callback !== 'function') { - console.error("Lobby info: Callback not a function."); - return - } - - const lobby = service.getUserLobby(socketId); - - callback(null, { - status: 'ok', - lobby: lobby - }); - }); - - socket.on('request_start', (time = null) => { - console.log('request start', socket.rooms); - - const lobby = service.getUserLobby(socketId); - if (!lobby.isLeader(socketId)) { - console.warn("Non leader tried to start."); - return; - } - - io.to(lobby.name + "").emit('started'); - lobby.run(io); - - if (typeof time === 'number' && time) { - console.log("Starting at", time); - lobby.seek(io, time); - } - }); -}); diff --git a/backend/src/index.ts b/backend/src/index.ts new file mode 100644 index 0000000..a6cb73f --- /dev/null +++ b/backend/src/index.ts @@ -0,0 +1,175 @@ +import express from "express"; +import SocketIO, {Socket} from "socket.io"; +import path from "path"; + +import Service from './Service' + +// process.on('SIGINT', () => process.exit()); +// process.on('SIGTERM', () => process.exit()); + +const HOST = '0.0.0.0'; +const PORT = 3001; + +const app = express(); +const server = app.listen(PORT, HOST, () => console.log(`Centurion listening on port ${PORT}!`)); +app.use(express.static(path.join(__dirname, '../public'))); + +const io = SocketIO(server); + +const service = new Service(); + +io.on('connection', socket => { + socket.on('disconnect', (reason) => { + service.onSocketDisconnect(socket); + }); + + socket.on('ping', () => { + socket.emit('pong'); + }) + + socket.on('time_sync', (requestId: number, clientTime: number) => { + if (!Number.isSafeInteger(requestId)) return; + if (!Number.isSafeInteger(clientTime)) return; + + service.onTimeSync(socket, requestId, clientTime); + }) + + socket.on('request_start', () => { + service.onRequestStart(socket); + }); + + socket.on('request_join', (roomId: number) => { + if (!Number.isSafeInteger(roomId)) return; + + service.onRequestJoin(socket, roomId); + }); + + socket.on('request_join_random', () => { + service.onRequestJoinRandom(socket); + }) + + socket.on('call', (id: number, name: string, params: any) => { + if (!Number.isSafeInteger(id)) return; + // noinspection SuspiciousTypeOfGuard + if (!name || typeof (name) !== 'string') return; + // if (!params) return; + + let call = new Call(socket, id, name, params); + + if (name == 'room_exists') { + let roomId = params && params['roomId']; + if (!Number.isSafeInteger(roomId)) { + call.error('Invalid room id'); + return; + } + + call.respond(service.hasRoomId(roomId)); + return; + } + + if (name == 'request_join') { + let roomId = params && params['roomId']; + if (!Number.isSafeInteger(roomId)) { + call.error('Invalid room id'); + return; + } + if (!service.hasRoomId(roomId)) { + call.respond(false); + return; + } + if (service.onRequestJoin(socket, roomId)) { + call.respond(true); + } else { + call.respond(false); + } + } + }) + + service.onSocketConnect(socket); + + /*socket.on('join_room', (roomId, callback) => { + if (!callback || typeof callback !== 'function') { + console.error("Join: Callback not a function."); + return + } + + if (!roomId) { + return callback('no_room_id_given'); + } + + if (!Number.isSafeInteger(+roomId)) { + return callback('room_id_not_integer'); + } + + console.log(`${socketId} wants to join '${roomId}'.`); + + // Leave current room first + + let currentRoom = service.getUserRoom(socketId); + if (currentRoom) { + socket.leave(currentRoom.name); + service.leaveRoom(socketId); + } + + const room = service.joinRoom(socketId, roomId); + + socket.join(room.name); + sendRoom(socket, room); + }); + + socket.on('room_info', callback => { + if (!callback || typeof callback !== 'function') { + console.error("Room info: Callback not a function."); + return + } + + const room = service.getUserRoom(socketId); + sendRoom(socket, room); + }); + + socket.on('request_start', (time = null) => { + console.log('request start', socket.rooms); + + const room = service.getUserRoom(socketId); + if (!room.isLeader(socketId)) { + console.warn("Non leader tried to start."); + return; + } + + room.run(io); + sendRoom(io.to(room.name.toString()), room); + + if (typeof time === 'number' && time) { + console.log("Starting at", time); + room.seek(io, time); + } + });*/ +}); + +class Call { + private socket: Socket; + private id: number; + private name: string; + private params: any; + + constructor(socket: Socket, id: number, name: string, params: any) { + this.socket = socket; + this.id = id; + this.name = name; + this.params = params; + } + + error(reason: string) { + this.socket.emit('call_response', { + 'id': this.id, + 'error': reason + }) + } + + respond(data: any) { + this.socket.emit('call_response', { + 'id': this.id, + 'response': data + }); + } +} diff --git a/backend/src/service.js b/backend/src/service.js deleted file mode 100644 index a9431fe..0000000 --- a/backend/src/service.js +++ /dev/null @@ -1,68 +0,0 @@ -const User = require("./User.js"); -const state = require("./State.js"); - -/** - * - * @param {string} socketId - * @param {number} lobbyId - * @returns {Lobby} - */ -function joinLobby(socketId, lobbyId) { - let lobby = state.getLobby(lobbyId); - if (!lobby) { - lobby = state.createLobby(lobbyId); - } - - lobby.addUser(new User(socketId)); - - if (!lobby.hasLeader()) { - lobby.setLeader(socketId); - } - - state.lobbies[lobby.name] = lobby; - return lobby; -} - -function leaveLobby(socketId) { - Object.keys(state.lobbies).forEach(lobbyId => { - const lobby = state.getLobby(lobbyId); - - if (!lobby) { - return; - } - - lobby.removeUser(socketId); - - if (!lobby.hasUsers()) { - state.removeLobby(lobbyId); - return; - } - - if (lobby.getLeader() === socketId) { - lobby.setRandomLeader(); - } - }); -} - -/** - * - * @param socketId - * @returns {Lobby|undefined} - */ -function getUserLobby(socketId) { - for (let lobbyId of Object.keys(state.lobbies)) { - const lobby = state.getLobby(lobbyId); - - if (!lobby) { - continue; - } - - if (lobby.getUser(socketId)) { - return lobby; - } - } - - return undefined; -} - -module.exports = {joinLobby, leaveLobby, getUserLobby}; diff --git a/backend/src/timeline.js b/backend/src/timeline.ts similarity index 64% rename from backend/src/timeline.js rename to backend/src/timeline.ts index ab9a30f..8c75510 100644 --- a/backend/src/timeline.js +++ b/backend/src/timeline.ts @@ -1,11 +1,19 @@ -const timeline = require('../data/timeline.js'); +// @ts-ignore +import timeline from '../data/timelines.js'; + + +export function getTimeline(name: string) { + let t = timeline.timelines.find((i: any) => i.name == name); + if (!t) return null; + return t; +} /** * * @param i * @returns {*} */ -function getIndex(i) { +export function getIndex(i: number): any { if (i >= timeline.length) { return; } @@ -17,7 +25,7 @@ function getIndex(i) { * @param {number} i - the index. * @returns {{count: number, timestamp: number}|undefined} */ -function getNextShot(i) { +export function getNextShot(i: number) { for (; i < timeline.length; i++) { const time = getIndex(i); @@ -34,9 +42,9 @@ function getNextShot(i) { return undefined; } -function indexForTime(seconds) { +export function indexForTime(seconds: number): number { let lastIndex = 0; - for(let i = 0; i < timeline.length; i++) { + for (let i = 0; i < timeline.length; i++) { const time = timeline[i]; if (time.timestamp >= seconds) { @@ -45,8 +53,6 @@ function indexForTime(seconds) { lastIndex = i; } -} -module.exports = { - getIndex, getNextShot, indexForTime -}; \ No newline at end of file + return -1; +} diff --git a/backend/src/util.js b/backend/src/util.js deleted file mode 100644 index 85c0c89..0000000 --- a/backend/src/util.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Generates random int - * @param {number} min, inclusive - * @param {number} max, exclusive - * @returns {number} - */ -function getRandomInt(min, max) { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min)) + min; -} - -module.exports = { - getRandomInt -}; \ No newline at end of file diff --git a/backend/src/util.ts b/backend/src/util.ts new file mode 100644 index 0000000..157e5bd --- /dev/null +++ b/backend/src/util.ts @@ -0,0 +1,20 @@ +/** + * Generates random int + * @param {number} min, inclusive + * @param {number} max, exclusive + * @returns {number} + */ +export function randomInt(min: number, max: number): number { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min)) + min; +} + +let _randomTimeOffsetForDebug = randomInt(-10000, 10000); +_randomTimeOffsetForDebug = 0; + +console.log('random time offset', _randomTimeOffsetForDebug); + +export function getCurrentTime() { + return Date.now() + _randomTimeOffsetForDebug; +} diff --git a/backend/tsconfig.json b/backend/tsconfig.json new file mode 100644 index 0000000..8bb50b5 --- /dev/null +++ b/backend/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "strict": true, + "esModuleInterop": true + } +} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 4403353..21de874 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,27 +12,32 @@ "tinycolor2": "^1.4.1" } }, - "@ant-design/create-react-context": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@ant-design/create-react-context/-/create-react-context-0.2.5.tgz", - "integrity": "sha512-1rMAa4qgP2lfl/QBH9i78+Gjxtj9FTMpMyDGZsEBW5Kih72EuUo9958mV8PgpRkh4uwPSQ7vVZWXeyNZXVAFDg==", + "@ant-design/icons": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-4.0.6.tgz", + "integrity": "sha512-Hvly7PhImdZo5+UnpRPSpqcYFttTEE9ELCgir6R9cPe99IHciLv97EZTshYTFp4T6i2q0x9nuSLpG11UFeu4Dg==", "requires": { - "gud": "^1.0.0", - "warning": "^4.0.3" + "@ant-design/colors": "^3.1.0", + "@ant-design/icons-svg": "^4.0.0", + "classnames": "^2.2.6", + "insert-css": "^2.0.0", + "rc-util": "^4.9.0" } }, - "@ant-design/icons": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz", - "integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w==" + "@ant-design/icons-svg": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.0.0.tgz", + "integrity": "sha512-Nai+cd3XUrv/z50gSk1FI08j6rENZ1e93rhKeLTBGwa5WrmHvhn2vowa5+voZW2qkXJn1btS6tdvTEDB90M0Pw==" }, - "@ant-design/icons-react": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@ant-design/icons-react/-/icons-react-2.0.1.tgz", - "integrity": "sha512-r1QfoltMuruJZqdiKcbPim3d8LNsVPB733U0gZEUSxBLuqilwsW28K2rCTWSMTjmFX7Mfpf+v/wdiFe/XCqThw==", + "@ant-design/react-slick": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-0.25.5.tgz", + "integrity": "sha512-fusHR9LkarCARvYTN6cG3yz2/Ogf+HTaJ2XEihIjsjgm6uE1aSXycRFEVDpOFP1Aib51Z2Iz3tgg/gL+WbK8rQ==", "requires": { - "@ant-design/colors": "^3.1.0", - "babel-runtime": "^6.26.0" + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "lodash": "^4.17.15", + "resize-observer-polyfill": "^1.5.0" } }, "@babel/code-frame": { @@ -1624,6 +1629,15 @@ "@types/node": "*" } }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "@types/istanbul-lib-coverage": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", @@ -1701,10 +1715,10 @@ "@types/react": "*" } }, - "@types/react-slick": { - "version": "0.23.4", - "resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.4.tgz", - "integrity": "sha512-vXoIy4GUfB7/YgqubR4H7RALo+pRdMYCeLgWwV3MPwl5pggTlEkFBTF19R7u+LJc85uMqC7RfsbkqPLMQ4ab+A==", + "@types/react-lifecycles-compat": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/react-lifecycles-compat/-/react-lifecycles-compat-3.0.1.tgz", + "integrity": "sha512-4KiU5s1Go4xRbf7t6VxUUpBeN5PGjpjpBv9VvET4uiPHC500VNYBclU13f8ehHkHoZL39b2cfwHu6RzbV3b44A==", "requires": { "@types/react": "*" } @@ -1717,6 +1731,11 @@ "@types/react": "*" } }, + "@types/shallowequal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/shallowequal/-/shallowequal-1.1.1.tgz", + "integrity": "sha512-Lhni3aX80zbpdxRuWhnuYPm8j8UQaa571lHP/xI4W+7BAFhSIhRReXnqjEgT/XzPoXZTJkCqstFMJ8CZTK6IlQ==" + }, "@types/socket.io-client": { "version": "1.4.32", "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.32.tgz", @@ -2251,63 +2270,53 @@ } }, "antd": { - "version": "3.26.15", - "resolved": "https://registry.npmjs.org/antd/-/antd-3.26.15.tgz", - "integrity": "sha512-OAcfz9D1Qt+4Fme4E0DfCKuWm/1RIVrJZzaTYVCGOnVAHJjoxEtKCoCrcj/8wwCS9LbXHVci/s2u/gY+QmtCSw==", - "requires": { - "@ant-design/create-react-context": "^0.2.4", - "@ant-design/icons": "~2.1.1", - "@ant-design/icons-react": "~2.0.1", - "@types/react-slick": "^0.23.4", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/antd/-/antd-4.1.4.tgz", + "integrity": "sha512-YRF/nrAq4R+olKRJxEDqeO4xkTvx+U6ovIQjGew1JDiEHMMhSftpvpYg2Iu5hRdFL66uxQk6VYngMttBpuYm9Q==", + "requires": { + "@ant-design/icons": "^4.0.0", + "@ant-design/react-slick": "~0.25.5", "array-tree-filter": "^2.1.0", - "babel-runtime": "6.x", "classnames": "~2.2.6", "copy-to-clipboard": "^3.2.0", "css-animation": "^1.5.0", - "dom-closest": "^0.2.0", - "enquire.js": "^2.1.6", - "is-mobile": "^2.1.0", "lodash": "^4.17.13", "moment": "^2.24.0", "omit.js": "^1.0.2", "prop-types": "^15.7.2", "raf": "^3.4.1", - "rc-animate": "^2.10.2", - "rc-calendar": "~9.15.7", - "rc-cascader": "~0.17.4", - "rc-checkbox": "~2.1.6", + "rc-animate": "~2.10.2", + "rc-cascader": "~1.0.0", + "rc-checkbox": "~2.2.0", "rc-collapse": "~1.11.3", "rc-dialog": "~7.6.0", "rc-drawer": "~3.1.1", - "rc-dropdown": "~2.4.1", - "rc-editor-mention": "^1.1.13", - "rc-form": "^2.4.10", - "rc-input-number": "~4.5.0", - "rc-mentions": "~0.4.0", - "rc-menu": "~7.5.1", - "rc-notification": "~3.3.1", - "rc-pagination": "~1.20.11", + "rc-dropdown": "~3.0.0", + "rc-field-form": "~1.1.0", + "rc-input-number": "~4.5.4", + "rc-mentions": "~1.1.0", + "rc-menu": "~8.0.1", + "rc-notification": "~4.0.0", + "rc-pagination": "~2.2.0", + "rc-picker": "~1.4.0", "rc-progress": "~2.5.0", - "rc-rate": "~2.5.0", - "rc-resize-observer": "^0.1.0", - "rc-select": "~9.2.0", - "rc-slider": "~8.7.1", + "rc-rate": "~2.5.1", + "rc-resize-observer": "^0.2.0", + "rc-select": "~10.2.0", + "rc-slider": "~9.2.3", "rc-steps": "~3.5.0", "rc-switch": "~1.9.0", - "rc-table": "~6.10.5", - "rc-tabs": "~9.7.0", - "rc-time-picker": "~3.7.1", - "rc-tooltip": "~3.7.3", - "rc-tree": "~2.1.0", - "rc-tree-select": "~2.9.1", - "rc-trigger": "^2.6.2", - "rc-upload": "~2.9.1", - "rc-util": "^4.16.1", - "react-lazy-load": "^3.0.13", - "react-lifecycles-compat": "^3.0.4", - "react-slick": "~0.25.2", + "rc-table": "~7.4.2", + "rc-tabs": "~10.1.1", + "rc-tooltip": "~4.0.2", + "rc-tree": "~3.1.0", + "rc-tree-select": "~3.1.0", + "rc-trigger": "~4.0.0", + "rc-upload": "~3.0.0", + "rc-util": "^4.20.0", + "rc-virtual-list": "^1.1.0", "resize-observer-polyfill": "^1.5.1", - "shallowequal": "^1.1.0", + "scroll-into-view-if-needed": "^2.2.20", "warning": "~4.0.3" } }, @@ -2513,9 +2522,9 @@ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, "async-validator": { - "version": "1.11.5", - "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.11.5.tgz", - "integrity": "sha512-XNtCsMAeAH1pdLMEg1z8/Bb3a8cdCbui9QbJATRFHHHW5kT6+NPI3zSVQUXgikTFITzsg+kYY5NTWhM2Orwt9w==" + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-3.2.4.tgz", + "integrity": "sha512-mTgzMJixkrh+5t2gbYoua8MLy11GHkQqFE6tbhY5Aqc4jEDGsR4BWP+sVQiYDHtzTMB8WIwI/ypObTVPcTZInw==" }, "asynckit": { "version": "0.4.0", @@ -3719,6 +3728,11 @@ } } }, + "compute-scroll-into-view": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.13.tgz", + "integrity": "sha512-o+w9w7A98aAFi/GjK8cxSV+CdASuPa2rR5UWs3+yHkJzWqaKoBEufFNWYaXInCSmUfDCVhesG+v9MTWqOjsxFg==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3909,16 +3923,6 @@ "sha.js": "^2.4.8" } }, - "create-react-class": { - "version": "15.6.3", - "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz", - "integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==", - "requires": { - "fbjs": "^0.8.9", - "loose-envify": "^1.3.1", - "object-assign": "^4.1.1" - } - }, "cross-spawn": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", @@ -4559,14 +4563,6 @@ "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.11.1.tgz", "integrity": "sha512-hN42DmUgtweBx0iBjDLO4WtKOMcK8yBmPx/fgdsgQadLuzPu/8co3oLdK5yMmeM/vnUd3yDyV6qV8/NzxBexQg==" }, - "dom-closest": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-closest/-/dom-closest-0.2.0.tgz", - "integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=", - "requires": { - "dom-matches": ">=1.0.1" - } - }, "dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", @@ -4584,16 +4580,6 @@ "csstype": "^2.6.7" } }, - "dom-matches": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-matches/-/dom-matches-2.0.0.tgz", - "integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw=" - }, - "dom-scroll-into-view": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-1.2.1.tgz", - "integrity": "sha1-6PNnMt0ImwIBqI14Fdw/iObWbH4=" - }, "dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", @@ -4672,16 +4658,6 @@ "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" }, - "draft-js": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.10.5.tgz", - "integrity": "sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==", - "requires": { - "fbjs": "^0.8.15", - "immutable": "~3.7.4", - "object-assign": "^4.1.0" - } - }, "duplexer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", @@ -4746,14 +4722,6 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "requires": { - "iconv-lite": "~0.4.13" - } - }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -4828,11 +4796,6 @@ } } }, - "enquire.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz", - "integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ=" - }, "entities": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", @@ -5384,11 +5347,6 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==" }, - "eventlistener": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/eventlistener/-/eventlistener-0.0.1.tgz", - "integrity": "sha1-7Suqu4UiJ68rz4iRUscsY8pTLrg=" - }, "events": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", @@ -5752,27 +5710,6 @@ "bser": "2.1.1" } }, - "fbjs": { - "version": "0.8.17", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", - "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", - "requires": { - "core-js": "^1.0.0", - "isomorphic-fetch": "^2.1.1", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.18" - }, - "dependencies": { - "core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" - } - } - }, "figgy-pudding": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", @@ -6236,11 +6173,6 @@ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" }, - "gud": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", - "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==" - }, "gzip-size": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", @@ -6652,11 +6584,6 @@ "resolved": "https://registry.npmjs.org/immer/-/immer-1.10.0.tgz", "integrity": "sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg==" }, - "immutable": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", - "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks=" - }, "import-cwd": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", @@ -6834,6 +6761,11 @@ } } }, + "insert-css": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/insert-css/-/insert-css-2.0.0.tgz", + "integrity": "sha1-610Ql7dUL0x56jBg067gfQU4gPQ=" + }, "internal-ip": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", @@ -7019,11 +6951,6 @@ "is-extglob": "^2.1.1" } }, - "is-mobile": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-2.2.1.tgz", - "integrity": "sha512-6zELsfVFr326eq2CI53yvqq6YBanOxKBybwDT+MbMS2laBnK6Ez8m5XHSuTQQbnKRfpDzCod1CMWW5q3wZYMvA==" - }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -7160,15 +7087,6 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "requires": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" - } - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -8867,11 +8785,6 @@ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" - }, "lodash.flow": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", @@ -8905,11 +8818,6 @@ "lodash._reinterpolate": "^3.0.0" } }, - "lodash.throttle": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" - }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -9215,21 +9123,18 @@ } }, "mini-store": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mini-store/-/mini-store-2.0.0.tgz", - "integrity": "sha512-EG0CuwpQmX+XL4QVS0kxNwHW5ftSbhygu1qxQH0pipugjnPkbvkalCdQbEihMwtQY6d3MTN+MS0q+aurs+RfLQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mini-store/-/mini-store-3.0.2.tgz", + "integrity": "sha512-TM7IQBu+mVssLQReprx7JGftXk0EyaiIWw7yAx6E4SIZRHwgQ8XcG4dINFAaBCBihbYPJyhf7kbz7e5qk1FkuQ==", "requires": { - "hoist-non-react-statics": "^2.3.1", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/react-lifecycles-compat": "^3.0.1", + "@types/shallowequal": "^1.1.1", + "hoist-non-react-statics": "^3.3.2", "prop-types": "^15.6.0", "react-lifecycles-compat": "^3.0.4", - "shallowequal": "^1.0.2" - }, - "dependencies": { - "hoist-non-react-statics": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", - "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" - } + "shallowequal": "^1.0.2", + "typescript": "^3.8.3" } }, "minimalistic-assert": { @@ -9391,11 +9296,6 @@ "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" }, - "mutationobserver-shim": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/mutationobserver-shim/-/mutationobserver-shim-0.3.5.tgz", - "integrity": "sha512-YAMuSp4Oi19SYQF04dGnRajyFp4Wyam+jKKWzm5roPcNh1Rip8dnHPxls5F/xBgY0H2gV+3IzWuIvYQPDAvmBQ==" - }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -9465,15 +9365,6 @@ "tslib": "^1.10.0" } }, - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } - }, "node-forge": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", @@ -9671,6 +9562,17 @@ "prepend-http": "^1.0.0", "query-string": "^4.1.0", "sort-keys": "^1.0.0" + }, + "dependencies": { + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + } } }, "npm-run-path": { @@ -11322,14 +11224,6 @@ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "requires": { - "asap": "~2.0.3" - } - }, "promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", @@ -11437,12 +11331,20 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.12.1.tgz", + "integrity": "sha512-OHj+zzfRMyj3rmo/6G8a5Ifvw3AleL/EbcHMD27YA31Q+cO5lfmQxECkImuNVjcskLcvBRVHNAB3w6udMs1eAA==", "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" + "decode-uri-component": "^0.2.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "dependencies": { + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" + } } }, "querystring": { @@ -11509,14 +11411,14 @@ } }, "rc-align": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-2.4.5.tgz", - "integrity": "sha512-nv9wYUYdfyfK+qskThf4BQUSIadeI/dCsfaMZfNEoxm9HwOIioQ+LyqmMK6jWHAZQgOzMLaqawhuBXlF63vgjw==", + "version": "3.0.0-rc.1", + "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-3.0.0-rc.1.tgz", + "integrity": "sha512-GbofumhCUb7SxP410j/fbtR2M9Zml+eoZSdaliZh6R3NhfEj5zP4jcO3HG3S9C9KIcXQQtd/cwVHkb9Y0KU7Hg==", "requires": { - "babel-runtime": "^6.26.0", + "classnames": "2.x", "dom-align": "^1.7.0", - "prop-types": "^15.5.8", - "rc-util": "^4.0.4" + "rc-util": "^4.12.0", + "resize-observer-polyfill": "^1.5.1" } }, "rc-animate": { @@ -11533,43 +11435,24 @@ "react-lifecycles-compat": "^3.0.4" } }, - "rc-calendar": { - "version": "9.15.10", - "resolved": "https://registry.npmjs.org/rc-calendar/-/rc-calendar-9.15.10.tgz", - "integrity": "sha512-xh1A3rYejKskAvkjnd9BcHXFbBnAYsHMGHBdtoAkbwp43B6yEieNL0g0Tzz8s1gApDZV2j5vF1jJ9IIpPYFNLw==", - "requires": { - "babel-runtime": "6.x", - "classnames": "2.x", - "moment": "2.x", - "prop-types": "^15.5.8", - "rc-trigger": "^2.2.0", - "rc-util": "^4.1.1", - "react-lifecycles-compat": "^3.0.4" - } - }, "rc-cascader": { - "version": "0.17.5", - "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-0.17.5.tgz", - "integrity": "sha512-WYMVcxU0+Lj+xLr4YYH0+yXODumvNXDcVEs5i7L1mtpWwYkubPV/zbQpn+jGKFCIW/hOhjkU4J1db8/P/UKE7A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-1.0.1.tgz", + "integrity": "sha512-3mk33+YKJBP1XSrTYbdVLuCC73rUDq5STNALhvua5i8vyIgIxtb5fSl96JdWWq1Oj8tIBoHnCgoEoOYnIXkthQ==", "requires": { "array-tree-filter": "^2.1.0", - "prop-types": "^15.5.8", - "rc-trigger": "^2.2.0", + "rc-trigger": "^4.0.0", "rc-util": "^4.0.4", - "react-lifecycles-compat": "^3.0.4", - "shallow-equal": "^1.0.0", "warning": "^4.0.1" } }, "rc-checkbox": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.1.8.tgz", - "integrity": "sha512-6qOgh0/by0nVNASx6LZnhRTy17Etcgav+IrI7kL9V9kcDZ/g7K14JFlqrtJ3NjDq/Kyn+BPI1st1XvbkhfaJeg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.2.0.tgz", + "integrity": "sha512-Wjh/nutLA8iIPTT1P9I9KOqlUblVe+CWa3SxMibFySnLyYbMxKNtPhwNcbADPOqzNU0AsCntTduNeJg1n0B5fg==", "requires": { "babel-runtime": "^6.23.0", - "classnames": "2.x", - "prop-types": "15.x", - "react-lifecycles-compat": "^3.0.4" + "classnames": "2.x" } }, "rc-collapse": { @@ -11607,58 +11490,23 @@ } }, "rc-dropdown": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-2.4.1.tgz", - "integrity": "sha512-p0XYn0wrOpAZ2fUGE6YJ6U8JBNc5ASijznZ6dkojdaEfQJAeZtV9KMEewhxkVlxGSbbdXe10ptjBlTEW9vEwEg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-3.0.2.tgz", + "integrity": "sha512-T3XP4qL6xmkxn8z52YF2SEPoMHPpBiLf0Kty3mjNdRSyKnlu+0F+3bhDHf6gO1msmqrjURaz8sMNAFDcoFHHnw==", "requires": { "babel-runtime": "^6.26.0", "classnames": "^2.2.6", - "prop-types": "^15.5.8", - "rc-trigger": "^2.5.1", - "react-lifecycles-compat": "^3.0.2" + "rc-trigger": "^4.0.0" } }, - "rc-editor-core": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/rc-editor-core/-/rc-editor-core-0.8.10.tgz", - "integrity": "sha512-T3aHpeMCIYA1sdAI7ynHHjXy5fqp83uPlD68ovZ0oClTSc3tbHmyCxXlA+Ti4YgmcpCYv7avF6a+TIbAka53kw==", - "requires": { - "babel-runtime": "^6.26.0", - "classnames": "^2.2.5", - "draft-js": "^0.10.0", - "immutable": "^3.7.4", - "lodash": "^4.16.5", - "prop-types": "^15.5.8", - "setimmediate": "^1.0.5" - } - }, - "rc-editor-mention": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/rc-editor-mention/-/rc-editor-mention-1.1.13.tgz", - "integrity": "sha512-3AOmGir91Fi2ogfRRaXLtqlNuIwQpvla7oUnGHS1+3eo7b+fUp5IlKcagqtwUBB5oDNofoySXkLBxzWvSYNp/Q==", - "requires": { - "babel-runtime": "^6.23.0", - "classnames": "^2.2.5", - "dom-scroll-into-view": "^1.2.0", - "draft-js": "~0.10.0", - "immutable": "~3.7.4", - "prop-types": "^15.5.8", - "rc-animate": "^2.3.0", - "rc-editor-core": "~0.8.3" - } - }, - "rc-form": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/rc-form/-/rc-form-2.4.11.tgz", - "integrity": "sha512-8BL+FNlFLTOY/A5X6tU35GQJLSIpsmqpwn/tFAYQTczXc4dMJ33ggtH248Cum8+LS0jLTsJKG2L4Qp+1CkY+sA==", + "rc-field-form": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.1.3.tgz", + "integrity": "sha512-m7SUNNaum4pHrUj5MGnymEk3SRitMUZBhnMS0wqWrcL6XqvdTAG5Yz5HjukA6BryaS6nyQOgUVBXMxxNN/XsTQ==", "requires": { - "async-validator": "~1.11.3", - "babel-runtime": "6.x", - "create-react-class": "^15.5.3", - "dom-scroll-into-view": "1.x", - "hoist-non-react-statics": "^3.3.0", - "lodash": "^4.17.4", - "rc-util": "^4.15.3", + "@babel/runtime": "^7.8.4", + "async-validator": "^3.0.3", + "rc-util": "^4.17.0", "warning": "^4.0.3" } }, @@ -11685,55 +11533,59 @@ } }, "rc-mentions": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-0.4.2.tgz", - "integrity": "sha512-DTZurQzacLXOfVuiHydGzqkq7cFMHXF18l2jZ9PhWUn2cqvOSY3W4osN0Pq29AOMOBpcxdZCzgc7Lb0r/bgkDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.1.0.tgz", + "integrity": "sha512-uOVMiQ5Jxfo3mbpOZsZt20Alid0268lX9eBR2I/chly0qhNbmSB71iLOHGkbL7zuHd50GF/eSr9fXJJQKUYG1Q==", "requires": { - "@ant-design/create-react-context": "^0.2.4", "classnames": "^2.2.6", - "rc-menu": "^7.4.22", - "rc-trigger": "^2.6.2", - "rc-util": "^4.6.0", - "react-lifecycles-compat": "^3.0.4" + "rc-menu": "^8.0.1", + "rc-trigger": "^4.0.0", + "rc-util": "^4.6.0" } }, "rc-menu": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-7.5.5.tgz", - "integrity": "sha512-4YJXJgrpUGEA1rMftXN7bDhrV5rPB8oBJoHqT+GVXtIWCanfQxEnM3fmhHQhatL59JoAFMZhJaNzhJIk4FUWCQ==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-8.0.3.tgz", + "integrity": "sha512-a37l9MfzjXt8/q5en6ukjD2PoVsHCzWeRPdFK9eWi6hF5/9M3mfxgUt1LruQvaJKMQUxDyN5+4M8FsYULXJALw==", "requires": { "classnames": "2.x", - "dom-scroll-into-view": "1.x", - "mini-store": "^2.0.0", - "mutationobserver-shim": "^0.3.2", + "mini-store": "^3.0.1", "rc-animate": "^2.10.1", - "rc-trigger": "^2.3.0", + "rc-trigger": "^4.0.0", "rc-util": "^4.13.0", "resize-observer-polyfill": "^1.5.0", + "scroll-into-view-if-needed": "^2.2.20", "shallowequal": "^1.1.0" } }, "rc-notification": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-3.3.1.tgz", - "integrity": "sha512-U5+f4BmBVfMSf3OHSLyRagsJ74yKwlrQAtbbL5ijoA0F2C60BufwnOcHG18tVprd7iaIjzZt1TKMmQSYSvgrig==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-4.0.0.tgz", + "integrity": "sha512-In9FimkJY+JSIq3/eopPfBpQQr2Zugq5i9Aw9vdiNCGCsAsSO9bGq2dPsn8bamOydNrhc3djljGfmxUUMbcZnA==", "requires": { - "babel-runtime": "6.x", "classnames": "2.x", - "prop-types": "^15.5.8", "rc-animate": "2.x", "rc-util": "^4.0.4" } }, "rc-pagination": { - "version": "1.20.14", - "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-1.20.14.tgz", - "integrity": "sha512-sNKwbFrxiqATqcIIShfrFs8BT03n4UUwTAMYae+JhHTmILQmXdvimEnZbVuWcno6G02DAJcLrFpmkn1h2tmEJw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-2.2.0.tgz", + "integrity": "sha512-fXempMD/kvHu8tsiW70uPjn1pI4mdD62xFG9drcBh17gj5CbCjazrjpWS615RSauk3b2BBgIcAJzREAMvlAkFQ==", "requires": { - "babel-runtime": "6.x", - "classnames": "^2.2.6", - "prop-types": "^15.5.7", - "react-lifecycles-compat": "^3.0.4" + "classnames": "^2.2.1" + } + }, + "rc-picker": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-1.4.9.tgz", + "integrity": "sha512-Lg/+06ozXEsivYit+fNET6IKSY8xnWEDsuQiRjJttsELg1kE3JyCZflaX98nCxkg+2IQqMPVXLuKIiaYGr43Uw==", + "requires": { + "classnames": "^2.2.1", + "moment": "^2.24.0", + "rc-trigger": "^4.0.0", + "rc-util": "^4.17.0", + "shallowequal": "^1.1.0" } }, "rc-progress": { @@ -11757,45 +11609,37 @@ } }, "rc-resize-observer": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-0.1.3.tgz", - "integrity": "sha512-uzOQEwx83xdQSFOkOAM7x7GHIQKYnrDV4dWxtCxyG1BS1pkfJ4EvDeMfsvAJHSYkQXVBu+sgRHGbRtLG3qiuUg==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-0.2.1.tgz", + "integrity": "sha512-GENTRkL3lq05ilrjTxPpHUPrKTC9D7XqUGesSXgi/GyO4j/jKIjLPn7zuZOcJ5QmN5QGRe24IaVWPZHQPE6vLw==", "requires": { "classnames": "^2.2.1", - "rc-util": "^4.13.0", + "rc-util": "^4.14.0", "resize-observer-polyfill": "^1.5.1" } }, "rc-select": { - "version": "9.2.3", - "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-9.2.3.tgz", - "integrity": "sha512-WhswxOMWiNnkXRbxyrj0kiIvyCfo/BaRPaYbsDetSIAU2yEDwKHF798blCP5u86KLOBKBvtxWLFCkSsQw1so5w==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-10.2.4.tgz", + "integrity": "sha512-PtfAHQRXof5gX1qEYQc8GIgroajtzU3mcMGbqM1aE1jqaZ4r+p0GJy3rabXoNANsKH7jUV5+zYJb5VhTxj2vmQ==", "requires": { - "babel-runtime": "^6.23.0", "classnames": "2.x", - "component-classes": "1.x", - "dom-scroll-into-view": "1.x", - "prop-types": "^15.5.8", - "raf": "^3.4.0", - "rc-animate": "2.x", - "rc-menu": "^7.3.0", - "rc-trigger": "^2.5.4", - "rc-util": "^4.0.4", - "react-lifecycles-compat": "^3.0.2", - "warning": "^4.0.2" + "rc-animate": "^2.10.0", + "rc-trigger": "^4.0.0", + "rc-util": "^4.20.0", + "rc-virtual-list": "^1.1.2", + "warning": "^4.0.3" } }, "rc-slider": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-8.7.1.tgz", - "integrity": "sha512-WMT5mRFUEcrLWwTxsyS8jYmlaMsTVCZIGENLikHsNv+tE8ThU2lCoPfi/xFNUfJFNFSBFP3MwPez9ZsJmNp13g==", + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-9.2.4.tgz", + "integrity": "sha512-wSr7vz+WtzzGqsGU2rTQ4mmLz9fkuIDMPYMYm8ygYFvxQ2Rh4uRhOWHYI0R8krNK5k1bGycckYxmQqUIvLAh3w==", "requires": { "babel-runtime": "6.x", "classnames": "^2.2.5", - "prop-types": "^15.5.4", - "rc-tooltip": "^3.7.0", + "rc-tooltip": "^4.0.0", "rc-util": "^4.0.4", - "react-lifecycles-compat": "^3.0.4", "shallowequal": "^1.1.0", "warning": "^4.0.3" } @@ -11822,149 +11666,85 @@ } }, "rc-table": { - "version": "6.10.14", - "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-6.10.14.tgz", - "integrity": "sha512-yn47IqxXA4bzPAs1Aai7WwNzOBpuH1mm+GYrIIOUuGySaxz20Wr3udbRF+gLzEbG14CWUxomvcUaXyWPWdH08w==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.4.5.tgz", + "integrity": "sha512-lQS9izhGmgyCVK05imUrl32lBS9g2f3hB8LOKOof19JWCULKuYL5D3lLpaZSpCTecRYfONYNpgR7mZs7FOnYSQ==", "requires": { "classnames": "^2.2.5", "component-classes": "^1.2.6", "lodash": "^4.17.5", - "mini-store": "^2.0.0", "prop-types": "^15.5.8", - "rc-util": "^4.13.0", + "raf": "^3.4.1", + "rc-resize-observer": "^0.2.0", + "rc-util": "^4.20.1", "react-lifecycles-compat": "^3.0.2", - "shallowequal": "^1.0.2" + "shallowequal": "^1.1.0" } }, "rc-tabs": { - "version": "9.7.0", - "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-9.7.0.tgz", - "integrity": "sha512-kvmgp8/MfLzFZ06hWHignqomFQ5nF7BqKr5O1FfhE4VKsGrep52YSF/1MvS5oe0NPcI9XGNS2p751C5v6cYDpQ==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-10.1.1.tgz", + "integrity": "sha512-dOFeaYil3d6zV3ZtGZWfRf7zwyqUQ48cl67/Y/03SsBWEdYgfZzlgjfHqmUT+V7L7CvhQ5lIQyYpj4EthkgKCg==", "requires": { - "@ant-design/create-react-context": "^0.2.4", - "babel-runtime": "6.x", "classnames": "2.x", "lodash": "^4.17.5", - "prop-types": "15.x", - "raf": "^3.4.1", "rc-hammerjs": "~0.6.0", - "rc-util": "^4.0.4", - "react-lifecycles-compat": "^3.0.4", "resize-observer-polyfill": "^1.5.1", "warning": "^4.0.3" } }, - "rc-time-picker": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/rc-time-picker/-/rc-time-picker-3.7.3.tgz", - "integrity": "sha512-Lv1Mvzp9fRXhXEnRLO4nW6GLNxUkfAZ3RsiIBsWjGjXXvMNjdr4BX/ayElHAFK0DoJqOhm7c5tjmIYpEOwcUXg==", - "requires": { - "classnames": "2.x", - "moment": "2.x", - "prop-types": "^15.5.8", - "raf": "^3.4.1", - "rc-trigger": "^2.2.0", - "react-lifecycles-compat": "^3.0.4" - } - }, "rc-tooltip": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.3.tgz", - "integrity": "sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-4.0.3.tgz", + "integrity": "sha512-HNyBh9/fPdds0DXja8JQX0XTIHmZapB3lLzbdn74aNSxXG1KUkt+GK4X1aOTRY5X9mqm4uUKdeFrn7j273H8gw==", "requires": { - "babel-runtime": "6.x", - "prop-types": "^15.5.8", - "rc-trigger": "^2.2.2" + "rc-trigger": "^4.0.0" } }, "rc-tree": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.3.tgz", - "integrity": "sha512-COvV65spQ6omrHBUhHRKqKNL5+ddXjlS+qWZchaL9FFuQNvjM5pjp9RnmMWK4fJJ5kBhhpLneh6wh9Vh3kSMXQ==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-3.1.5.tgz", + "integrity": "sha512-LOUfsJg5XxtA4FKgGkuVwnbBlnh3VVtySF7LMp4ko0n8oIUBYnn2vs6WG41kuH0V4tLTlQhvCFup/6JEKL01sg==", "requires": { - "@ant-design/create-react-context": "^0.2.4", "classnames": "2.x", "prop-types": "^15.5.8", - "rc-animate": "^2.6.0", - "rc-util": "^4.5.1", - "react-lifecycles-compat": "^3.0.4", - "warning": "^4.0.3" + "rc-animate": "^2.9.2", + "rc-util": "^4.11.0", + "rc-virtual-list": "^1.1.0", + "react-lifecycles-compat": "^3.0.4" } }, "rc-tree-select": { - "version": "2.9.4", - "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-2.9.4.tgz", - "integrity": "sha512-0HQkXAN4XbfBW20CZYh3G+V+VMrjX42XRtDCpyv6PDUm5vikC0Ob682ZBCVS97Ww2a5Hf6Ajmu0ahWEdIEpwhg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-3.1.3.tgz", + "integrity": "sha512-VQDr+qLCCJ9V/4ewnp3crMT2N7iJV58V0uWVA3nGJxVuxhSj8TPHFZLnyMh6vaNrQsrY6eBp/x1y6nEJBjnVQg==", "requires": { - "classnames": "^2.2.1", - "dom-scroll-into-view": "^1.2.1", - "prop-types": "^15.5.8", - "raf": "^3.4.0", - "rc-animate": "^2.8.2", - "rc-tree": "~2.1.0", - "rc-trigger": "^3.0.0", - "rc-util": "^4.5.0", - "react-lifecycles-compat": "^3.0.4", - "shallowequal": "^1.0.2", - "warning": "^4.0.1" - }, - "dependencies": { - "rc-trigger": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-3.0.0.tgz", - "integrity": "sha512-hQxbbJpo23E2QnYczfq3Ec5J5tVl2mUDhkqxrEsQAqk16HfADQg+iKNWzEYXyERSncdxfnzYuaBgy764mNRzTA==", - "requires": { - "babel-runtime": "6.x", - "classnames": "^2.2.6", - "prop-types": "15.x", - "raf": "^3.4.0", - "rc-align": "^2.4.1", - "rc-animate": "^3.0.0-rc.1", - "rc-util": "^4.15.7" - }, - "dependencies": { - "rc-animate": { - "version": "3.0.0-rc.6", - "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.0.0-rc.6.tgz", - "integrity": "sha512-oBLPpiT6Q4t6YvD/pkLcmofBP1p01TX0Otse8Q4+Mxt8J+VSDflLZGIgf62EwkvRwsQUkLPjZVFBsldnPKLzjg==", - "requires": { - "babel-runtime": "6.x", - "classnames": "^2.2.5", - "component-classes": "^1.2.6", - "fbjs": "^0.8.16", - "prop-types": "15.x", - "raf": "^3.4.0", - "rc-util": "^4.5.0", - "react-lifecycles-compat": "^3.0.4" - } - } - } - } + "classnames": "2.x", + "rc-select": "^10.1.0", + "rc-tree": "^3.1.0", + "rc-util": "^4.17.0" } }, "rc-trigger": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-2.6.5.tgz", - "integrity": "sha512-m6Cts9hLeZWsTvWnuMm7oElhf+03GOjOLfTuU0QmdB9ZrW7jR2IpI5rpNM7i9MvAAlMAmTx5Zr7g3uu/aMvZAw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-4.0.2.tgz", + "integrity": "sha512-to5S1NhK10rWHIgQpoQdwIhuDc2Ok4R4/dh5NLrDt6C+gqkohsdBCYiPk97Z+NwGhRU8N+dbf251bivX8DkzQg==", "requires": { - "babel-runtime": "6.x", "classnames": "^2.2.6", "prop-types": "15.x", - "rc-align": "^2.4.0", - "rc-animate": "2.x", - "rc-util": "^4.4.0", - "react-lifecycles-compat": "^3.0.4" + "raf": "^3.4.1", + "rc-align": "^3.0.0-rc.0", + "rc-animate": "^2.10.2", + "rc-util": "^4.20.0" } }, "rc-upload": { - "version": "2.9.4", - "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-2.9.4.tgz", - "integrity": "sha512-WXt0HGxXyzLrPV6iec/96Rbl/6dyrAW8pKuY6wwD7yFYwfU5bjgKjv7vC8KNMJ6wzitFrZjnoiogNL3dF9dj3Q==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-3.0.4.tgz", + "integrity": "sha512-dTCvj1iHxjHG0qo5UyN2ZmtueG9GG3xrOhOwnjsehaoOvl0TOjLbHkUIPPqLZk+wHb57Ue4KB7c3+IMgkDoBvw==", "requires": { "babel-runtime": "6.x", - "classnames": "^2.2.5", - "prop-types": "^15.5.7", - "warning": "4.x" + "classnames": "^2.2.5" } }, "rc-util": { @@ -11979,6 +11759,16 @@ "shallowequal": "^1.1.0" } }, + "rc-virtual-list": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-1.1.2.tgz", + "integrity": "sha512-+WwxrtmBta7vcPCty7MtgilBmbxSGwN28Y8o+MG3GkHZccV0tXT+PLnAB+5WOjhhH10iFq+pzviRcXgcZ1x4OA==", + "requires": { + "classnames": "^2.2.6", + "raf": "^3.4.1", + "rc-util": "^4.8.0" + } + }, "react": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", @@ -12303,17 +12093,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "react-lazy-load": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/react-lazy-load/-/react-lazy-load-3.0.13.tgz", - "integrity": "sha1-OwqS0zbUPT8Nc8vm81sXBQsIuCQ=", - "requires": { - "eventlistener": "0.0.1", - "lodash.debounce": "^4.0.0", - "lodash.throttle": "^4.0.0", - "prop-types": "^15.5.8" - } - }, "react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -12404,18 +12183,6 @@ } } }, - "react-slick": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.25.2.tgz", - "integrity": "sha512-8MNH/NFX/R7zF6W/w+FS5VXNyDusF+XDW1OU0SzODEU7wqYB+ZTGAiNJ++zVNAVqCAHdyCybScaUB+FCZOmBBw==", - "requires": { - "classnames": "^2.2.5", - "enquire.js": "^2.1.6", - "json2mq": "^0.2.0", - "lodash.debounce": "^4.0.8", - "resize-observer-polyfill": "^1.5.0" - } - }, "react-transition-group": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.3.0.tgz", @@ -13032,6 +12799,14 @@ "ajv-keywords": "^3.4.1" } }, + "scroll-into-view-if-needed": { + "version": "2.2.24", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.24.tgz", + "integrity": "sha512-vsC6SzyIZUyJG8o4nbUDCiIwsPdH6W/FVmjT2avR2hp/yzS53JjGmg/bKD20TkoNajbu5dAQN4xR7yes4qhwtQ==", + "requires": { + "compute-scroll-into-view": "^1.0.13" + } + }, "scss-tokenizer": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", @@ -13273,11 +13048,6 @@ } } }, - "shallow-equal": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", - "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" - }, "shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", @@ -13684,6 +13454,11 @@ } } }, + "split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -14574,11 +14349,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==" }, - "ua-parser-js": { - "version": "0.7.21", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz", - "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==" - }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", diff --git a/frontend/package.json b/frontend/package.json index 7c84d05..282025b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,8 +11,9 @@ "@types/react": "^16.9.19", "@types/react-dom": "^16.9.5", "@types/react-transition-group": "^4.2.3", - "antd": "^3.26.9", + "antd": "^4.1.4", "node-sass": "^4.13.1", + "query-string": "^6.12.1", "react": "^16.12.0", "react-dom": "^16.12.0", "react-scripts": "^3.4.0", diff --git a/frontend/src/components/App.tsx b/frontend/src/components/App.tsx index 57212bc..e15f5b5 100644 --- a/frontend/src/components/App.tsx +++ b/frontend/src/components/App.tsx @@ -1,13 +1,10 @@ import React from 'react'; -import {SocketIOProvider} from "use-socketio/lib"; import Centurion from "./Centurion"; const App = () => { return ( - - - + ); }; diff --git a/frontend/src/components/Centurion.tsx b/frontend/src/components/Centurion.tsx index 39f5588..8460ce9 100644 --- a/frontend/src/components/Centurion.tsx +++ b/frontend/src/components/Centurion.tsx @@ -1,76 +1,38 @@ -import React, {useEffect, useRef, useState} from "react"; +import React, {useRef, useState} from "react"; import {Row} from "antd"; -import {useSocket} from "use-socketio"; import {NumberParam, useQueryParam} from "use-query-params"; -import {Tick} from "../types/types"; - +import {roomTime, useRoom, useRoomRunningChanged, useTick} from "../lib/Connection"; import NextShot from "./NextShot"; import Feed from "./Feed"; import ShotsTaken from "./ShotsTaken"; import Lobby from "./Lobby"; import logo from "../img/via-logo.svg"; +import Player from "./Player"; const Centurion = () => { - const [started, setStarted] = useState(false); - const [wantsToStart, setWantsToStart] = useState(false); - const player = useRef(new Audio("centurion.m4a")); - const [noSound] = useQueryParam('noSound', NumberParam); - - function goStart() { - console.log("Starting from wrapper.."); - setWantsToStart(true); - } - - - useSocket("started", async (obj: any) => { - console.log("got started"); - setStarted(true); - - if (typeof noSound === 'undefined') { - await player.current.play(); - } - }); - - useEffect(() => { - if (noSound === 1) { - // Won't play sound so we don't get DOM Interaction errors. - setWantsToStart(true); - } - }, [noSound]); - - useSocket("tick_event", async (tick: Tick) => { - if (!started && wantsToStart) { - if (player.current.paused) { - if (typeof noSound === 'undefined') { - await player.current.play(); - } - } - - setStarted(true); - player.current.currentTime = tick.current; - } - }); + let roomRunning = useRoomRunningChanged()?.running || false; const feedContent = ( - - - - - + + + + + + + + ); const lobbyContent = ( - + ); - const content = started ? feedContent : lobbyContent; - return ( <>
- {content} + {roomRunning ? feedContent : lobbyContent}