Compare commits
21 Commits
1970610b4d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 946e4020d9 | |||
| 571c749e25 | |||
| 718407d709 | |||
| 348a074a3a | |||
| 6c70628616 | |||
| e64288694b | |||
| ee95be1031 | |||
| 5f6251114f | |||
| a49013fc0c | |||
| 3cd7be1e7b | |||
| 415f417182 | |||
| 6e08884bd6 | |||
| aa351b566a | |||
| 22b2289933 | |||
| 293b6f0266 | |||
| 9cc58c20f4 | |||
| 6203332841 | |||
| a7b20d997e | |||
| 314496438a | |||
| f55f7ef827 | |||
| 802583d834 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.idea
|
||||||
BIN
I projekat DW.pdf
Normal file
BIN
I projekat DW.pdf
Normal file
Binary file not shown.
@@ -1,28 +0,0 @@
|
|||||||
Game,Event_Name,Start_Date,End_Date,Prize_Pool_USD,Num_Participants,Winner,Runner_Up,Game_Type,Platform,Club_Championship_Points,Gender
|
|
||||||
Rennsport,Rennsport R1 at EWC 2025,2025-07-08,2025-07-11,500000,9,BMW M Team Redline Red Bull Sim Racing,Virtus.pro,Racing,PC,Yes,
|
|
||||||
Valorant,Esports World Cup 2025,2025-07-08,2025-07-13,1250000,16,Team Heretics,Fnatic,Tactical Shooter,PC,Yes,
|
|
||||||
Dota 2,Esports World Cup 2025,2025-07-08,2025-07-19,3000000,16,Team Spirit,Team Falcons,MOBA,PC,Yes,
|
|
||||||
Fatal Fury: City of the Wolves,Esports World Cup 2025,2025-07-10,2025-07-12,1000000,16,GO1 (DetonatioN FocusMe),Xiaohai (KuaiShou Gaming),Fighting,Console/PC,Yes,
|
|
||||||
Apex Legends,ALGS 2025 Midseason Playoffs,2025-07-10,2025-07-13,2000000,40,VK Gaming,ROC Esports,Battle Royale,PC/Console,Yes,
|
|
||||||
Mobile Legends: Bang Bang,MLBB Mid Season Cup 2025,2025-07-10,2025-08-02,3000000,23,Team Liquid PH,SRG.OG,MOBA,Mobile,Yes,Men
|
|
||||||
Mobile Legends: Bang Bang,MLBB Women's Invitational 2025,2025-07-15,2025-07-19,500000,16,Team Vitality,Gaimin Gladiators,MOBA,Mobile,Yes,Women
|
|
||||||
Honor of Kings,HoK World Cup 2025,2025-07-15,2025-07-26,3000000,18,AG.AL,ThunderTalk Global,MOBA,Mobile,Yes,
|
|
||||||
Free Fire,Esports World Cup 2025,2025-07-16,2025-07-20,1000000,18,EVOS Esports,Rex Regum Qeon,Battle Royale,Mobile,Yes,
|
|
||||||
League of Legends,Esports World Cup 2025,2025-07-16,2025-07-20,2000000,12,Gen.G,AG.AL,MOBA,PC,Yes,
|
|
||||||
StarCraft II,Esports World Cup 2025,2025-07-22,2025-07-25,700000,18,Serral (Basilisk),Classic (Virtus.pro),RTS,PC,Yes,
|
|
||||||
Call of Duty: Black Ops 6,Esports World Cup 2025,2025-07-24,2025-07-27,1800000,16,OpTic Gaming,Vancouver Surge,FPS,Console/PC,Yes,
|
|
||||||
PUBG Mobile,PUBG Mobile World Cup 2025,2025-07-25,2025-08-03,3000000,24,Yangon Galacticos,Weibo Gaming,Battle Royale,Mobile,Yes,
|
|
||||||
Chess,Esports World Cup 2025,2025-07-29,2025-08-01,1500000,16,Magnus Carlsen (Team Liquid),Alireza Firouzja (Team Falcons),Strategy,Online,Yes,
|
|
||||||
Overwatch 2,OWCS Midseason Championship 2025,2025-07-31,2025-08-03,1000000,16,Team Falcons,Al Qadsiah,FPS,PC,Yes,
|
|
||||||
Rainbow Six Siege X,Esports World Cup 2025,2025-08-05,2025-08-09,2000000,16,Team Secret,G2 Esports,Tactical Shooter,PC,Yes,
|
|
||||||
Call of Duty: Warzone,Esports World Cup 2025,2025-08-06,2025-08-09,1000000,21,Twisted Minds,Gentle Mates,Battle Royale,Console/PC,Yes,
|
|
||||||
EA Sports FC 25,FC Pro 25 World Championship,2025-08-07,2025-08-10,1000000,32,ManuBachoore (Team Liquid),Brice (Team Vitality),Sports,Console/PC,Yes,
|
|
||||||
Teamfight Tactics,Esports World Cup 2025,2025-08-11,2025-08-15,500000,16,Weibo Gaming,Virtus.pro,Auto Battler,PC,Yes,
|
|
||||||
PUBG: Battlegrounds,Esports World Cup 2025,2025-08-12,2025-08-16,2000000,24,Twisted Minds,Gen.G,Battle Royale,PC,Yes,
|
|
||||||
Tekken 8,Esports World Cup 2025,2025-08-13,2025-08-16,1000000,32,ULSAN (DN Freecs),LOWHIGH (DRX),Fighting,Console/PC,Yes,
|
|
||||||
Rocket League,Esports World Cup 2025,2025-08-14,2025-08-17,1000000,16,Karmine Corp,Geekay Esports,Sports,PC/Console,Yes,
|
|
||||||
CrossFire,Esports World Cup 2025,2025-08-19,2025-08-23,2000000,16,AG.AL,BaiSha Gaming,FPS,PC,Yes,
|
|
||||||
Street Fighter 6,Esports World Cup 2025,2025-08-20,2025-08-23,1000000,48,Xiaohai (KuaiShou Gaming),Blaz (2Game Esports),Fighting,Console/PC,Yes,
|
|
||||||
Counter-Strike 2,Esports World Cup 2025,2025-08-20,2025-08-24,1250000,16,The MongolZ,Aurora Gaming,FPS,PC,Yes,
|
|
||||||
Naraka: Bladepoint,Mid-Season Championship 2025 Solo,2025-08-19,2025-08-19,150000,12,TBD,TBD,Battle Royale,PC,No,
|
|
||||||
Naraka: Bladepoint,Mid-Season Championship 2025 Trios,2025-08-20,2025-08-20,350000,12,TBD,TBD,Battle Royale,PC,No,
|
|
||||||
|
@@ -1,258 +0,0 @@
|
|||||||
Event,Medal,Team_Organization,Player,Country,Role
|
|
||||||
Apex Legends,Gold,VK Gaming,Kasssa,Brazil,Player
|
|
||||||
Apex Legends,Gold,VK Gaming,QQ,China,Player
|
|
||||||
Apex Legends,Gold,VK Gaming,LqDuD,China,Player
|
|
||||||
Apex Legends,Silver,ROC Esports,Vaxlon,Philippines,Player
|
|
||||||
Apex Legends,Silver,ROC Esports,Deeds,Australia,Player
|
|
||||||
Apex Legends,Silver,ROC Esports,Sauceror,USA,Player
|
|
||||||
Apex Legends,Bronze,Ninjas in Pyjamas,Vein,USA,Player
|
|
||||||
Apex Legends,Bronze,Ninjas in Pyjamas,Kurev,Russia,Player
|
|
||||||
Apex Legends,Bronze,Ninjas in Pyjamas,McLovin,USA,Player
|
|
||||||
Call of Duty: Black Ops 6,Gold,OpTic Gaming,Dashy,USA,Player
|
|
||||||
Call of Duty: Black Ops 6,Gold,OpTic Gaming,Huke,USA,Player
|
|
||||||
Call of Duty: Black Ops 6,Gold,OpTic Gaming,Mercules,USA,Player
|
|
||||||
Call of Duty: Black Ops 6,Gold,OpTic Gaming,Shotzzy,USA,Player
|
|
||||||
Call of Duty: Black Ops 6,Silver,Vancouver Surge,04,Canada,Player
|
|
||||||
Call of Duty: Black Ops 6,Silver,Vancouver Surge,Abuzah,Morocco,Player
|
|
||||||
Call of Duty: Black Ops 6,Silver,Vancouver Surge,Neptune,USA,Player
|
|
||||||
Call of Duty: Black Ops 6,Silver,Vancouver Surge,Nastie,UK,Player
|
|
||||||
Call of Duty: Black Ops 6,Bronze,Movistar KOI,Abe,Spain,Player
|
|
||||||
Call of Duty: Black Ops 6,Bronze,Movistar KOI,CleanX,Denmark,Player
|
|
||||||
Call of Duty: Black Ops 6,Bronze,Movistar KOI,Insight,UK,Player
|
|
||||||
Call of Duty: Black Ops 6,Bronze,Movistar KOI,JoeDeceives,USA,Player
|
|
||||||
Call of Duty: Warzone,Gold,Twisted Minds,zSmit,USA,Player
|
|
||||||
Call of Duty: Warzone,Gold,Twisted Minds,Almond,USA,Player
|
|
||||||
Call of Duty: Warzone,Gold,Twisted Minds,Aydan,USA,Player
|
|
||||||
Call of Duty: Warzone,Silver,Gentle Mates,Enkeo,France,Player
|
|
||||||
Call of Duty: Warzone,Silver,Gentle Mates,Gromalok,France,Player
|
|
||||||
Call of Duty: Warzone,Silver,Gentle Mates,HalloW,France,Player
|
|
||||||
Call of Duty: Warzone,Bronze,Virtus.pro,Dongy,South Korea,Player
|
|
||||||
Call of Duty: Warzone,Bronze,Virtus.pro,Newbz,USA,Player
|
|
||||||
Call of Duty: Warzone,Bronze,Virtus.pro,Sage,USA,Player
|
|
||||||
Chess,Gold,Team Liquid,Magnus Carlsen,Norway,Player
|
|
||||||
Chess,Silver,Team Falcons,Alireza Firouzja,France,Player
|
|
||||||
Chess,Bronze,Team Falcons,Hikaru Nakamura,USA,Player
|
|
||||||
CrossFire,Gold,AG.AL,ZY,China,Player
|
|
||||||
CrossFire,Gold,AG.AL,Jwei,China,Player
|
|
||||||
CrossFire,Gold,AG.AL,Doo,China,Player
|
|
||||||
CrossFire,Gold,AG.AL,1222,China,Player
|
|
||||||
CrossFire,Gold,AG.AL,ZQ,China,Player
|
|
||||||
CrossFire,Silver,BaiSha Gaming,Xxiao,China,Player
|
|
||||||
CrossFire,Silver,BaiSha Gaming,N9,China,Player
|
|
||||||
CrossFire,Silver,BaiSha Gaming,577,China,Player
|
|
||||||
CrossFire,Silver,BaiSha Gaming,Lye,China,Player
|
|
||||||
CrossFire,Silver,BaiSha Gaming,YDSS,China,Player
|
|
||||||
CrossFire,Bronze,Evolution Power,ZAY,China,Player
|
|
||||||
CrossFire,Bronze,Evolution Power,mino,China,Player
|
|
||||||
CrossFire,Bronze,Evolution Power,YZK,China,Player
|
|
||||||
CrossFire,Bronze,Evolution Power,yh,China,Player
|
|
||||||
CrossFire,Bronze,Evolution Power,xqq,China,Player
|
|
||||||
Counter-Strike 2,Gold,The MongolZ,Techno4K,Mongolia,Player
|
|
||||||
Counter-Strike 2,Gold,The MongolZ,910,Mongolia,Player
|
|
||||||
Counter-Strike 2,Gold,The MongolZ,mzinho,Mongolia,Player
|
|
||||||
Counter-Strike 2,Gold,The MongolZ,bLitz,Mongolia,Player
|
|
||||||
Counter-Strike 2,Gold,The MongolZ,Senzu,Mongolia,Player
|
|
||||||
Counter-Strike 2,Silver,Aurora Gaming,MAJ3R,Turkey,Player
|
|
||||||
Counter-Strike 2,Silver,Aurora Gaming,XANTARES,Turkey,Player
|
|
||||||
Counter-Strike 2,Silver,Aurora Gaming,woxic,Turkey,Player
|
|
||||||
Counter-Strike 2,Silver,Aurora Gaming,Wicadia,Turkey,Player
|
|
||||||
Counter-Strike 2,Silver,Aurora Gaming,jottAAA,Turkey,Player
|
|
||||||
Counter-Strike 2,Bronze,Team Falcons,NiKo,Bosnia,Player
|
|
||||||
Counter-Strike 2,Bronze,Team Falcons,TeSeS,Denmark,Player
|
|
||||||
Counter-Strike 2,Bronze,Team Falcons,m0NESY,Russia,Player
|
|
||||||
Counter-Strike 2,Bronze,Team Falcons,kyxsan,Bosnia,Player
|
|
||||||
Counter-Strike 2,Bronze,Team Falcons,kyousuke,Russia,Player
|
|
||||||
Dota 2,Gold,Team Spirit,Yatoro,Ukraine,Carry
|
|
||||||
Dota 2,Gold,Team Spirit,Larl,Russia,Mid
|
|
||||||
Dota 2,Gold,Team Spirit,Collapse,Russia,Offlane
|
|
||||||
Dota 2,Gold,Team Spirit,Rue,Russia,Support
|
|
||||||
Dota 2,Gold,Team Spirit,Miposhka,Russia,Support
|
|
||||||
Dota 2,Silver,Team Falcons,skiter,Slovakia,Carry
|
|
||||||
Dota 2,Silver,Team Falcons,Malr1ne,Ukraine,Mid
|
|
||||||
Dota 2,Silver,Team Falcons,ATF,Jordan,Offlane
|
|
||||||
Dota 2,Silver,Team Falcons,Cr1t-,Denmark,Support
|
|
||||||
Dota 2,Silver,Team Falcons,Sneyking,USA,Support
|
|
||||||
Dota 2,Bronze,Parivision,Satanic,Russia,Carry
|
|
||||||
Dota 2,Bronze,Parivision,No[o]ne-,Ukraine,Mid
|
|
||||||
Dota 2,Bronze,Parivision,DM,Ukraine,Offlane
|
|
||||||
Dota 2,Bronze,Parivision,9Class,Russia,Support
|
|
||||||
Dota 2,Bronze,Parivision,Dukalis,Russia,Support
|
|
||||||
EA Sports FC 25,Gold,Team Liquid,ManuBachoore,Netherlands,Player
|
|
||||||
EA Sports FC 25,Silver,Team Vitality,Brice,France,Player
|
|
||||||
EA Sports FC 25,Bronze,Team Liquid,Levi de Weerd,Netherlands,Player
|
|
||||||
Fatal Fury: City of the Wolves,Gold,DetonatioN FocusMe,GO1,Japan,Player
|
|
||||||
Fatal Fury: City of the Wolves,Silver,KuaiShou Gaming,Xiaohai,China,Player
|
|
||||||
Fatal Fury: City of the Wolves,Bronze,Natus Vincere,DarkAngel,South Korea,Player
|
|
||||||
Free Fire,Gold,EVOS Esports,Rasyah,Indonesia,Player
|
|
||||||
Free Fire,Gold,EVOS Esports,AimGOD,Indonesia,Player
|
|
||||||
Free Fire,Gold,EVOS Esports,Reyyy,Indonesia,Player
|
|
||||||
Free Fire,Gold,EVOS Esports,Koceel,Indonesia,Player
|
|
||||||
Free Fire,Silver,Rex Regum Qeon,Dutzz,Indonesia,Player
|
|
||||||
Free Fire,Silver,Rex Regum Qeon,Abay,Indonesia,Player
|
|
||||||
Free Fire,Silver,Rex Regum Qeon,18Deer,Indonesia,Player
|
|
||||||
Free Fire,Silver,Rex Regum Qeon,Maal,Indonesia,Player
|
|
||||||
Free Fire,Bronze,Team Vitality,JUMP,Thailand,Player
|
|
||||||
Free Fire,Bronze,Team Vitality,COUGAR,Thailand,Player
|
|
||||||
Free Fire,Bronze,Team Vitality,ZEN1S,Thailand,Player
|
|
||||||
Free Fire,Bronze,Team Vitality,DON,Thailand,Player
|
|
||||||
Honor of Kings,Gold,AG.AL,Ran,China,Player
|
|
||||||
Honor of Kings,Gold,AG.AL,Zoe,China,Player
|
|
||||||
Honor of Kings,Gold,AG.AL,Sheng,China,Player
|
|
||||||
Honor of Kings,Gold,AG.AL,YiNuo,China,Player
|
|
||||||
Honor of Kings,Gold,AG.AL,Shuai,China,Player
|
|
||||||
Honor of Kings,Silver,ThunderTalk Global,Qing,China,Player
|
|
||||||
Honor of Kings,Silver,ThunderTalk Global,Sunrise,China,Player
|
|
||||||
Honor of Kings,Silver,ThunderTalk Global,Crane,China,Player
|
|
||||||
Honor of Kings,Silver,ThunderTalk Global,Snowy,China,Player
|
|
||||||
Honor of Kings,Silver,ThunderTalk Global,Joy,China,Player
|
|
||||||
Honor of Kings,Bronze,Nova Esports,Xuan,China,Player
|
|
||||||
Honor of Kings,Bronze,Nova Esports,Cy,China,Player
|
|
||||||
Honor of Kings,Bronze,Nova Esports,Wendy,China,Player
|
|
||||||
Honor of Kings,Bronze,Nova Esports,Muci,China,Player
|
|
||||||
Honor of Kings,Bronze,Nova Esports,Weipit,China,Player
|
|
||||||
League of Legends,Gold,Gen.G,Kiin,South Korea,Top
|
|
||||||
League of Legends,Gold,Gen.G,Canyon,South Korea,Jungle
|
|
||||||
League of Legends,Gold,Gen.G,Chovy,South Korea,Mid
|
|
||||||
League of Legends,Gold,Gen.G,Ruler,South Korea,ADC
|
|
||||||
League of Legends,Gold,Gen.G,Duro,South Korea,Support
|
|
||||||
League of Legends,Silver,AG.AL,Flandre,China,Top
|
|
||||||
League of Legends,Silver,AG.AL,Tarzan,South Korea,Jungle
|
|
||||||
League of Legends,Silver,AG.AL,Shanks,China,Mid
|
|
||||||
League of Legends,Silver,AG.AL,Hope,China,ADC
|
|
||||||
League of Legends,Silver,AG.AL,Kael,South Korea,Support
|
|
||||||
League of Legends,Bronze,T1,Doran,South Korea,Top
|
|
||||||
League of Legends,Bronze,T1,Oner,South Korea,Jungle
|
|
||||||
League of Legends,Bronze,T1,Faker,South Korea,Mid
|
|
||||||
League of Legends,Bronze,T1,Gumayusi,South Korea,ADC
|
|
||||||
League of Legends,Bronze,T1,Keria,South Korea,Support
|
|
||||||
Mobile Legends: Bang Bang - Men,Gold,Team Liquid PH,Sanford,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Gold,Team Liquid PH,KarlTzy,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Gold,Team Liquid PH,Sanji,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Gold,Team Liquid PH,Oheb,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Gold,Team Liquid PH,Jaypee,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Silver,SRG.OG,Kramm,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Silver,SRG.OG,Sekys,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Silver,SRG.OG,Stormie,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Silver,SRG.OG,Innocent,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Silver,SRG.OG,Yums,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Bronze,Onic Philippines,Kirk,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Bronze,Onic Philippines,K1NG KONG,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Bronze,Onic Philippines,Super Frince,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Bronze,Onic Philippines,Kelra,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Men,Bronze,Onic Philippines,Brusko,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Gold,Team Vitality,Fumi,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Gold,Team Vitality,Vival,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Gold,Team Vitality,Cinny,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Gold,Team Vitality,Chell,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Gold,Team Vitality,Vivian,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Silver,Gaimin Gladiators,Aria,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Silver,Gaimin Gladiators,Nicholette,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Silver,Gaimin Gladiators,Sayori,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Silver,Gaimin Gladiators,Panda,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Silver,Gaimin Gladiators,Ashlay,Philippines,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Bronze,Terror Queens,Hlaing,Myanmar,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Bronze,Terror Queens,Ruli,Myanmar,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Bronze,Terror Queens,LunaLynn,Myanmar,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Bronze,Terror Queens,CKOSHIII,Myanmar,Player
|
|
||||||
Mobile Legends: Bang Bang - Women,Bronze,Terror Queens,Kuu,Myanmar,Player
|
|
||||||
Overwatch 2,Gold,Team Falcons,Proper,South Korea,DPS
|
|
||||||
Overwatch 2,Gold,Team Falcons,MER1T,South Korea,DPS
|
|
||||||
Overwatch 2,Gold,Team Falcons,SOMEONE,South Korea,Tank
|
|
||||||
Overwatch 2,Gold,Team Falcons,Hanbin,South Korea,Tank
|
|
||||||
Overwatch 2,Gold,Team Falcons,ChiYo,South Korea,Support
|
|
||||||
Overwatch 2,Gold,Team Falcons,Fielder,South Korea,Support
|
|
||||||
Overwatch 2,Silver,Al Qadsiah,LBBD7,Saudi Arabia,Player
|
|
||||||
Overwatch 2,Silver,Al Qadsiah,CheckMate,Saudi Arabia,Player
|
|
||||||
Overwatch 2,Silver,Al Qadsiah,ZIYAD,Saudi Arabia,Player
|
|
||||||
Overwatch 2,Silver,Al Qadsiah,Landon,Saudi Arabia,Player
|
|
||||||
Overwatch 2,Silver,Al Qadsiah,Kellex,Saudi Arabia,Player
|
|
||||||
Overwatch 2,Bronze,Twisted Minds,Quartz,Saudi Arabia,Player
|
|
||||||
Overwatch 2,Bronze,Twisted Minds,Youbi,Saudi Arabia,Player
|
|
||||||
Overwatch 2,Bronze,Twisted Minds,KSAA,Saudi Arabia,Player
|
|
||||||
Overwatch 2,Bronze,Twisted Minds,FunnyAstro,UK,Player
|
|
||||||
Overwatch 2,Bronze,Twisted Minds,Simple,Saudi Arabia,Player
|
|
||||||
PUBG: Battlegrounds,Gold,Twisted Minds,xmpl,Russia,Player
|
|
||||||
PUBG: Battlegrounds,Gold,Twisted Minds,BatulinS,Russia,Player
|
|
||||||
PUBG: Battlegrounds,Gold,Twisted Minds,Perfect1ks,Russia,Player
|
|
||||||
PUBG: Battlegrounds,Gold,Twisted Minds,Lu,Russia,Player
|
|
||||||
PUBG: Battlegrounds,Silver,Gen.G,Tosi,South Korea,Player
|
|
||||||
PUBG: Battlegrounds,Silver,Gen.G,F1ame,South Korea,Player
|
|
||||||
PUBG: Battlegrounds,Silver,Gen.G,Orca,South Korea,Player
|
|
||||||
PUBG: Battlegrounds,Silver,Gen.G,BeaN,South Korea,Player
|
|
||||||
PUBG: Battlegrounds,Bronze,Team Falcons,hwinn,USA,Player
|
|
||||||
PUBG: Battlegrounds,Bronze,Team Falcons,TGLTN,Australia,Player
|
|
||||||
PUBG: Battlegrounds,Bronze,Team Falcons,Shrimzy,USA,Player
|
|
||||||
PUBG: Battlegrounds,Bronze,Team Falcons,Kickstart,USA,Player
|
|
||||||
PUBG Mobile,Gold,Yangon Galacticos,Smile,Myanmar,Player
|
|
||||||
PUBG Mobile,Gold,Yangon Galacticos,Marnett,Myanmar,Player
|
|
||||||
PUBG Mobile,Gold,Yangon Galacticos,Romeo,Myanmar,Player
|
|
||||||
PUBG Mobile,Gold,Yangon Galacticos,SAYCLOUD,Myanmar,Player
|
|
||||||
PUBG Mobile,Silver,Weibo Gaming,Suk,China,Player
|
|
||||||
PUBG Mobile,Silver,Weibo Gaming,Order,China,Player
|
|
||||||
PUBG Mobile,Silver,Weibo Gaming,33z,China,Player
|
|
||||||
PUBG Mobile,Silver,Weibo Gaming,HECC,China,Player
|
|
||||||
PUBG Mobile,Bronze,Alpha Gaming,Zyol,Mongolia,Player
|
|
||||||
PUBG Mobile,Bronze,Alpha Gaming,DOK,Mongolia,Player
|
|
||||||
PUBG Mobile,Bronze,Alpha Gaming,REFUS,Mongolia,Player
|
|
||||||
PUBG Mobile,Bronze,Alpha Gaming,TOP,Mongolia,Player
|
|
||||||
Rainbow Six Siege X,Gold,Team Secret,Savage,Brazil,Player
|
|
||||||
Rainbow Six Siege X,Gold,Team Secret,jume,Brazil,Player
|
|
||||||
Rainbow Six Siege X,Gold,Team Secret,Adrian,Brazil,Player
|
|
||||||
Rainbow Six Siege X,Gold,Team Secret,Mowwwgli,Brazil,Player
|
|
||||||
Rainbow Six Siege X,Gold,Team Secret,NoaUrz,Brazil,Player
|
|
||||||
Rainbow Six Siege X,Silver,G2 Esports,Alem4o,Brazil,Player
|
|
||||||
Rainbow Six Siege X,Silver,G2 Esports,Doki,UK,Player
|
|
||||||
Rainbow Six Siege X,Silver,G2 Esports,BlaZ,France,Player
|
|
||||||
Rainbow Six Siege X,Silver,G2 Esports,Loira,Brazil,Player
|
|
||||||
Rainbow Six Siege X,Silver,G2 Esports,Stompn,Brazil,Player
|
|
||||||
Rainbow Six Siege X,Bronze,Furia Esports,FelipeX,Brazil,Player
|
|
||||||
Rainbow Six Siege X,Bronze,Furia Esports,HerdsZ,Brazil,Player
|
|
||||||
Rainbow Six Siege X,Bronze,Furia Esports,Jv92,Brazil,Player
|
|
||||||
Rainbow Six Siege X,Bronze,Furia Esports,Kheyze,Brazil,Player
|
|
||||||
Rainbow Six Siege X,Bronze,Furia Esports,nade,Brazil,Player
|
|
||||||
Rennsport,Gold,BMW M Team Redline Red Bull Sim Racing,Luke Bennett,UK,Driver
|
|
||||||
Rennsport,Gold,BMW M Team Redline Red Bull Sim Racing,Jeffery Rietveld,Netherlands,Driver
|
|
||||||
Rennsport,Gold,BMW M Team Redline Red Bull Sim Racing,Sebastian Job,Germany,Driver
|
|
||||||
Rennsport,Gold,BMW M Team Redline Red Bull Sim Racing,Kevin Siggy,Austria,Driver
|
|
||||||
Rennsport,Silver,Virtus.pro,Kevin Ellis Jr,USA,Driver
|
|
||||||
Rennsport,Silver,Virtus.pro,Dáire McCormack,Ireland,Driver
|
|
||||||
Rennsport,Silver,Virtus.pro,Vojtěch Fiala,Czech Republic,Driver
|
|
||||||
Rennsport,Silver,Virtus.pro,Mikhail Statsenko,Russia,Driver
|
|
||||||
Rennsport,Bronze,Team Vitality,Thibault Cazaubon,France,Driver
|
|
||||||
Rennsport,Bronze,Team Vitality,Marcell Csincsik,Hungary,Driver
|
|
||||||
Rennsport,Bronze,Team Vitality,Erhan Jajovski,North Macedonia,Driver
|
|
||||||
Rennsport,Bronze,Team Vitality,Jiri Toman,Czech Republic,Driver
|
|
||||||
Rocket League,Gold,Karmine Corp,Vatira,France,Player
|
|
||||||
Rocket League,Gold,Karmine Corp,Atow,France,Player
|
|
||||||
Rocket League,Gold,Karmine Corp,dralii,France,Player
|
|
||||||
Rocket League,Silver,Geekay Esports,Archie,UK,Player
|
|
||||||
Rocket League,Silver,Geekay Esports,Joyo,USA,Player
|
|
||||||
Rocket League,Silver,Geekay Esports,oaly,Netherlands,Player
|
|
||||||
Rocket League,Bronze,Team Falcons,Trk511,Saudi Arabia,Player
|
|
||||||
Rocket League,Bronze,Team Falcons,Rw9,Saudi Arabia,Player
|
|
||||||
Rocket League,Bronze,Team Falcons,Kiileerrz,Saudi Arabia,Player
|
|
||||||
StarCraft II,Gold,Basilisk,Serral,Finland,Player
|
|
||||||
StarCraft II,Silver,Virtus.pro,Classic,South Korea,Player
|
|
||||||
StarCraft II,Bronze,Team Liquid,Cure,South Korea,Player
|
|
||||||
Street Fighter 6,Gold,KuaiShou Gaming,Xiaohai,China,Player
|
|
||||||
Street Fighter 6,Silver,2Game Esports,Blaz,South Korea,Player
|
|
||||||
Street Fighter 6,Bronze,DRX,Leshar,South Korea,Player
|
|
||||||
Teamfight Tactics,Gold,Weibo Gaming,Saopimi,China,Player
|
|
||||||
Teamfight Tactics,Gold,Weibo Gaming,LBTZ,China,Player
|
|
||||||
Teamfight Tactics,Gold,Weibo Gaming,Guan,China,Player
|
|
||||||
Teamfight Tactics,Gold,Weibo Gaming,TianLong,China,Player
|
|
||||||
Teamfight Tactics,Silver,Virtus.pro,Maris,Russia,Player
|
|
||||||
Teamfight Tactics,Silver,Virtus.pro,Milo,Russia,Player
|
|
||||||
Teamfight Tactics,Silver,Virtus.pro,k1an,Russia,Player
|
|
||||||
Teamfight Tactics,Silver,Virtus.pro,NCC1,Russia,Player
|
|
||||||
Teamfight Tactics,Bronze,T1,Binteum,South Korea,Player
|
|
||||||
Teamfight Tactics,Bronze,T1,sCsC,South Korea,Player
|
|
||||||
Teamfight Tactics,Bronze,T1,dunizuni,South Korea,Player
|
|
||||||
Teamfight Tactics,Bronze,T1,CrazyMoving,South Korea,Player
|
|
||||||
Teamfight Tactics,Bronze,AEGIS,Opale,France,Player
|
|
||||||
Teamfight Tactics,Bronze,AEGIS,Pas de Bol,France,Player
|
|
||||||
Teamfight Tactics,Bronze,AEGIS,Lyyyress,France,Player
|
|
||||||
Teamfight Tactics,Bronze,AEGIS,Gobosteur,France,Player
|
|
||||||
Tekken 8,Gold,DN Freecs,ULSAN,South Korea,Player
|
|
||||||
Tekken 8,Silver,DRX,LOWHIGH,South Korea,Player
|
|
||||||
Tekken 8,Bronze,DN Freecs,CBM,South Korea,Player
|
|
||||||
|
@@ -1,25 +0,0 @@
|
|||||||
Rank,Organization,Total_Points,Prize_Money_USD,Tournament_Wins,Top_8_Finishes,Region,Club_Partner_Status,Eligible_to_Win,Games_Won
|
|
||||||
1,Team Falcons,3850,7000000,2,5,Middle East,Yes,Yes,"Overwatch 2, PUBG: Battlegrounds"
|
|
||||||
2,Team Liquid,2400,4000000,2,4,Europe,Yes,Yes,"Chess, EA Sports FC 25"
|
|
||||||
3,Team Vitality,1950,3000000,1,4,Europe,Yes,Yes,Mobile Legends: Bang Bang - Women
|
|
||||||
4,Twisted Minds,1800,2250000,2,3,Middle East,Yes,Yes,"Call of Duty: Warzone, PUBG: Battlegrounds"
|
|
||||||
5,Virtus.pro,1600,2250000,0,5,Europe,Yes,No,None
|
|
||||||
6,Team Spirit,1550,2250000,1,3,Europe,Yes,Yes,Dota 2
|
|
||||||
7,AG.AL,1500,1500000,2,3,Asia,Yes,Yes,"CrossFire, Honor of Kings"
|
|
||||||
8,Gen.G,1400,1000000,1,3,Asia,Yes,Yes,League of Legends
|
|
||||||
9,Weibo Gaming,1250,850000,1,2,Asia,Yes,Yes,Teamfight Tactics
|
|
||||||
10,KuaiShou Gaming,1100,700000,1,2,Asia,No,Yes,Street Fighter 6
|
|
||||||
11,DRX,950,600000,0,3,Asia,No,No,None
|
|
||||||
12,Aurora Gaming,900,525000,0,3,Europe,No,No,None
|
|
||||||
13,T1,850,425000,0,3,Asia,Yes,No,None
|
|
||||||
14,Team Heretics,800,425000,1,1,Europe,No,Yes,Valorant
|
|
||||||
15,DetonatioN FocusMe,750,300000,1,1,Asia,No,Yes,Fatal Fury: City of the Wolves
|
|
||||||
16,DN Freecs,700,300000,1,1,Asia,No,Yes,Tekken 8
|
|
||||||
17,Karmine Corp,650,300000,1,1,Europe,Yes,Yes,Rocket League
|
|
||||||
18,Team Secret,600,300000,1,1,Asia,Yes,Yes,Rainbow Six Siege X
|
|
||||||
19,G2 Esports,550,225000,0,2,Europe,Yes,No,None
|
|
||||||
20,Al Qadsiah,500,150000,0,2,Middle East,No,No,None
|
|
||||||
21,Gaimin Gladiators,450,150000,0,2,North America,Yes,No,None
|
|
||||||
22,Geekay Esports,400,150000,0,2,Middle East,No,No,None
|
|
||||||
23,ROC Esports,350,150000,0,2,Asia,No,No,None
|
|
||||||
24,Rex Regum Qeon,300,150000,0,2,Asia,Yes,No,None
|
|
||||||
|
@@ -1,41 +0,0 @@
|
|||||||
Organization,Region,Country,Club_Partner_Status,Top_8_2024,Games_Competing,Founded,HQ_Location,CEO,Social_Media_Followers_M
|
|
||||||
Fnatic,Europe,UK,Current,No,"Valorant, League of Legends",2004,"London, UK",Sam Mathews,2.5
|
|
||||||
G2 Esports,Europe,Germany,Current,No,"Rainbow Six Siege X, Counter-Strike 2",2013,"Berlin, Germany",Alban Dechelotte,3.2
|
|
||||||
Gentle Mates,Europe,France,Current,No,Call of Duty: Warzone,2023,"Paris, France",Squeezie,1.8
|
|
||||||
HEROIC,Europe,Norway,Current,No,Counter-Strike 2,2016,"Oslo, Norway",Joachim Haraldsen,0.9
|
|
||||||
Karmine Corp,Europe,France,Current,No,"Rocket League, League of Legends",2020,"Paris, France",Kameto,2.1
|
|
||||||
MOUZ,Europe,Germany,Current,No,Counter-Strike 2,2002,"Hamburg, Germany",Stefan Wendt,1.5
|
|
||||||
Movistar KOI,Europe,Spain,Current,No,Call of Duty: Black Ops 6,2023,"Madrid, Spain",Ibai Llanos,1.2
|
|
||||||
Natus Vincere,Europe,Ukraine,Current,Yes,"Counter-Strike 2, Dota 2",2009,"Kyiv, Ukraine",Yevhen Zolotarov,2.8
|
|
||||||
Ninjas in Pyjamas,Europe,Sweden,Current,Yes,"Counter-Strike 2, Apex Legends",2000,"Stockholm, Sweden",Hicham Chahine,3.0
|
|
||||||
Team BDS,Europe,Switzerland,Current,Yes,"Rocket League, League of Legends",2019,"Geneva, Switzerland",Patrice Spathis,0.7
|
|
||||||
Team Liquid,Europe,Netherlands,Current,Yes,"Dota 2, Chess, EA Sports FC 25, Counter-Strike 2",2000,"Utrecht, Netherlands",Steve Arhancet,4.5
|
|
||||||
Team Secret,Europe,Philippines,Current,No,"Rainbow Six Siege X, Dota 2",2014,"Manila, Philippines",John Yao,1.9
|
|
||||||
Team Spirit,Europe,Russia,Current,Yes,"Dota 2, Counter-Strike 2",2015,"Moscow, Russia",Nikita Cheshir Chukalin,2.2
|
|
||||||
Team Vitality,Europe,France,Current,Yes,"EA Sports FC 25, Counter-Strike 2, Mobile Legends",2013,"Paris, France",Nicolas Maurer,3.8
|
|
||||||
Virtus.pro,Europe,Russia,Current,No,"Counter-Strike 2, Dota 2, Rennsport",2003,"Moscow, Russia",Sergey Glamazda,2.0
|
|
||||||
100 Thieves,North America,USA,Current,No,"Call of Duty: Black Ops 6, Valorant",2017,"Los Angeles, USA",Matthew Nadeshot Haag,3.5
|
|
||||||
Cloud9,North America,USA,Current,No,"Counter-Strike 2, Valorant",2013,"Los Angeles, USA",Jack Etienne,2.7
|
|
||||||
FaZe Clan,North America,USA,Current,Yes,"Call of Duty: Black Ops 6, Counter-Strike 2",2010,"Los Angeles, USA",Lee Trink,5.2
|
|
||||||
Gaimin Gladiators,North America,USA,Current,Yes,"Dota 2, Mobile Legends",2021,"Toronto, Canada",Joseph Turner,0.6
|
|
||||||
Sentinels,North America,USA,Current,No,Valorant,2018,"Los Angeles, USA",Rob Moore,2.3
|
|
||||||
All Gamers,Asia,China,Current,No,"CrossFire, Honor of Kings, League of Legends",1999,"Chengdu, China",Jiang Lei,1.4
|
|
||||||
Bilibili Gaming,Asia,China,Current,No,"League of Legends, Valorant",2017,"Hangzhou, China",Chen Rui,1.1
|
|
||||||
Edward Gaming,Asia,China,Current,No,"League of Legends, Valorant",2013,"Guangzhou, China",Zhu Yilong,2.0
|
|
||||||
EVOS Esports,Asia,Indonesia,Current,No,"Free Fire, Mobile Legends",2016,"Jakarta, Indonesia",Ivan Yeo,1.6
|
|
||||||
Gen.G Esports,Asia,South Korea,Current,No,"League of Legends, Valorant, PUBG",2017,"Seoul, South Korea",Arnold Hur,2.4
|
|
||||||
JD Gaming,Asia,China,Current,No,League of Legends,2017,"Beijing, China",Ye Mingming,1.3
|
|
||||||
ONIC Esports,Asia,Indonesia,Current,No,Mobile Legends,2018,"Jakarta, Indonesia",Justin Anselmus,1.0
|
|
||||||
REJECT,Asia,Japan,Current,No,"Street Fighter 6, Tekken 8",2020,"Tokyo, Japan",Takuya Aoki,0.5
|
|
||||||
Rex Regum Qeon,Asia,Indonesia,Current,No,"Free Fire, Mobile Legends",2013,"Jakarta, Indonesia",Adrian Pauline,1.2
|
|
||||||
S8UL Esports,Asia,India,Current,No,Battlegrounds Mobile India,2018,"Mumbai, India",Lokesh Jain,0.8
|
|
||||||
T1,Asia,South Korea,Current,Yes,"League of Legends, Valorant, Teamfight Tactics",2004,"Seoul, South Korea",Joe Marsh,5.0
|
|
||||||
Weibo Gaming,Asia,China,Current,No,"League of Legends, Teamfight Tactics, PUBG Mobile",2011,"Shanghai, China",Wang Sicong,1.7
|
|
||||||
Wolves Esports,Asia,China,Current,No,"Honor of Kings, PUBG Mobile",2019,"Chongqing, China",Guo Bin,0.9
|
|
||||||
ZETA DIVISION,Asia,Japan,Current,No,Valorant,2017,"Tokyo, Japan",Shinji Okubo,1.5
|
|
||||||
FURIA,South America,Brazil,Current,No,"Counter-Strike 2, Rainbow Six Siege X",2017,"São Paulo, Brazil",André Akkari,2.1
|
|
||||||
Leviatán,South America,Chile,Current,No,Valorant,2020,"Santiago, Chile",Pablo Maldonado,0.8
|
|
||||||
LOUD,South America,Brazil,Current,No,"Valorant, League of Legends",2019,"São Paulo, Brazil",Bruno Playhard,1.8
|
|
||||||
POWR Esports,Middle East,Saudi Arabia,Current,No,Counter-Strike 2,2021,"Riyadh, Saudi Arabia",Faisal Bin Homran,0.3
|
|
||||||
Team Falcons,Middle East,Saudi Arabia,Current,Yes,"Dota 2, Counter-Strike 2, Overwatch 2, PUBG",2017,"Riyadh, Saudi Arabia",Mosaad Aldossary,4.0
|
|
||||||
Twisted Minds,Middle East,Saudi Arabia,Current,Yes,"Call of Duty: Warzone, PUBG, Apex Legends",2020,"Riyadh, Saudi Arabia",Ahmad Al-Megren,1.1
|
|
||||||
|
@@ -1,273 +0,0 @@
|
|||||||
Player_ID,Player_Name,Country,Region,Team,Game,Role,Age,Experience_Years,Previous_Team,Tournament_Place,Prize_Earned_USD,Social_Media_Followers_K
|
|
||||||
EWC2025_001,Kasssa,Brazil,South America,VK Gaming,Apex Legends,IGL,24,5,Furia,1,0,45
|
|
||||||
EWC2025_002,QQ,China,Asia,VK Gaming,Apex Legends,Fragger,22,4,None,1,0,120
|
|
||||||
EWC2025_003,LqDuD,China,Asia,VK Gaming,Apex Legends,Support,21,3,None,1,0,80
|
|
||||||
EWC2025_004,Vaxlon,Philippines,Asia,ROC Esports,Apex Legends,IGL,25,6,Team Liquid,2,0,35
|
|
||||||
EWC2025_005,Deeds,Australia,Oceania,ROC Esports,Apex Legends,Fragger,23,4,None,2,0,28
|
|
||||||
EWC2025_006,Sauceror,USA,North America,ROC Esports,Apex Legends,Support,26,7,TSM,2,0,55
|
|
||||||
EWC2025_007,Vein,USA,North America,Ninjas in Pyjamas,Apex Legends,IGL,24,5,Sentinels,3,0,42
|
|
||||||
EWC2025_008,Kurev,Russia,Europe,Ninjas in Pyjamas,Apex Legends,Fragger,22,3,None,3,0,18
|
|
||||||
EWC2025_009,McLovin,USA,North America,Ninjas in Pyjamas,Apex Legends,Support,23,4,Cloud9,3,0,38
|
|
||||||
EWC2025_010,Dashy,USA,North America,OpTic Gaming,Call of Duty Black Ops 6,AR,26,8,OpTic Texas,1,0,850
|
|
||||||
EWC2025_011,Huke,USA,North America,OpTic Gaming,Call of Duty Black Ops 6,SMG,25,7,Dallas Empire,1,0,420
|
|
||||||
EWC2025_012,Mercules,USA,North America,OpTic Gaming,Call of Duty Black Ops 6,SMG,21,3,None,1,0,95
|
|
||||||
EWC2025_013,Shotzzy,USA,North America,OpTic Gaming,Call of Duty Black Ops 6,SMG,23,5,Dallas Empire,1,0,680
|
|
||||||
EWC2025_014,04,Canada,North America,Vancouver Surge,Call of Duty Black Ops 6,AR,22,4,None,2,0,32
|
|
||||||
EWC2025_015,Abuzah,Morocco,Europe,Vancouver Surge,Call of Duty Black Ops 6,SMG,24,5,Toronto Ultra,2,0,45
|
|
||||||
EWC2025_016,Neptune,USA,North America,Vancouver Surge,Call of Duty Black Ops 6,SMG,23,4,None,2,0,38
|
|
||||||
EWC2025_017,Nastie,UK,Europe,Vancouver Surge,Call of Duty Black Ops 6,AR,24,5,London Royal Ravens,2,0,52
|
|
||||||
EWC2025_018,Abe,Spain,Europe,Movistar KOI,Call of Duty Black Ops 6,AR,22,3,None,3,0,25
|
|
||||||
EWC2025_019,CleanX,Denmark,Europe,Movistar KOI,Call of Duty Black Ops 6,SMG,24,5,Toronto Ultra,3,0,48
|
|
||||||
EWC2025_020,Insight,UK,Europe,Movistar KOI,Call of Duty Black Ops 6,AR,25,6,Toronto Ultra,3,0,55
|
|
||||||
EWC2025_021,JoeDeceives,USA,North America,Movistar KOI,Call of Duty Black Ops 6,SMG,21,2,None,3,0,18
|
|
||||||
EWC2025_022,Magnus Carlsen,Norway,Europe,Team Liquid,Chess,Grandmaster,34,20,None,1,0,2500
|
|
||||||
EWC2025_023,Alireza Firouzja,France,Europe,Team Falcons,Chess,Grandmaster,21,8,None,2,0,450
|
|
||||||
EWC2025_024,Hikaru Nakamura,USA,North America,Team Falcons,Chess,Grandmaster,37,22,None,3,0,3200
|
|
||||||
EWC2025_025,Techno4K,Mongolia,Asia,The MongolZ,Counter-Strike 2,AWPer,22,5,None,1,0,180
|
|
||||||
EWC2025_026,910,Mongolia,Asia,The MongolZ,Counter-Strike 2,Entry,21,4,None,1,0,120
|
|
||||||
EWC2025_027,mzinho,Mongolia,Asia,The MongolZ,Counter-Strike 2,IGL,23,6,None,1,0,150
|
|
||||||
EWC2025_028,bLitz,Mongolia,Asia,The MongolZ,Counter-Strike 2,Support,24,6,None,1,0,140
|
|
||||||
EWC2025_029,Senzu,Mongolia,Asia,The MongolZ,Counter-Strike 2,Rifler,20,3,None,1,0,95
|
|
||||||
EWC2025_030,MAJ3R,Turkey,Europe,Aurora Gaming,Counter-Strike 2,IGL,29,10,Eternal Fire,2,0,220
|
|
||||||
EWC2025_031,XANTARES,Turkey,Europe,Aurora Gaming,Counter-Strike 2,Entry,29,11,Eternal Fire,2,0,380
|
|
||||||
EWC2025_032,woxic,Turkey,Europe,Aurora Gaming,Counter-Strike 2,AWPer,26,8,Eternal Fire,2,0,290
|
|
||||||
EWC2025_033,Wicadia,Turkey,Europe,Aurora Gaming,Counter-Strike 2,Rifler,19,2,None,2,0,85
|
|
||||||
EWC2025_034,jottAAA,Turkey,Europe,Aurora Gaming,Counter-Strike 2,Support,22,4,None,2,0,65
|
|
||||||
EWC2025_035,NiKo,Bosnia,Europe,Team Falcons,Counter-Strike 2,Entry,28,11,G2 Esports,3,0,950
|
|
||||||
EWC2025_036,TeSeS,Denmark,Europe,Team Falcons,Counter-Strike 2,Rifler,26,7,Heroic,3,0,180
|
|
||||||
EWC2025_037,m0NESY,Russia,Europe,Team Falcons,Counter-Strike 2,AWPer,20,4,G2 Esports,3,0,720
|
|
||||||
EWC2025_038,kyxsan,North Macedonia,Europe,Team Falcons,Counter-Strike 2,IGL,24,5,Astralis,3,0,110
|
|
||||||
EWC2025_039,kyousuke,Russia,Europe,Team Falcons,Counter-Strike 2,Support,19,2,None,3,0,75
|
|
||||||
EWC2025_040,Yatoro,Ukraine,Europe,Team Spirit,Dota 2,Carry,22,6,None,1,0,320
|
|
||||||
EWC2025_041,Larl,Russia,Europe,Team Spirit,Dota 2,Mid,23,5,None,1,0,180
|
|
||||||
EWC2025_042,Collapse,Russia,Europe,Team Spirit,Dota 2,Offlane,23,6,None,1,0,210
|
|
||||||
EWC2025_043,Rue,Russia,Europe,Team Spirit,Dota 2,Support,21,4,None,1,0,95
|
|
||||||
EWC2025_044,Miposhka,Russia,Europe,Team Spirit,Dota 2,Support,26,8,None,1,0,150
|
|
||||||
EWC2025_045,skiter,Slovakia,Europe,Team Falcons,Dota 2,Carry,26,8,Tundra Esports,2,0,140
|
|
||||||
EWC2025_046,Malr1ne,Ukraine,Europe,Team Falcons,Dota 2,Mid,22,4,None,2,0,85
|
|
||||||
EWC2025_047,ATF,Jordan,Middle East,Team Falcons,Dota 2,Offlane,21,5,Nigma Galaxy,2,0,180
|
|
||||||
EWC2025_048,Cr1t-,Denmark,Europe,Team Falcons,Dota 2,Support,28,10,Evil Geniuses,2,0,220
|
|
||||||
EWC2025_049,Sneyking,USA,North America,Team Falcons,Dota 2,Support,29,11,Tundra Esports,2,0,130
|
|
||||||
EWC2025_050,Satanic,Russia,Europe,Parivision,Dota 2,Carry,20,3,None,3,0,65
|
|
||||||
EWC2025_051,No[o]ne-,Ukraine,Europe,Parivision,Dota 2,Mid,30,12,Virtus.pro,3,0,190
|
|
||||||
EWC2025_052,DM,Ukraine,Europe,Parivision,Dota 2,Offlane,26,7,Natus Vincere,3,0,110
|
|
||||||
EWC2025_053,9Class,Russia,Europe,Parivision,Dota 2,Support,22,4,None,3,0,45
|
|
||||||
EWC2025_054,Dukalis,Russia,Europe,Parivision,Dota 2,Support,24,6,None,3,0,55
|
|
||||||
EWC2025_055,Kiin,South Korea,Asia,Gen.G,League of Legends,Top,26,8,Afreeca Freecs,1,0,280
|
|
||||||
EWC2025_056,Canyon,South Korea,Asia,Gen.G,League of Legends,Jungle,24,6,DAMWON KIA,1,0,350
|
|
||||||
EWC2025_057,Chovy,South Korea,Asia,Gen.G,League of Legends,Mid,23,7,Griffin,1,0,420
|
|
||||||
EWC2025_058,Ruler,South Korea,Asia,Gen.G,League of Legends,ADC,26,9,JD Gaming,1,0,380
|
|
||||||
EWC2025_059,Duro,South Korea,Asia,Gen.G,League of Legends,Support,22,3,None,1,0,95
|
|
||||||
EWC2025_060,Flandre,China,Asia,AG.AL,League of Legends,Top,27,9,EDG,2,0,220
|
|
||||||
EWC2025_061,Tarzan,South Korea,Asia,AG.AL,League of Legends,Jungle,25,7,LNG,2,0,310
|
|
||||||
EWC2025_062,Shanks,China,Asia,AG.AL,League of Legends,Mid,23,5,None,2,0,140
|
|
||||||
EWC2025_063,Hope,China,Asia,AG.AL,League of Legends,ADC,24,6,JD Gaming,2,0,180
|
|
||||||
EWC2025_064,Kael,South Korea,Asia,AG.AL,League of Legends,Support,24,5,None,2,0,85
|
|
||||||
EWC2025_065,Doran,South Korea,Asia,T1,League of Legends,Top,24,6,Gen.G,3,0,250
|
|
||||||
EWC2025_066,Oner,South Korea,Asia,T1,League of Legends,Jungle,22,4,None,3,0,320
|
|
||||||
EWC2025_067,Faker,South Korea,Asia,T1,League of Legends,Mid,29,12,None,3,0,5000
|
|
||||||
EWC2025_068,Gumayusi,South Korea,Asia,T1,League of Legends,ADC,24,5,None,3,0,450
|
|
||||||
EWC2025_069,Keria,South Korea,Asia,T1,League of Legends,Support,23,5,None,3,0,380
|
|
||||||
EWC2025_070,Boo,Lithuania,Europe,Team Heretics,Valorant,IGL,27,5,G2 Esports,1,0,180
|
|
||||||
EWC2025_071,benjyfishy,UK,Europe,Team Heretics,Valorant,Duelist,20,3,None,1,0,850
|
|
||||||
EWC2025_072,MiniBoo,Lithuania,Europe,Team Heretics,Valorant,Duelist,19,2,None,1,0,120
|
|
||||||
EWC2025_073,RieNs,Turkey,Europe,Team Heretics,Valorant,Controller,21,3,None,1,0,95
|
|
||||||
EWC2025_074,Wo0t,Finland,Europe,Team Heretics,Valorant,Initiator,20,2,None,1,0,110
|
|
||||||
EWC2025_075,Boaster,UK,Europe,Fnatic,Valorant,IGL,30,5,None,2,0,520
|
|
||||||
EWC2025_076,Alfajer,Saudi Arabia,Middle East,Fnatic,Valorant,Sentinel,19,3,None,2,0,280
|
|
||||||
EWC2025_077,Chronicle,Russia,Europe,Fnatic,Valorant,Flex,22,5,Gambit Esports,2,0,310
|
|
||||||
EWC2025_078,kaajak,Poland,Europe,Fnatic,Valorant,Duelist,20,2,None,2,0,85
|
|
||||||
EWC2025_079,crashies,USA,North America,Fnatic,Valorant,Initiator,26,5,OpTic Gaming,2,0,190
|
|
||||||
EWC2025_080,t3xture,South Korea,Asia,Gen.G,Valorant,Duelist,23,4,None,3,0,120
|
|
||||||
EWC2025_081,Karon,South Korea,Asia,Gen.G,Valorant,Sentinel,21,3,None,3,0,85
|
|
||||||
EWC2025_082,Munchkin,South Korea,Asia,Gen.G,Valorant,IGL,26,5,T1,3,0,150
|
|
||||||
EWC2025_083,Ash,South Korea,Asia,Gen.G,Valorant,Controller,22,4,None,3,0,75
|
|
||||||
EWC2025_084,Foxy9,South Korea,Asia,Gen.G,Valorant,Initiator,21,3,None,3,0,68
|
|
||||||
EWC2025_085,Proper,South Korea,Asia,Team Falcons,Overwatch 2,DPS,22,6,San Francisco Shock,1,0,180
|
|
||||||
EWC2025_086,MER1T,South Korea,Asia,Team Falcons,Overwatch 2,DPS,23,5,Houston Outlaws,1,0,95
|
|
||||||
EWC2025_087,SOMEONE,South Korea,Asia,Team Falcons,Overwatch 2,Tank,21,4,Florida Mayhem,1,0,78
|
|
||||||
EWC2025_088,Hanbin,South Korea,Asia,Team Falcons,Overwatch 2,Tank,22,5,Dallas Fuel,1,0,110
|
|
||||||
EWC2025_089,ChiYo,South Korea,Asia,Team Falcons,Overwatch 2,Support,23,5,Dallas Fuel,1,0,85
|
|
||||||
EWC2025_090,Fielder,South Korea,Asia,Team Falcons,Overwatch 2,Support,24,6,Dallas Fuel,1,0,92
|
|
||||||
EWC2025_091,LBBD7,Saudi Arabia,Middle East,Al Qadsiah,Overwatch 2,DPS,22,4,None,2,0,35
|
|
||||||
EWC2025_092,CheckMate,Saudi Arabia,Middle East,Al Qadsiah,Overwatch 2,Tank,23,5,None,2,0,28
|
|
||||||
EWC2025_093,ZIYAD,Saudi Arabia,Middle East,Al Qadsiah,Overwatch 2,DPS,21,3,None,2,0,22
|
|
||||||
EWC2025_094,Landon,Saudi Arabia,Middle East,Al Qadsiah,Overwatch 2,Support,24,5,None,2,0,18
|
|
||||||
EWC2025_095,Kellex,Saudi Arabia,Middle East,Al Qadsiah,Overwatch 2,Support,22,4,None,2,0,15
|
|
||||||
EWC2025_096,Quartz,Saudi Arabia,Middle East,Twisted Minds,Overwatch 2,DPS,21,3,None,3,0,25
|
|
||||||
EWC2025_097,Youbi,Saudi Arabia,Middle East,Twisted Minds,Overwatch 2,Tank,22,4,None,3,0,20
|
|
||||||
EWC2025_098,KSAA,Saudi Arabia,Middle East,Twisted Minds,Overwatch 2,Support,24,5,None,3,0,30
|
|
||||||
EWC2025_099,FunnyAstro,UK,Europe,Twisted Minds,Overwatch 2,Support,26,7,Philadelphia Fusion,3,0,120
|
|
||||||
EWC2025_100,Simple,Saudi Arabia,Middle East,Twisted Minds,Overwatch 2,DPS,20,2,None,3,0,12
|
|
||||||
EWC2025_101,Serral,Finland,Europe,Basilisk,StarCraft II,Zerg,27,12,ENCE,1,0,280
|
|
||||||
EWC2025_102,Classic,South Korea,Asia,Virtus.pro,StarCraft II,Protoss,32,14,None,2,0,150
|
|
||||||
EWC2025_103,Cure,South Korea,Asia,Team Liquid,StarCraft II,Terran,29,11,None,3,0,95
|
|
||||||
EWC2025_104,Xiaohai,China,Asia,KuaiShou Gaming,Street Fighter 6,Player,35,18,Qanba,1,0,320
|
|
||||||
EWC2025_105,Blaz,South Korea,Asia,2Game Esports,Street Fighter 6,Player,25,8,None,2,0,85
|
|
||||||
EWC2025_106,Leshar,South Korea,Asia,DRX,Street Fighter 6,Player,23,6,None,3,0,55
|
|
||||||
EWC2025_107,ULSAN,South Korea,Asia,DN Freecs,Tekken 8,Player,26,10,None,1,0,180
|
|
||||||
EWC2025_108,LOWHIGH,South Korea,Asia,DRX,Tekken 8,Player,28,12,None,2,0,150
|
|
||||||
EWC2025_109,CBM,South Korea,Asia,DN Freecs,Tekken 8,Player,24,8,None,3,0,95
|
|
||||||
EWC2025_110,ManuBachoore,Netherlands,Europe,Team Liquid,EA Sports FC 25,Player,21,5,None,1,0,180
|
|
||||||
EWC2025_111,Brice,France,Europe,Team Vitality,EA Sports FC 25,Player,22,4,None,2,0,95
|
|
||||||
EWC2025_112,Levi de Weerd,Netherlands,Europe,Team Liquid,EA Sports FC 25,Player,20,3,None,3,0,65
|
|
||||||
EWC2025_113,GO1,Japan,Asia,DetonatioN FocusMe,Fatal Fury City of the Wolves,Player,30,12,Cyclops Osaka,1,0,220
|
|
||||||
EWC2025_114,Xiaohai,China,Asia,KuaiShou Gaming,Fatal Fury City of the Wolves,Player,35,18,Qanba,2,0,320
|
|
||||||
EWC2025_115,DarkAngel,South Korea,Asia,Natus Vincere,Fatal Fury City of the Wolves,Player,24,6,None,3,0,45
|
|
||||||
EWC2025_116,Vatira,France,Europe,Karmine Corp,Rocket League,Player,19,5,Moist Esports,1,0,280
|
|
||||||
EWC2025_117,Atow,France,Europe,Karmine Corp,Rocket League,Player,18,4,None,1,0,150
|
|
||||||
EWC2025_118,dralii,France,Europe,Karmine Corp,Rocket League,Player,20,4,None,1,0,120
|
|
||||||
EWC2025_119,Archie,UK,Europe,Geekay Esports,Rocket League,Player,19,4,None,2,0,95
|
|
||||||
EWC2025_120,Joyo,USA,North America,Geekay Esports,Rocket League,Player,20,5,Moist Esports,2,0,180
|
|
||||||
EWC2025_121,oaly,Netherlands,Europe,Geekay Esports,Rocket League,Player,21,5,None,2,0,85
|
|
||||||
EWC2025_122,Trk511,Saudi Arabia,Middle East,Team Falcons,Rocket League,Player,20,4,None,3,0,55
|
|
||||||
EWC2025_123,Rw9,Saudi Arabia,Middle East,Team Falcons,Rocket League,Player,19,3,None,3,0,42
|
|
||||||
EWC2025_124,Kiileerrz,Saudi Arabia,Middle East,Team Falcons,Rocket League,Player,21,4,None,3,0,38
|
|
||||||
EWC2025_125,zSmit,USA,North America,Twisted Minds,Call of Duty Warzone,Player,24,5,None,1,0,120
|
|
||||||
EWC2025_126,Almond,USA,North America,Twisted Minds,Call of Duty Warzone,Player,23,4,None,1,0,95
|
|
||||||
EWC2025_127,Aydan,USA,North America,Twisted Minds,Call of Duty Warzone,Player,25,6,New York Subliners,1,0,850
|
|
||||||
EWC2025_128,Enkeo,France,Europe,Gentle Mates,Call of Duty Warzone,Player,22,3,None,2,0,35
|
|
||||||
EWC2025_129,Gromalok,France,Europe,Gentle Mates,Call of Duty Warzone,Player,24,4,None,2,0,28
|
|
||||||
EWC2025_130,HalloW,France,Europe,Gentle Mates,Call of Duty Warzone,Player,23,4,None,2,0,22
|
|
||||||
EWC2025_131,Dongy,South Korea,Asia,Virtus.pro,Call of Duty Warzone,Player,22,3,None,3,0,18
|
|
||||||
EWC2025_132,Newbz,USA,North America,Virtus.pro,Call of Duty Warzone,Player,24,5,None,3,0,65
|
|
||||||
EWC2025_133,Sage,USA,North America,Virtus.pro,Call of Duty Warzone,Player,23,4,None,3,0,45
|
|
||||||
EWC2025_134,ZY,China,Asia,AG.AL,CrossFire,Player,24,6,None,1,0,85
|
|
||||||
EWC2025_135,Jwei,China,Asia,AG.AL,CrossFire,Player,22,4,None,1,0,65
|
|
||||||
EWC2025_136,Doo,China,Asia,AG.AL,CrossFire,Player,21,3,None,1,0,55
|
|
||||||
EWC2025_137,1222,China,Asia,AG.AL,CrossFire,Player,23,5,None,1,0,48
|
|
||||||
EWC2025_138,ZQ,China,Asia,AG.AL,CrossFire,Player,20,3,None,1,0,35
|
|
||||||
EWC2025_139,Xxiao,China,Asia,BaiSha Gaming,CrossFire,Player,25,7,None,2,0,72
|
|
||||||
EWC2025_140,N9,China,Asia,BaiSha Gaming,CrossFire,Player,24,6,None,2,0,68
|
|
||||||
EWC2025_141,577,China,Asia,BaiSha Gaming,CrossFire,Player,22,4,None,2,0,42
|
|
||||||
EWC2025_142,Lye,China,Asia,BaiSha Gaming,CrossFire,Player,23,5,None,2,0,38
|
|
||||||
EWC2025_143,YDSS,China,Asia,BaiSha Gaming,CrossFire,Player,21,3,None,2,0,32
|
|
||||||
EWC2025_144,ZAY,China,Asia,Evolution Power,CrossFire,Player,24,5,None,3,0,28
|
|
||||||
EWC2025_145,mino,China,Asia,Evolution Power,CrossFire,Player,22,4,None,3,0,25
|
|
||||||
EWC2025_146,YZK,China,Asia,Evolution Power,CrossFire,Player,23,5,None,3,0,22
|
|
||||||
EWC2025_147,yh,China,Asia,Evolution Power,CrossFire,Player,21,3,None,3,0,18
|
|
||||||
EWC2025_148,xqq,China,Asia,Evolution Power,CrossFire,Player,20,3,None,3,0,15
|
|
||||||
EWC2025_149,Rasyah,Indonesia,Asia,EVOS Esports,Free Fire,Player,22,4,None,1,0,120
|
|
||||||
EWC2025_150,AimGOD,Indonesia,Asia,EVOS Esports,Free Fire,Player,21,3,None,1,0,95
|
|
||||||
EWC2025_151,Reyyy,Indonesia,Asia,EVOS Esports,Free Fire,Player,20,3,None,1,0,85
|
|
||||||
EWC2025_152,Koceel,Indonesia,Asia,EVOS Esports,Free Fire,Player,23,5,None,1,0,78
|
|
||||||
EWC2025_153,Dutzz,Indonesia,Asia,Rex Regum Qeon,Free Fire,Player,22,4,None,2,0,65
|
|
||||||
EWC2025_154,Abay,Indonesia,Asia,Rex Regum Qeon,Free Fire,Player,21,3,None,2,0,58
|
|
||||||
EWC2025_155,18Deer,Indonesia,Asia,Rex Regum Qeon,Free Fire,Player,20,3,None,2,0,52
|
|
||||||
EWC2025_156,Maal,Indonesia,Asia,Rex Regum Qeon,Free Fire,Player,24,5,None,2,0,48
|
|
||||||
EWC2025_157,JUMP,Thailand,Asia,Team Vitality,Free Fire,Player,22,4,None,3,0,42
|
|
||||||
EWC2025_158,COUGAR,Thailand,Asia,Team Vitality,Free Fire,Player,21,3,None,3,0,38
|
|
||||||
EWC2025_159,ZEN1S,Thailand,Asia,Team Vitality,Free Fire,Player,23,5,None,3,0,35
|
|
||||||
EWC2025_160,DON,Thailand,Asia,Team Vitality,Free Fire,Player,20,3,None,3,0,28
|
|
||||||
EWC2025_161,Ran,China,Asia,AG.AL,Honor of Kings,Player,22,4,None,1,0,95
|
|
||||||
EWC2025_162,Zoe,China,Asia,AG.AL,Honor of Kings,Player,21,3,None,1,0,85
|
|
||||||
EWC2025_163,Sheng,China,Asia,AG.AL,Honor of Kings,Player,20,3,None,1,0,78
|
|
||||||
EWC2025_164,YiNuo,China,Asia,AG.AL,Honor of Kings,Player,23,5,None,1,0,72
|
|
||||||
EWC2025_165,Shuai,China,Asia,AG.AL,Honor of Kings,Player,22,4,None,1,0,65
|
|
||||||
EWC2025_166,Qing,China,Asia,ThunderTalk Global,Honor of Kings,Player,24,5,None,2,0,58
|
|
||||||
EWC2025_167,Sunrise,China,Asia,ThunderTalk Global,Honor of Kings,Player,21,3,None,2,0,52
|
|
||||||
EWC2025_168,Crane,China,Asia,ThunderTalk Global,Honor of Kings,Player,22,4,None,2,0,48
|
|
||||||
EWC2025_169,Snowy,China,Asia,ThunderTalk Global,Honor of Kings,Player,20,3,None,2,0,42
|
|
||||||
EWC2025_170,Joy,China,Asia,ThunderTalk Global,Honor of Kings,Player,23,5,None,2,0,38
|
|
||||||
EWC2025_171,Xuan,China,Asia,Nova Esports,Honor of Kings,Player,22,4,None,3,0,35
|
|
||||||
EWC2025_172,Cy,China,Asia,Nova Esports,Honor of Kings,Player,21,3,None,3,0,32
|
|
||||||
EWC2025_173,Wendy,China,Asia,Nova Esports,Honor of Kings,Player,20,3,None,3,0,28
|
|
||||||
EWC2025_174,Muci,China,Asia,Nova Esports,Honor of Kings,Player,23,5,None,3,0,25
|
|
||||||
EWC2025_175,Weipit,China,Asia,Nova Esports,Honor of Kings,Player,22,4,None,3,0,22
|
|
||||||
EWC2025_176,Sanford,Philippines,Asia,Team Liquid PH,Mobile Legends Bang Bang Men,Player,22,4,None,1,0,120
|
|
||||||
EWC2025_177,KarlTzy,Philippines,Asia,Team Liquid PH,Mobile Legends Bang Bang Men,Player,23,5,None,1,0,150
|
|
||||||
EWC2025_178,Sanji,Philippines,Asia,Team Liquid PH,Mobile Legends Bang Bang Men,Player,21,3,None,1,0,95
|
|
||||||
EWC2025_179,Oheb,Philippines,Asia,Team Liquid PH,Mobile Legends Bang Bang Men,Player,22,4,None,1,0,85
|
|
||||||
EWC2025_180,Jaypee,Philippines,Asia,Team Liquid PH,Mobile Legends Bang Bang Men,Player,20,3,None,1,0,72
|
|
||||||
EWC2025_181,Kramm,Philippines,Asia,SRG.OG,Mobile Legends Bang Bang Men,Player,22,4,None,2,0,58
|
|
||||||
EWC2025_182,Sekys,Philippines,Asia,SRG.OG,Mobile Legends Bang Bang Men,Player,21,3,None,2,0,52
|
|
||||||
EWC2025_183,Stormie,Philippines,Asia,SRG.OG,Mobile Legends Bang Bang Men,Player,23,5,None,2,0,48
|
|
||||||
EWC2025_184,Innocent,Philippines,Asia,SRG.OG,Mobile Legends Bang Bang Men,Player,22,4,None,2,0,42
|
|
||||||
EWC2025_185,Yums,Philippines,Asia,SRG.OG,Mobile Legends Bang Bang Men,Player,20,3,None,2,0,38
|
|
||||||
EWC2025_186,Kirk,Philippines,Asia,Onic Philippines,Mobile Legends Bang Bang Men,Player,22,4,None,3,0,35
|
|
||||||
EWC2025_187,K1NG KONG,Philippines,Asia,Onic Philippines,Mobile Legends Bang Bang Men,Player,21,3,None,3,0,32
|
|
||||||
EWC2025_188,Super Frince,Philippines,Asia,Onic Philippines,Mobile Legends Bang Bang Men,Player,23,5,None,3,0,28
|
|
||||||
EWC2025_189,Kelra,Philippines,Asia,Onic Philippines,Mobile Legends Bang Bang Men,Player,22,4,None,3,0,25
|
|
||||||
EWC2025_190,Brusko,Philippines,Asia,Onic Philippines,Mobile Legends Bang Bang Men,Player,20,3,None,3,0,22
|
|
||||||
EWC2025_191,Fumi,Philippines,Asia,Team Vitality,Mobile Legends Bang Bang Women,Player,21,3,None,1,0,65
|
|
||||||
EWC2025_192,Vival,Philippines,Asia,Team Vitality,Mobile Legends Bang Bang Women,Player,20,3,None,1,0,58
|
|
||||||
EWC2025_193,Cinny,Philippines,Asia,Team Vitality,Mobile Legends Bang Bang Women,Player,22,4,None,1,0,52
|
|
||||||
EWC2025_194,Chell,Philippines,Asia,Team Vitality,Mobile Legends Bang Bang Women,Player,21,3,None,1,0,48
|
|
||||||
EWC2025_195,Vivian,Philippines,Asia,Team Vitality,Mobile Legends Bang Bang Women,Player,23,5,None,1,0,42
|
|
||||||
EWC2025_196,Aria,Philippines,Asia,Gaimin Gladiators,Mobile Legends Bang Bang Women,Player,22,4,None,2,0,38
|
|
||||||
EWC2025_197,Nicholette,Philippines,Asia,Gaimin Gladiators,Mobile Legends Bang Bang Women,Player,21,3,None,2,0,35
|
|
||||||
EWC2025_198,Sayori,Philippines,Asia,Gaimin Gladiators,Mobile Legends Bang Bang Women,Player,20,3,None,2,0,32
|
|
||||||
EWC2025_199,Panda,Philippines,Asia,Gaimin Gladiators,Mobile Legends Bang Bang Women,Player,23,5,None,2,0,28
|
|
||||||
EWC2025_200,Ashlay,Philippines,Asia,Gaimin Gladiators,Mobile Legends Bang Bang Women,Player,22,4,None,2,0,25
|
|
||||||
EWC2025_201,Hlaing,Myanmar,Asia,Terror Queens,Mobile Legends Bang Bang Women,Player,21,3,None,3,0,22
|
|
||||||
EWC2025_202,Ruli,Myanmar,Asia,Terror Queens,Mobile Legends Bang Bang Women,Player,20,3,None,3,0,18
|
|
||||||
EWC2025_203,LunaLynn,Myanmar,Asia,Terror Queens,Mobile Legends Bang Bang Women,Player,22,4,None,3,0,15
|
|
||||||
EWC2025_204,CKOSHIII,Myanmar,Asia,Terror Queens,Mobile Legends Bang Bang Women,Player,23,5,None,3,0,12
|
|
||||||
EWC2025_205,Kuu,Myanmar,Asia,Terror Queens,Mobile Legends Bang Bang Women,Player,21,3,None,3,0,10
|
|
||||||
EWC2025_206,xmpl,Russia,Europe,Twisted Minds,PUBG Battlegrounds,Player,24,5,None,1,0,85
|
|
||||||
EWC2025_207,BatulinS,Russia,Europe,Twisted Minds,PUBG Battlegrounds,Player,23,4,None,1,0,72
|
|
||||||
EWC2025_208,Perfect1ks,Russia,Europe,Twisted Minds,PUBG Battlegrounds,Player,22,4,None,1,0,65
|
|
||||||
EWC2025_209,Lu,Russia,Europe,Twisted Minds,PUBG Battlegrounds,Player,21,3,None,1,0,58
|
|
||||||
EWC2025_210,Tosi,South Korea,Asia,Gen.G,PUBG Battlegrounds,Player,24,5,None,2,0,52
|
|
||||||
EWC2025_211,F1ame,South Korea,Asia,Gen.G,PUBG Battlegrounds,Player,23,4,None,2,0,48
|
|
||||||
EWC2025_212,Orca,South Korea,Asia,Gen.G,PUBG Battlegrounds,Player,22,4,None,2,0,42
|
|
||||||
EWC2025_213,BeaN,South Korea,Asia,Gen.G,PUBG Battlegrounds,Player,21,3,None,2,0,38
|
|
||||||
EWC2025_214,hwinn,USA,North America,Team Falcons,PUBG Battlegrounds,Player,24,5,None,3,0,35
|
|
||||||
EWC2025_215,TGLTN,Australia,Oceania,Team Falcons,PUBG Battlegrounds,Player,23,4,None,3,0,32
|
|
||||||
EWC2025_216,Shrimzy,USA,North America,Team Falcons,PUBG Battlegrounds,Player,22,4,None,3,0,28
|
|
||||||
EWC2025_217,Kickstart,USA,North America,Team Falcons,PUBG Battlegrounds,Player,21,3,None,3,0,25
|
|
||||||
EWC2025_218,Smile,Myanmar,Asia,Yangon Galacticos,PUBG Mobile,Player,22,4,None,1,0,65
|
|
||||||
EWC2025_219,Marnett,Myanmar,Asia,Yangon Galacticos,PUBG Mobile,Player,21,3,None,1,0,58
|
|
||||||
EWC2025_220,Romeo,Myanmar,Asia,Yangon Galacticos,PUBG Mobile,Player,20,3,None,1,0,52
|
|
||||||
EWC2025_221,SAYCLOUD,Myanmar,Asia,Yangon Galacticos,PUBG Mobile,Player,23,5,None,1,0,48
|
|
||||||
EWC2025_222,Suk,China,Asia,Weibo Gaming,PUBG Mobile,Player,24,5,None,2,0,42
|
|
||||||
EWC2025_223,Order,China,Asia,Weibo Gaming,PUBG Mobile,Player,23,4,None,2,0,38
|
|
||||||
EWC2025_224,33z,China,Asia,Weibo Gaming,PUBG Mobile,Player,22,4,None,2,0,35
|
|
||||||
EWC2025_225,HECC,China,Asia,Weibo Gaming,PUBG Mobile,Player,21,3,None,2,0,32
|
|
||||||
EWC2025_226,Zyol,Mongolia,Asia,Alpha Gaming,PUBG Mobile,Player,22,4,None,3,0,28
|
|
||||||
EWC2025_227,DOK,Mongolia,Asia,Alpha Gaming,PUBG Mobile,Player,21,3,None,3,0,25
|
|
||||||
EWC2025_228,REFUS,Mongolia,Asia,Alpha Gaming,PUBG Mobile,Player,23,5,None,3,0,22
|
|
||||||
EWC2025_229,TOP,Mongolia,Asia,Alpha Gaming,PUBG Mobile,Player,20,3,None,3,0,18
|
|
||||||
EWC2025_230,Savage,Brazil,South America,Team Secret,Rainbow Six Siege X,Player,24,5,None,1,0,95
|
|
||||||
EWC2025_231,jume,Brazil,South America,Team Secret,Rainbow Six Siege X,Player,23,4,None,1,0,85
|
|
||||||
EWC2025_232,Adrian,Brazil,South America,Team Secret,Rainbow Six Siege X,Player,22,4,None,1,0,78
|
|
||||||
EWC2025_233,Mowwwgli,Brazil,South America,Team Secret,Rainbow Six Siege X,Player,21,3,None,1,0,72
|
|
||||||
EWC2025_234,NoaUrz,Brazil,South America,Team Secret,Rainbow Six Siege X,Player,25,6,None,1,0,65
|
|
||||||
EWC2025_235,Alem4o,Brazil,South America,G2 Esports,Rainbow Six Siege X,Player,24,5,None,2,0,58
|
|
||||||
EWC2025_236,Doki,UK,Europe,G2 Esports,Rainbow Six Siege X,Player,23,4,None,2,0,52
|
|
||||||
EWC2025_237,BlaZ,France,Europe,G2 Esports,Rainbow Six Siege X,Player,22,4,None,2,0,48
|
|
||||||
EWC2025_238,Loira,Brazil,South America,G2 Esports,Rainbow Six Siege X,Player,21,3,None,2,0,42
|
|
||||||
EWC2025_239,Stompn,Brazil,South America,G2 Esports,Rainbow Six Siege X,Player,24,5,None,2,0,38
|
|
||||||
EWC2025_240,FelipeX,Brazil,South America,Furia Esports,Rainbow Six Siege X,Player,22,4,None,3,0,35
|
|
||||||
EWC2025_241,HerdsZ,Brazil,South America,Furia Esports,Rainbow Six Siege X,Player,23,5,None,3,0,32
|
|
||||||
EWC2025_242,Jv92,Brazil,South America,Furia Esports,Rainbow Six Siege X,Player,21,3,None,3,0,28
|
|
||||||
EWC2025_243,Kheyze,Brazil,South America,Furia Esports,Rainbow Six Siege X,Player,24,5,None,3,0,25
|
|
||||||
EWC2025_244,nade,Brazil,South America,Furia Esports,Rainbow Six Siege X,Player,22,4,None,3,0,22
|
|
||||||
EWC2025_245,Luke Bennett,UK,Europe,BMW M Team Redline Red Bull Sim Racing,Rennsport,Driver,25,7,None,1,0,85
|
|
||||||
EWC2025_246,Jeffery Rietveld,Netherlands,Europe,BMW M Team Redline Red Bull Sim Racing,Rennsport,Driver,24,6,None,1,0,72
|
|
||||||
EWC2025_247,Sebastian Job,Germany,Europe,BMW M Team Redline Red Bull Sim Racing,Rennsport,Driver,23,5,None,1,0,65
|
|
||||||
EWC2025_248,Kevin Siggy,Austria,Europe,BMW M Team Redline Red Bull Sim Racing,Rennsport,Driver,22,4,None,1,0,58
|
|
||||||
EWC2025_249,Kevin Ellis Jr,USA,North America,Virtus.pro,Rennsport,Driver,24,5,None,2,0,52
|
|
||||||
EWC2025_250,Daire McCormack,Ireland,Europe,Virtus.pro,Rennsport,Driver,23,4,None,2,0,48
|
|
||||||
EWC2025_251,Vojtech Fiala,Czech Republic,Europe,Virtus.pro,Rennsport,Driver,22,4,None,2,0,42
|
|
||||||
EWC2025_252,Mikhail Statsenko,Russia,Europe,Virtus.pro,Rennsport,Driver,21,3,None,2,0,38
|
|
||||||
EWC2025_253,Thibault Cazaubon,France,Europe,Team Vitality,Rennsport,Driver,24,5,None,3,0,35
|
|
||||||
EWC2025_254,Marcell Csincsik,Hungary,Europe,Team Vitality,Rennsport,Driver,23,4,None,3,0,32
|
|
||||||
EWC2025_255,Erhan Jajovski,North Macedonia,Europe,Team Vitality,Rennsport,Driver,22,4,None,3,0,28
|
|
||||||
EWC2025_256,Jiri Toman,Czech Republic,Europe,Team Vitality,Rennsport,Driver,21,3,None,3,0,25
|
|
||||||
EWC2025_257,Saopimi,China,Asia,Weibo Gaming,Teamfight Tactics,Player,22,4,None,1,0,65
|
|
||||||
EWC2025_258,LBTZ,China,Asia,Weibo Gaming,Teamfight Tactics,Player,21,3,None,1,0,58
|
|
||||||
EWC2025_259,Guan,China,Asia,Weibo Gaming,Teamfight Tactics,Player,23,5,None,1,0,52
|
|
||||||
EWC2025_260,TianLong,China,Asia,Weibo Gaming,Teamfight Tactics,Player,20,3,None,1,0,48
|
|
||||||
EWC2025_261,Maris,Russia,Europe,Virtus.pro,Teamfight Tactics,Player,24,5,None,2,0,42
|
|
||||||
EWC2025_262,Milo,Russia,Europe,Virtus.pro,Teamfight Tactics,Player,22,4,None,2,0,38
|
|
||||||
EWC2025_263,k1an,Russia,Europe,Virtus.pro,Teamfight Tactics,Player,21,3,None,2,0,35
|
|
||||||
EWC2025_264,NCC1,Russia,Europe,Virtus.pro,Teamfight Tactics,Player,23,5,None,2,0,32
|
|
||||||
EWC2025_265,Binteum,South Korea,Asia,T1,Teamfight Tactics,Player,22,4,None,3,0,28
|
|
||||||
EWC2025_266,sCsC,South Korea,Asia,T1,Teamfight Tactics,Player,21,3,None,3,0,25
|
|
||||||
EWC2025_267,dunizuni,South Korea,Asia,T1,Teamfight Tactics,Player,23,5,None,3,0,22
|
|
||||||
EWC2025_268,CrazyMoving,South Korea,Asia,T1,Teamfight Tactics,Player,20,3,None,3,0,18
|
|
||||||
EWC2025_269,Opale,France,Europe,AEGIS,Teamfight Tactics,Player,22,4,None,3,0,15
|
|
||||||
EWC2025_270,Pas de Bol,France,Europe,AEGIS,Teamfight Tactics,Player,21,3,None,3,0,12
|
|
||||||
EWC2025_271,Lyyyress,France,Europe,AEGIS,Teamfight Tactics,Player,23,5,None,3,0,10
|
|
||||||
EWC2025_272,Gobosteur,France,Europe,AEGIS,Teamfight Tactics,Player,20,3,None,3,0,8
|
|
||||||
|
@@ -1,6 +0,0 @@
|
|||||||
Category,Amount_USD,Percentage,Description,Num_Recipients
|
|
||||||
Club Championship,27000000,27.0,Top 24 clubs based on points,24
|
|
||||||
Game Championships,45000000,45.0,Individual game tournament prizes,25
|
|
||||||
Qualifiers,15000000,15.0,Regional qualifier prizes,200
|
|
||||||
MVP Awards,3000000,3.0,Most Valuable Player per game,25
|
|
||||||
Club Partner Support,10000000,10.0,Support for 40 partner clubs,40
|
|
||||||
|
@@ -1,28 +0,0 @@
|
|||||||
Week,Game,Start_Date,End_Date,Duration_Days,Venue,Time_Zone
|
|
||||||
1,Rennsport,2025-07-08,2025-07-11,4,"Boulevard City, Riyadh",AST
|
|
||||||
1,Valorant,2025-07-08,2025-07-13,6,"Boulevard City, Riyadh",AST
|
|
||||||
1,Dota 2,2025-07-08,2025-07-19,12,"Boulevard City, Riyadh",AST
|
|
||||||
1,Fatal Fury: City of the Wolves,2025-07-10,2025-07-12,3,"Boulevard City, Riyadh",AST
|
|
||||||
1,Apex Legends,2025-07-10,2025-07-13,4,"Boulevard City, Riyadh",AST
|
|
||||||
1,Mobile Legends: Bang Bang - Men,2025-07-10,2025-08-02,24,"Boulevard City, Riyadh",AST
|
|
||||||
2,Mobile Legends: Bang Bang - Women,2025-07-15,2025-07-19,5,"Boulevard City, Riyadh",AST
|
|
||||||
2,Honor of Kings,2025-07-15,2025-07-26,12,"Boulevard City, Riyadh",AST
|
|
||||||
2,Free Fire,2025-07-16,2025-07-20,5,"Boulevard City, Riyadh",AST
|
|
||||||
2,League of Legends,2025-07-16,2025-07-20,5,"Boulevard City, Riyadh",AST
|
|
||||||
2,StarCraft II,2025-07-22,2025-07-25,4,"Boulevard City, Riyadh",AST
|
|
||||||
3,Call of Duty: Black Ops 6,2025-07-24,2025-07-27,4,"Boulevard City, Riyadh",AST
|
|
||||||
3,PUBG Mobile,2025-07-25,2025-08-03,10,"Boulevard City, Riyadh",AST
|
|
||||||
3,Chess,2025-07-29,2025-08-01,4,"Boulevard City, Riyadh",AST
|
|
||||||
3,Overwatch 2,2025-07-31,2025-08-03,4,"Boulevard City, Riyadh",AST
|
|
||||||
4,Rainbow Six Siege X,2025-08-05,2025-08-09,5,"Boulevard City, Riyadh",AST
|
|
||||||
4,Call of Duty: Warzone,2025-08-06,2025-08-09,4,"Boulevard City, Riyadh",AST
|
|
||||||
4,EA Sports FC 25,2025-08-07,2025-08-10,4,"Boulevard City, Riyadh",AST
|
|
||||||
5,Teamfight Tactics,2025-08-11,2025-08-15,5,"Boulevard City, Riyadh",AST
|
|
||||||
5,PUBG: Battlegrounds,2025-08-12,2025-08-16,5,"Boulevard City, Riyadh",AST
|
|
||||||
5,Tekken 8,2025-08-13,2025-08-16,4,"Boulevard City, Riyadh",AST
|
|
||||||
5,Rocket League,2025-08-14,2025-08-17,4,"Boulevard City, Riyadh",AST
|
|
||||||
6,CrossFire,2025-08-19,2025-08-23,5,"Boulevard City, Riyadh",AST
|
|
||||||
6,Street Fighter 6,2025-08-20,2025-08-23,4,"Boulevard City, Riyadh",AST
|
|
||||||
6,Counter-Strike 2,2025-08-20,2025-08-24,5,"Boulevard City, Riyadh",AST
|
|
||||||
6,Naraka: Bladepoint - Solo,2025-08-19,2025-08-19,1,"Boulevard City, Riyadh",AST
|
|
||||||
6,Naraka: Bladepoint - Trios,2025-08-20,2025-08-20,1,"Boulevard City, Riyadh",AST
|
|
||||||
|
@@ -1,37 +0,0 @@
|
|||||||
Country,Gold_Medals,Silver_Medals,Bronze_Medals,Total_Medals,Total_Players,Top_Game,Region
|
|
||||||
South Korea,4,3,5,12,58,League of Legends,Asia
|
|
||||||
China,3,2,2,7,52,Honor of Kings,Asia
|
|
||||||
USA,3,1,4,8,38,Call of Duty: Black Ops 6,North America
|
|
||||||
Russia,2,2,3,7,28,Dota 2,Europe
|
|
||||||
Saudi Arabia,1,1,3,5,32,Overwatch 2,Middle East
|
|
||||||
Philippines,1,2,2,5,30,Mobile Legends: Bang Bang,Asia
|
|
||||||
France,1,1,1,3,18,Rocket League,Europe
|
|
||||||
Mongolia,1,1,0,2,10,Counter-Strike 2,Asia
|
|
||||||
Brazil,1,0,1,2,22,Rainbow Six Siege X,South America
|
|
||||||
UK,1,0,1,2,14,Rocket League,Europe
|
|
||||||
Netherlands,1,0,1,2,8,EA Sports FC 25,Europe
|
|
||||||
Japan,1,0,0,1,4,Fatal Fury: City of the Wolves,Asia
|
|
||||||
Finland,1,0,0,1,3,StarCraft II,Europe
|
|
||||||
Indonesia,1,0,0,1,12,Free Fire,Asia
|
|
||||||
Myanmar,1,0,1,2,16,PUBG Mobile,Asia
|
|
||||||
Turkey,0,1,0,1,10,Counter-Strike 2,Europe
|
|
||||||
Ukraine,0,1,1,2,12,Dota 2,Europe
|
|
||||||
Denmark,0,1,0,1,6,Dota 2,Europe
|
|
||||||
Jordan,0,1,0,1,4,Dota 2,Middle East
|
|
||||||
Slovakia,0,1,0,1,4,Dota 2,Europe
|
|
||||||
Lithuania,0,1,0,1,4,Valorant,Europe
|
|
||||||
Thailand,0,0,1,1,8,Free Fire,Asia
|
|
||||||
Australia,0,0,1,1,6,Apex Legends,Oceania
|
|
||||||
Morocco,0,0,0,0,4,Call of Duty: Black Ops 6,Europe
|
|
||||||
Canada,0,0,0,0,4,Call of Duty: Black Ops 6,North America
|
|
||||||
Spain,0,0,0,0,4,Call of Duty: Black Ops 6,Europe
|
|
||||||
North Macedonia,0,0,0,0,4,Counter-Strike 2,Europe
|
|
||||||
Bosnia,0,0,0,0,4,Counter-Strike 2,Europe
|
|
||||||
Poland,0,0,0,0,4,Valorant,Europe
|
|
||||||
Ireland,0,0,0,0,4,Rennsport,Europe
|
|
||||||
Germany,0,0,0,0,4,Rennsport,Europe
|
|
||||||
Austria,0,0,0,0,4,Rennsport,Europe
|
|
||||||
Czech Republic,0,0,0,0,8,Rennsport,Europe
|
|
||||||
Hungary,0,0,0,0,4,Rennsport,Europe
|
|
||||||
India,0,0,0,0,4,Battlegrounds Mobile India,Asia
|
|
||||||
Chile,0,0,0,0,4,Valorant,South America
|
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
Placement,Points,System_Type,Description
|
|
||||||
1,1000,Standard,Winner
|
|
||||||
2,600,Standard,Runner-up
|
|
||||||
3,350,Standard,Third place
|
|
||||||
4,200,Standard,Fourth place
|
|
||||||
5,110,Standard,Fifth place
|
|
||||||
6,110,Standard,Sixth place
|
|
||||||
7,110,Standard,Seventh place
|
|
||||||
8,110,Standard,Eighth place
|
|
||||||
1,1000,Co-Placement,Winner (shared)
|
|
||||||
2,600,Co-Placement,Runner-up (shared)
|
|
||||||
3,350,Co-Placement,Third place (shared)
|
|
||||||
4,200,Co-Placement,Fourth place (shared)
|
|
||||||
5,110,Co-Placement,Fifth place (shared)
|
|
||||||
6,110,Co-Placement,Sixth place (shared)
|
|
||||||
7,110,Co-Placement,Seventh place (shared)
|
|
||||||
8,110,Co-Placement,Eighth place (shared)
|
|
||||||
|
@@ -1,51 +0,0 @@
|
|||||||
Game,Match_Type,Team_1,Team_2,Winner,Score,Map,Duration_Minutes,MVP
|
|
||||||
Apex Legends,Finals,VK Gaming,ROC Esports,VK Gaming,N/A,Multiple,180,Kasssa
|
|
||||||
Apex Legends,Third Place,Ninjas in Pyjamas,FaZe Clan,Ninjas in Pyjamas,N/A,Multiple,120,Vein
|
|
||||||
Call of Duty: Black Ops 6,Grand Final,OpTic Gaming,Vancouver Surge,OpTic Gaming,4-1,Multiple,150,Dashy
|
|
||||||
Call of Duty: Black Ops 6,Third Place,Movistar KOI,100 Thieves,Movistar KOI,3-2,Multiple,120,CleanX
|
|
||||||
Chess,Final,Magnus Carlsen,Alireza Firouzja,Magnus Carlsen,2.5-1.5,N/A,240,Magnus Carlsen
|
|
||||||
Chess,Third Place,Hikaru Nakamura,Fabiano Caruana,Hikaru Nakamura,2-1,N/A,180,Hikaru Nakamura
|
|
||||||
Counter-Strike 2,Grand Final,The MongolZ,Aurora Gaming,The MongolZ,2-0,"Dust2, Mirage",90,mzinho
|
|
||||||
Counter-Strike 2,Third Place,Team Falcons,Natus Vincere,Team Falcons,2-1,"Inferno, Nuke, Ancient",120,NiKo
|
|
||||||
Dota 2,Grand Final,Team Spirit,Team Falcons,Team Spirit,3-1,Multiple,210,Yatoro
|
|
||||||
Dota 2,Third Place,Parivision,Gaimin Gladiators,Parivision,2-0,Multiple,90,No[o]ne-
|
|
||||||
League of Legends,Grand Final,Gen.G,AG.AL,Gen.G,3-1,Multiple,180,Chovy
|
|
||||||
League of Legends,Third Place,T1,Bilibili Gaming,T1,2-1,Multiple,150,Faker
|
|
||||||
Valorant,Grand Final,Team Heretics,Fnatic,Team Heretics,3-1,"Ascent, Bind, Haven, Split",150,benjyfishy
|
|
||||||
Valorant,Third Place,Gen.G,Sentinels,Gen.G,2-1,Multiple,120,Munchkin
|
|
||||||
Overwatch 2,Grand Final,Team Falcons,Al Qadsiah,Team Falcons,4-1,Multiple,120,Proper
|
|
||||||
Overwatch 2,Third Place,Twisted Minds,Team Vitality,Twisted Minds,3-2,Multiple,150,FunnyAstro
|
|
||||||
StarCraft II,Final,Serral,Classic,Serral,4-1,Multiple,180,Serral
|
|
||||||
StarCraft II,Third Place,Cure,Maru,Cure,2-1,Multiple,120,Cure
|
|
||||||
Street Fighter 6,Final,Xiaohai,Blaz,Xiaohai,5-2,N/A,45,Xiaohai
|
|
||||||
Street Fighter 6,Third Place,Leshar,AngryBird,Leshar,3-2,N/A,30,Leshar
|
|
||||||
Tekken 8,Final,ULSAN,LOWHIGH,ULSAN,3-1,N/A,30,ULSAN
|
|
||||||
Tekken 8,Third Place,CBM,Arslan Ash,CBM,2-1,N/A,25,CBM
|
|
||||||
EA Sports FC 25,Final,ManuBachoore,Brice,ManuBachoore,3-1,N/A,30,ManuBachoore
|
|
||||||
EA Sports FC 25,Third Place,Levi de Weerd,Tekkz,Levi de Weerd,2-1,N/A,25,Levi de Weerd
|
|
||||||
Fatal Fury: City of the Wolves,Final,GO1,Xiaohai,GO1,3-2,N/A,30,GO1
|
|
||||||
Fatal Fury: City of the Wolves,Third Place,DarkAngel,MenaRD,DarkAngel,2-1,N/A,25,DarkAngel
|
|
||||||
Rocket League,Grand Final,Karmine Corp,Geekay Esports,Karmine Corp,4-2,Multiple,60,Vatira
|
|
||||||
Rocket League,Third Place,Team Falcons,Team BDS,Team Falcons,3-2,Multiple,50,Trk511
|
|
||||||
Call of Duty: Warzone,Final,Twisted Minds,Gentle Mates,Twisted Minds,N/A,Multiple,180,Aydan
|
|
||||||
Call of Duty: Warzone,Third Place,Virtus.pro,Team Liquid,Virtus.pro,N/A,Multiple,120,Newbz
|
|
||||||
CrossFire,Grand Final,AG.AL,BaiSha Gaming,AG.AL,3-1,Multiple,120,ZY
|
|
||||||
CrossFire,Third Place,Evolution Power,EDward Gaming,Evolution Power,2-1,Multiple,90,ZAY
|
|
||||||
Free Fire,Final,EVOS Esports,Rex Regum Qeon,EVOS Esports,N/A,Multiple,180,Rasyah
|
|
||||||
Free Fire,Third Place,Team Vitality,ONIC Esports,Team Vitality,N/A,Multiple,120,JUMP
|
|
||||||
Honor of Kings,Grand Final,AG.AL,ThunderTalk Global,AG.AL,4-1,Multiple,150,Ran
|
|
||||||
Honor of Kings,Third Place,Nova Esports,Wolves Esports,Nova Esports,3-2,Multiple,120,Xuan
|
|
||||||
Mobile Legends: Bang Bang - Men,Grand Final,Team Liquid PH,SRG.OG,Team Liquid PH,4-2,Multiple,180,KarlTzy
|
|
||||||
Mobile Legends: Bang Bang - Men,Third Place,Onic Philippines,EVOS Esports,Onic Philippines,3-1,Multiple,120,Kelra
|
|
||||||
Mobile Legends: Bang Bang - Women,Grand Final,Team Vitality,Gaimin Gladiators,Team Vitality,3-1,Multiple,90,Fumi
|
|
||||||
Mobile Legends: Bang Bang - Women,Third Place,Terror Queens,ONIC Esports,Terror Queens,2-1,Multiple,60,Hlaing
|
|
||||||
PUBG: Battlegrounds,Final,Twisted Minds,Gen.G,Twisted Minds,N/A,Multiple,180,xmpl
|
|
||||||
PUBG: Battlegrounds,Third Place,Team Falcons,FaZe Clan,Team Falcons,N/A,Multiple,120,hwinn
|
|
||||||
PUBG Mobile,Final,Yangon Galacticos,Weibo Gaming,Yangon Galacticos,N/A,Multiple,180,Smile
|
|
||||||
PUBG Mobile,Third Place,Alpha Gaming,Team Vitality,Alpha Gaming,N/A,Multiple,120,Zyol
|
|
||||||
Rainbow Six Siege X,Grand Final,Team Secret,G2 Esports,Team Secret,3-1,Multiple,150,Savage
|
|
||||||
Rainbow Six Siege X,Third Place,Furia Esports,Ninjas in Pyjamas,Furia Esports,2-1,Multiple,120,FelipeX
|
|
||||||
Rennsport,Final,BMW M Team Redline Red Bull Sim Racing,Virtus.pro,BMW M Team Redline Red Bull Sim Racing,N/A,Multiple,120,Luke Bennett
|
|
||||||
Rennsport,Third Place,Team Vitality,Team Liquid,Team Vitality,N/A,Multiple,90,Thibault Cazaubon
|
|
||||||
Teamfight Tactics,Final,Weibo Gaming,Virtus.pro,Weibo Gaming,N/A,N/A,180,Saopimi
|
|
||||||
Teamfight Tactics,Third Place,T1,AEGIS,T1,N/A,N/A,120,Binteum
|
|
||||||
|
202
data/README.md
202
data/README.md
@@ -1,202 +0,0 @@
|
|||||||
# 🎮 Esports World Cup 2025 — Complete Dataset
|
|
||||||
|
|
||||||
> **The most comprehensive structured dataset for EWC 2025**, covering all 27 game tournaments held in Riyadh, Saudi Arabia from July 8 to August 2025. 10 interlinked CSV files spanning players, teams, results, prize pools, and more.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📌 About the Dataset
|
|
||||||
|
|
||||||
The **Esports World Cup (EWC)** is the world's largest esports event, hosted annually at Boulevard City in Riyadh. The 2025 edition featured **27 title tournaments**, a **$100M+ total prize pool**, and competitors from **36+ countries** across PC and mobile platforms.
|
|
||||||
|
|
||||||
This dataset was compiled to support analysis of competitive esports at the highest level — team performance, player demographics, prize distribution, country dominance, and the Club Championship meta-game.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📁 Files Overview
|
|
||||||
|
|
||||||
| # | File | Rows | Cols | Description |
|
|
||||||
|---|------|------|------|-------------|
|
|
||||||
| 01 | `01_EWC2025_Event_Tournament_Summary.csv` | 27 | 12 | One row per game tournament — dates, prize pool, winner, platform |
|
|
||||||
| 02 | `02_EWC2025_Medalists.csv` | 257 | 6 | Every gold/silver/bronze medalist with country and role |
|
|
||||||
| 03 | `03_EWC2025_Club_Championship_Standings.csv` | 24 | 10 | Final Club Championship rankings with points and prize money |
|
|
||||||
| 04 | `04_EWC2025_Club_Partner_Program.csv` | 40 | 10 | All club partner orgs — region, founding year, social following |
|
|
||||||
| 05 | `05_EWC2025_Player_Roster.csv` | 272 | 13 | Full player roster with age, experience, earnings, social reach |
|
|
||||||
| 06 | `06_EWC2025_Prize_Pool_Distribution.csv` | 5 | 5 | How the $100M+ prize pool was split across categories |
|
|
||||||
| 07 | `07_EWC2025_Calendar_Schedule.csv` | 27 | 7 | Weekly schedule with venue and timezone for each tournament |
|
|
||||||
| 08 | `08_EWC2025_Country_Results.csv` | 36 | 8 | Medal tally by country with top game and player count |
|
|
||||||
| 09 | `09_EWC2025_Point_System.csv` | 16 | 4 | Club Championship point system by placement |
|
|
||||||
| 10 | `10_EWC2025_Game_by_Game_Results.csv` | 50 | 9 | Match results with scores, maps, duration, and MVP |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔑 Column Dictionary
|
|
||||||
|
|
||||||
### 01 — Event & Tournament Summary
|
|
||||||
| Column | Type | Description |
|
|
||||||
|--------|------|-------------|
|
|
||||||
| `Game` | str | Game title |
|
|
||||||
| `Event_Name` | str | Official tournament name |
|
|
||||||
| `Start_Date` | date | Tournament start date |
|
|
||||||
| `End_Date` | date | Tournament end date |
|
|
||||||
| `Prize_Pool_USD` | int | Total prize pool in USD |
|
|
||||||
| `Num_Participants` | int | Number of competing teams/players |
|
|
||||||
| `Winner` | str | Tournament champion |
|
|
||||||
| `Runner_Up` | str | Runner-up |
|
|
||||||
| `Game_Type` | str | Genre (MOBA, FPS, Racing, etc.) |
|
|
||||||
| `Platform` | str | PC or Mobile |
|
|
||||||
| `Club_Championship_Points` | str | Whether points were awarded (Yes/No) |
|
|
||||||
| `Gender` | str | Mixed/Women/Men (NaN = open) |
|
|
||||||
|
|
||||||
### 02 — Medalists
|
|
||||||
| Column | Type | Description |
|
|
||||||
|--------|------|-------------|
|
|
||||||
| `Event` | str | Game title |
|
|
||||||
| `Medal` | str | Gold / Silver / Bronze |
|
|
||||||
| `Team_Organization` | str | Organization name |
|
|
||||||
| `Player` | str | Player handle/name |
|
|
||||||
| `Country` | str | Player's country |
|
|
||||||
| `Role` | str | In-game role (IGL, Fragger, Support, etc.) |
|
|
||||||
|
|
||||||
### 03 — Club Championship Standings
|
|
||||||
| Column | Type | Description |
|
|
||||||
|--------|------|-------------|
|
|
||||||
| `Rank` | int | Final standing |
|
|
||||||
| `Organization` | str | Club name |
|
|
||||||
| `Total_Points` | int | Total Club Championship points |
|
|
||||||
| `Prize_Money_USD` | int | Prize money earned |
|
|
||||||
| `Tournament_Wins` | int | Number of tournaments won |
|
|
||||||
| `Top_8_Finishes` | int | Top-8 finishes across events |
|
|
||||||
| `Region` | str | Organization's home region |
|
|
||||||
| `Club_Partner_Status` | str | Current / New / No |
|
|
||||||
| `Eligible_to_Win` | str | Eligibility status |
|
|
||||||
| `Games_Won` | str | List of games the club won |
|
|
||||||
|
|
||||||
### 04 — Club Partner Program
|
|
||||||
| Column | Type | Description |
|
|
||||||
|--------|------|-------------|
|
|
||||||
| `Organization` | str | Club name |
|
|
||||||
| `Region` | str | Geographic region |
|
|
||||||
| `Country` | str | Home country |
|
|
||||||
| `Club_Partner_Status` | str | Current / New |
|
|
||||||
| `Top_8_2024` | str | Did club finish top-8 in 2024? |
|
|
||||||
| `Games_Competing` | str | Games the club entered |
|
|
||||||
| `Founded` | int | Year founded |
|
|
||||||
| `HQ_Location` | str | Headquarters city/country |
|
|
||||||
| `CEO` | str | CEO or owner |
|
|
||||||
| `Social_Media_Followers_M` | float | Total social following (millions) |
|
|
||||||
|
|
||||||
### 05 — Player Roster
|
|
||||||
| Column | Type | Description |
|
|
||||||
|--------|------|-------------|
|
|
||||||
| `Player_ID` | str | Unique player ID (EWC2025_XXX) |
|
|
||||||
| `Player_Name` | str | Player handle |
|
|
||||||
| `Country` | str | Nationality |
|
|
||||||
| `Region` | str | Continental region |
|
|
||||||
| `Team` | str | Competing team |
|
|
||||||
| `Game` | str | Game played |
|
|
||||||
| `Role` | str | In-game role |
|
|
||||||
| `Age` | int | Player age |
|
|
||||||
| `Experience_Years` | int | Years of pro experience |
|
|
||||||
| `Previous_Team` | str | Prior team (NaN if first team) |
|
|
||||||
| `Tournament_Place` | int | Final placement |
|
|
||||||
| `Prize_Earned_USD` | int | Individual prize earnings |
|
|
||||||
| `Social_Media_Followers_K` | int | Social following (thousands) |
|
|
||||||
|
|
||||||
### 06 — Prize Pool Distribution
|
|
||||||
| Column | Type | Description |
|
|
||||||
|--------|------|-------------|
|
|
||||||
| `Category` | str | Prize category |
|
|
||||||
| `Amount_USD` | int | Total amount for category |
|
|
||||||
| `Percentage` | float | Share of total prize pool |
|
|
||||||
| `Description` | str | What the prize covers |
|
|
||||||
| `Num_Recipients` | int | Number of recipients |
|
|
||||||
|
|
||||||
### 07 — Calendar & Schedule
|
|
||||||
| Column | Type | Description |
|
|
||||||
|--------|------|-------------|
|
|
||||||
| `Week` | int | Event week number |
|
|
||||||
| `Game` | str | Game title |
|
|
||||||
| `Start_Date` | date | Start date |
|
|
||||||
| `End_Date` | date | End date |
|
|
||||||
| `Duration_Days` | int | Tournament length in days |
|
|
||||||
| `Venue` | str | Venue name and city |
|
|
||||||
| `Time_Zone` | str | Local timezone (AST) |
|
|
||||||
|
|
||||||
### 08 — Country Results
|
|
||||||
| Column | Type | Description |
|
|
||||||
|--------|------|-------------|
|
|
||||||
| `Country` | str | Country name |
|
|
||||||
| `Gold_Medals` | int | Gold medals won |
|
|
||||||
| `Silver_Medals` | int | Silver medals won |
|
|
||||||
| `Bronze_Medals` | int | Bronze medals won |
|
|
||||||
| `Total_Medals` | int | Total medals |
|
|
||||||
| `Total_Players` | int | Number of players from country |
|
|
||||||
| `Top_Game` | str | Game country excelled in most |
|
|
||||||
| `Region` | str | Geographic region |
|
|
||||||
|
|
||||||
### 09 — Point System
|
|
||||||
| Column | Type | Description |
|
|
||||||
|--------|------|-------------|
|
|
||||||
| `Placement` | int | Finishing position |
|
|
||||||
| `Points` | int | Club Championship points awarded |
|
|
||||||
| `System_Type` | str | Standard / Extended / Special |
|
|
||||||
| `Description` | str | Label for the placement |
|
|
||||||
|
|
||||||
### 10 — Game-by-Game Results
|
|
||||||
| Column | Type | Description |
|
|
||||||
|--------|------|-------------|
|
|
||||||
| `Game` | str | Game title |
|
|
||||||
| `Match_Type` | str | Finals / Grand Final / Third Place / etc. |
|
|
||||||
| `Team_1` | str | First competing team |
|
|
||||||
| `Team_2` | str | Second competing team |
|
|
||||||
| `Winner` | str | Winning team |
|
|
||||||
| `Score` | str | Match score (e.g., 4-1) |
|
|
||||||
| `Map` | str | Map or stage played |
|
|
||||||
| `Duration_Minutes` | int | Match length in minutes |
|
|
||||||
| `MVP` | str | Most Valuable Player of the match |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔗 Entity Relationships
|
|
||||||
|
|
||||||
```
|
|
||||||
Event_Tournament_Summary ──┬──> Game_by_Game_Results (via Game)
|
|
||||||
├──> Medalists (via Event/Game)
|
|
||||||
└──> Calendar_Schedule (via Game)
|
|
||||||
|
|
||||||
Club_Championship_Standings ──> Club_Partner_Program (via Organization)
|
|
||||||
Club_Championship_Standings ──> Player_Roster (via Team)
|
|
||||||
|
|
||||||
Medalists ──> Player_Roster (via Player)
|
|
||||||
Country_Results ──> Player_Roster (via Country)
|
|
||||||
Point_System ──> Club_Championship_Standings (via Placement → Points)
|
|
||||||
Prize_Pool_Distribution ──> Event_Tournament_Summary (via Prize totals)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 Suggested Analyses
|
|
||||||
|
|
||||||
- 🏆 **Which country dominated EWC 2025?** — Medal tally, players per medal, regional power maps
|
|
||||||
- 💰 **Prize money vs. Club Championship performance** — Is tournament breadth or depth rewarded more?
|
|
||||||
- 👤 **Player age & experience vs. earnings** — Do veterans outperform newcomers?
|
|
||||||
- 🌍 **Regional representation by game genre** — Does Asia dominate MOBAs? Does Europe lead in FPS?
|
|
||||||
- 📅 **Schedule clustering** — Which weeks had the most high-stakes matches?
|
|
||||||
- 🔁 **Club partner loyalty** — How do new vs. current partners compare in performance?
|
|
||||||
- 🎯 **MVP distribution** — Which players appeared most often as MVPs across matches?
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📜 License
|
|
||||||
|
|
||||||
This dataset is released under **CC BY 4.0**. You are free to share and adapt it for any purpose with attribution.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🙏 Acknowledgements
|
|
||||||
|
|
||||||
Data compiled from publicly available Esports World Cup 2025 tournament results, official brackets, and club partnership announcements. This is a fan/researcher-compiled dataset and is not officially affiliated with EWC or its organizers.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*If you find this dataset useful, please upvote ⬆️ — it helps others discover it!*
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
$CONTAINER = "ewc2025-mysql"
|
$CONTAINER = "hotel-mysql"
|
||||||
$IMAGE = "mysql:8.4"
|
$IMAGE = "mysql:8.4"
|
||||||
$ROOT_PASSWORD = "ewc2025root"
|
$ROOT_PASSWORD = "hotel2025root"
|
||||||
$DATABASE = "ewc2025"
|
$DATABASE = "hotel_reservations"
|
||||||
$PORT = "13306"
|
$PORT = "13306"
|
||||||
|
|
||||||
$SQL_DIR = Resolve-Path "$PSScriptRoot\..\sql"
|
$SQL_DIR = Resolve-Path "$PSScriptRoot\..\sql"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
CONTAINER="ewc2025-mysql"
|
CONTAINER="hotel-mysql"
|
||||||
IMAGE="mysql:8.4"
|
IMAGE="mysql:8.4"
|
||||||
ROOT_PASSWORD="ewc2025root"
|
ROOT_PASSWORD="hotel2025root"
|
||||||
DATABASE="ewc2025"
|
DATABASE="hotel_reservations"
|
||||||
PORT="13306"
|
PORT="13306"
|
||||||
|
|
||||||
RUNTIME="docker"
|
RUNTIME="docker"
|
||||||
@@ -26,7 +26,7 @@ else
|
|||||||
-e MYSQL_DATABASE="${DATABASE}" \
|
-e MYSQL_DATABASE="${DATABASE}" \
|
||||||
-p "${PORT}:3306" \
|
-p "${PORT}:3306" \
|
||||||
-v "${CONTAINER}-data:/var/lib/mysql" \
|
-v "${CONTAINER}-data:/var/lib/mysql" \
|
||||||
-v "${SQL_DIR}/schema.sql:/docker-entrypoint-initdb.d/01_schema.sql:ro" \
|
-v "${SQL_DIR}/schema.sql:/docker-entrypoint-initdb.d/01_schema.sql:ro,z" \
|
||||||
"${IMAGE}"
|
"${IMAGE}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
$CONTAINER = "ewc2025-mysql"
|
$CONTAINER = "hotel-mysql"
|
||||||
|
|
||||||
$exists = docker ps -a --format '{{.Names}}' | Where-Object { $_ -eq $CONTAINER }
|
$exists = docker ps -a --format '{{.Names}}' | Where-Object { $_ -eq $CONTAINER }
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
CONTAINER="ewc2025-mysql"
|
CONTAINER="hotel-mysql"
|
||||||
|
|
||||||
RUNTIME="docker"
|
RUNTIME="docker"
|
||||||
if [[ "${1:-}" == "--podman" ]]; then
|
if [[ "${1:-}" == "--podman" ]]; then
|
||||||
|
|||||||
98
docs/01-overview.md
Normal file
98
docs/01-overview.md
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
# Hotel Reservations — Data Warehouse Project
|
||||||
|
|
||||||
|
## Project Summary
|
||||||
|
|
||||||
|
This project implements a complete **Data Warehousing pipeline** for a hotel reservation system, covering all standard DW layers:
|
||||||
|
|
||||||
|
```
|
||||||
|
MySQL OLTP ──► Apache NiFi ETL ──► Oracle Data Mart ──► Power BI Reports
|
||||||
|
(source) (transform) (analytical store) (OLAP queries)
|
||||||
|
```
|
||||||
|
|
||||||
|
The system is built around the **A.24 Hotel Reservations** domain from the course specification. The OLTP database was populated with **~635,000 synthetically generated rows** covering 200 hotels, 100,000 guests, 500,000 bookings, and 531,000 room bookings across a 4-year period (2022–2025).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Business Context
|
||||||
|
|
||||||
|
A hotel chain needs to answer questions like:
|
||||||
|
|
||||||
|
- Which countries generate the most revenue per quarter?
|
||||||
|
- How does occupancy differ between peak and off-peak seasons?
|
||||||
|
- What is the revenue contribution of 5-star vs 3-star hotels?
|
||||||
|
- How has a hotel's revenue changed after upgrading its star rating?
|
||||||
|
|
||||||
|
These questions require **historical, multi-dimensional analysis** that a normalized OLTP database cannot serve efficiently. The data mart provides pre-modelled, denormalized data optimized for analytical queries.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ SOURCE LAYER │
|
||||||
|
│ MySQL 8.4 (Docker/Podman, port 13306) │
|
||||||
|
│ Database: hotel_reservations │
|
||||||
|
│ 13 normalized tables, ~635K rows │
|
||||||
|
└───────────────────────┬─────────────────────────────────┘
|
||||||
|
│ JDBC (MySqlConnector)
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ ETL LAYER │
|
||||||
|
│ Apache NiFi │
|
||||||
|
│ 5 Process Groups: Date Dim / Static Dims / │
|
||||||
|
│ SCD2 Hotel / SCD1 Guest / Incremental Fact │
|
||||||
|
└───────────────────────┬─────────────────────────────────┘
|
||||||
|
│ JDBC (Oracle JDBC)
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ DATA MART LAYER │
|
||||||
|
│ Oracle (university lab schema) │
|
||||||
|
│ Star schema: 6 dimensions + 1 fact table │
|
||||||
|
│ SCD Type 2 on DIM_HOTEL │
|
||||||
|
└───────────────────────┬─────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ PRESENTATION LAYER │
|
||||||
|
│ Power BI Desktop │
|
||||||
|
│ OLAP reports via DirectQuery / Import │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
| Component | Technology | Version |
|
||||||
|
|-----------|-----------|---------|
|
||||||
|
| OLTP Database | MySQL | 8.4 |
|
||||||
|
| Container runtime | Docker / Podman | — |
|
||||||
|
| Data generator | C# (.NET) | 10 |
|
||||||
|
| ETL tool | Apache NiFi | — |
|
||||||
|
| Data Mart | Oracle RDBMS | university lab |
|
||||||
|
| Reporting | Power BI Desktop | — |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Repository Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
IPZ_1/
|
||||||
|
├── docker/
|
||||||
|
│ ├── start.sh # Start MySQL container (Linux/macOS)
|
||||||
|
│ ├── stop.sh # Stop MySQL container
|
||||||
|
│ ├── start.ps1 # Start MySQL container (Windows)
|
||||||
|
│ └── stop.ps1 # Stop MySQL container
|
||||||
|
├── sql/
|
||||||
|
│ ├── schema.sql # MySQL OLTP DDL
|
||||||
|
│ └── datamart_schema.sql # Oracle Data Mart DDL
|
||||||
|
├── generator/
|
||||||
|
│ └── generate.cs # .NET 10 data generator script
|
||||||
|
└── docs/
|
||||||
|
├── 01-overview.md # This file
|
||||||
|
├── 02-oltp.md # OLTP database design
|
||||||
|
├── 03-datamart.md # Data mart design
|
||||||
|
├── 04-setup.md # Setup and run guide
|
||||||
|
└── nifi-flow.md # NiFi ETL flow reference
|
||||||
|
```
|
||||||
258
docs/02-oltp.md
Normal file
258
docs/02-oltp.md
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
# OLTP Database — Design & Details
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The OLTP (Online Transaction Processing) database models a **hotel reservation system** using a fully normalized relational schema in **MySQL 8.4**. It follows 3NF and enforces referential integrity via foreign keys.
|
||||||
|
|
||||||
|
- **Database:** `hotel_reservations`
|
||||||
|
- **Character set:** `utf8mb4` / `utf8mb4_unicode_ci`
|
||||||
|
- **Tables:** 13
|
||||||
|
- **Total rows:** ~635,000
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Entity-Relationship Model
|
||||||
|
|
||||||
|
The schema covers five entity groups:
|
||||||
|
|
||||||
|
```
|
||||||
|
hotel_chain ──┐
|
||||||
|
country ───────┼──► hotel ──► hotel_room ──► room_booking ──► booking ──► guest
|
||||||
|
star_rating ──┘ │
|
||||||
|
└──► country
|
||||||
|
hotel_characteristic ◄──► hotel (M:N via hotel_hotel_characteristic)
|
||||||
|
|
||||||
|
room_type ◄──── hotel_room
|
||||||
|
room_type ◄──┐
|
||||||
|
rate_period ◄─┴── period_room_rate (price per room type per season)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Table Descriptions
|
||||||
|
|
||||||
|
### Reference / Lookup Tables
|
||||||
|
|
||||||
|
#### `hotel_chain`
|
||||||
|
International hotel chains (Hilton, Marriott, Accor, etc.).
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `hotel_chain_id` | INT UNSIGNED PK | Surrogate key |
|
||||||
|
| `code` | VARCHAR(10) UNIQUE | Short code (e.g. `HLT`) |
|
||||||
|
| `name` | VARCHAR(100) | Full name |
|
||||||
|
|
||||||
|
**Rows:** 10
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `country`
|
||||||
|
Countries from which guests come and where hotels are located.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `country_id` | INT UNSIGNED PK | Surrogate key |
|
||||||
|
| `code` | CHAR(2) UNIQUE | ISO 3166-1 alpha-2 (e.g. `GB`) |
|
||||||
|
| `name` | VARCHAR(100) | Country name |
|
||||||
|
| `currency` | VARCHAR(10) | ISO currency code (e.g. `EUR`) |
|
||||||
|
|
||||||
|
**Rows:** 40 (Europe, Americas, Asia, Africa, Oceania)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `star_rating`
|
||||||
|
Hotel classification from 1★ to 5★.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `star_rating_id` | INT UNSIGNED PK | Surrogate key |
|
||||||
|
| `code` | TINYINT UNIQUE | 1–5 |
|
||||||
|
| `description` | VARCHAR(20) | e.g. `3 Star` |
|
||||||
|
|
||||||
|
**Rows:** 5
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `hotel_characteristic`
|
||||||
|
Amenities and features a hotel may offer.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `characteristic_id` | INT UNSIGNED PK | Surrogate key |
|
||||||
|
| `code` | VARCHAR(20) UNIQUE | e.g. `POOL`, `SPA`, `WIFI` |
|
||||||
|
| `description` | VARCHAR(100) | Human-readable label |
|
||||||
|
|
||||||
|
**Rows:** 12 (WiFi, Pool, Gym, Spa, Restaurant, Bar, Parking, Valet, Conference, Shuttle, Room Service, Pet Friendly)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `room_type`
|
||||||
|
Types of rooms a hotel can offer, with a standard (base) rate.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `room_type_id` | INT UNSIGNED PK | Surrogate key |
|
||||||
|
| `code` | VARCHAR(20) UNIQUE | e.g. `SINGLE`, `SUITE` |
|
||||||
|
| `description` | VARCHAR(100) | e.g. `Junior Suite` |
|
||||||
|
| `standard_rate` | DECIMAL(10,2) | Base nightly rate (EUR) |
|
||||||
|
| `smoking_yn` | BOOLEAN | Smoking allowed flag |
|
||||||
|
|
||||||
|
**Rows:** 7 (Single €80, Double €120, Twin €115, Deluxe €180, Suite €280, Executive €450, Family €200)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `rate_period`
|
||||||
|
Seasonal pricing periods. Each period maps to a month range and applies a rate multiplier.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `rate_period_id` | INT UNSIGNED PK | Surrogate key |
|
||||||
|
| `code` | VARCHAR(20) UNIQUE | e.g. `PEAK`, `WINTER` |
|
||||||
|
| `description` | VARCHAR(50) | Human-readable label |
|
||||||
|
| `month_from` | TINYINT | Start month (1–12) |
|
||||||
|
| `month_to` | TINYINT | End month (1–12) |
|
||||||
|
|
||||||
|
**Rows:** 4
|
||||||
|
|
||||||
|
| Code | Period | Months | Multiplier |
|
||||||
|
|------|--------|--------|-----------|
|
||||||
|
| PEAK | Peak Season | Jun–Aug | ×1.5 |
|
||||||
|
| HIGH | High Season | Mar–May | ×1.2 |
|
||||||
|
| AUTUMN | Autumn Season | Sep–Nov | ×1.1 |
|
||||||
|
| WINTER | Winter Season | Dec–Feb | ×0.9 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Junction Tables
|
||||||
|
|
||||||
|
#### `period_room_rate`
|
||||||
|
The effective nightly rate for each (room_type, rate_period) combination.
|
||||||
|
Rate = `standard_rate × season_multiplier`.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `room_type_id` | INT UNSIGNED PK/FK | |
|
||||||
|
| `rate_period_id` | INT UNSIGNED PK/FK | |
|
||||||
|
| `rate` | DECIMAL(10,2) | Effective nightly rate |
|
||||||
|
|
||||||
|
**Rows:** 28 (7 room types × 4 seasons)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `hotel_hotel_characteristic`
|
||||||
|
M:N junction between hotels and their amenities.
|
||||||
|
|
||||||
|
| Column | Type |
|
||||||
|
|--------|------|
|
||||||
|
| `hotel_id` | INT UNSIGNED PK/FK |
|
||||||
|
| `characteristic_id` | INT UNSIGNED PK/FK |
|
||||||
|
|
||||||
|
**Rows:** ~1,415
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Core Entity Tables
|
||||||
|
|
||||||
|
#### `hotel`
|
||||||
|
Individual hotel properties.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `hotel_id` | INT UNSIGNED PK | |
|
||||||
|
| `hotel_chain_id` | INT UNSIGNED FK | NULL for independent hotels |
|
||||||
|
| `country_id` | INT UNSIGNED FK | |
|
||||||
|
| `star_rating_id` | INT UNSIGNED FK | |
|
||||||
|
| `code` | VARCHAR(20) UNIQUE | e.g. `HTL0001` |
|
||||||
|
| `name` | VARCHAR(150) | |
|
||||||
|
| `address` | VARCHAR(200) | |
|
||||||
|
| `postcode` | VARCHAR(20) | |
|
||||||
|
| `city` | VARCHAR(100) | |
|
||||||
|
| `url` | VARCHAR(200) | |
|
||||||
|
|
||||||
|
**Rows:** 200 (50 cities, star distribution: 5% 1★, 10% 2★, 40% 3★, 30% 4★, 15% 5★)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `hotel_room`
|
||||||
|
Individual rooms within each hotel.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `room_id` | INT UNSIGNED PK | |
|
||||||
|
| `hotel_id` | INT UNSIGNED FK | |
|
||||||
|
| `room_type_id` | INT UNSIGNED FK | |
|
||||||
|
| `room_number` | VARCHAR(10) | Format: `{floor}{number}`, e.g. `101` |
|
||||||
|
| `floor` | TINYINT UNSIGNED | |
|
||||||
|
|
||||||
|
**Rows:** 5,334 (5–60 rooms per hotel depending on star rating)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `guest`
|
||||||
|
Hotel guests.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `guest_id` | INT UNSIGNED PK | |
|
||||||
|
| `country_id` | INT UNSIGNED FK | Guest's home country |
|
||||||
|
| `name` | VARCHAR(150) | Full name |
|
||||||
|
| `email` | VARCHAR(150) | Unique synthetic email |
|
||||||
|
| `address` | VARCHAR(200) | |
|
||||||
|
| `city` | VARCHAR(100) | |
|
||||||
|
|
||||||
|
**Rows:** 100,000
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `booking`
|
||||||
|
A reservation made by a guest at a hotel. One booking can cover multiple rooms.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `booking_id` | INT UNSIGNED PK | |
|
||||||
|
| `guest_id` | INT UNSIGNED FK | |
|
||||||
|
| `hotel_id` | INT UNSIGNED FK | |
|
||||||
|
| `date_from` | DATE | Check-in |
|
||||||
|
| `date_to` | DATE | Check-out |
|
||||||
|
| `status` | ENUM | `confirmed`, `cancelled`, `completed`, `no_show` |
|
||||||
|
| `created_at` | DATETIME | When booking was made |
|
||||||
|
|
||||||
|
**Rows:** 500,000
|
||||||
|
**Status distribution:** 80% completed, 10% confirmed, 7% cancelled, 3% no_show
|
||||||
|
**Date range:** 2022-01-01 – 2025-12-31
|
||||||
|
**Seasonal distribution:** June–August heaviest (peak), December–February lightest
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `room_booking`
|
||||||
|
A specific room assigned within a booking. Stores the rate **as it was at booking time** (snapshot), independent of any future rate changes.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `room_booking_id` | INT UNSIGNED PK | |
|
||||||
|
| `booking_id` | INT UNSIGNED FK | |
|
||||||
|
| `room_id` | INT UNSIGNED FK | |
|
||||||
|
| `date_from` | DATE | |
|
||||||
|
| `date_to` | DATE | |
|
||||||
|
| `nightly_rate` | DECIMAL(10,2) | Rate at time of booking |
|
||||||
|
| `total_amount` | DECIMAL(10,2) | `nightly_rate × nights` |
|
||||||
|
|
||||||
|
**Rows:** 531,382
|
||||||
|
**Room count per booking:** 90% single room, 8% two rooms, 2% three rooms
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Data Generation
|
||||||
|
|
||||||
|
The database was populated using a **single-file C# script** (`generator/generate.cs`) running on .NET 10, using `MySqlConnector` as the only dependency.
|
||||||
|
|
||||||
|
Key generation decisions:
|
||||||
|
- **Seasonal booking distribution** via rejection sampling — months Jun–Aug are ~2.7× more likely than Jan–Feb
|
||||||
|
- **Rate snapshot** — each `room_booking.nightly_rate` is looked up from `period_room_rate` at insert time and stored, not re-computed later
|
||||||
|
- **Realistic stay lengths** — 30% one night, 25% two nights, 20% three nights, tapering off to 14-night stays
|
||||||
|
- **Cancelled/no-show bookings** partially skip room assignment (60% of cancellations have no room_booking)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run generator
|
||||||
|
dotnet run generator/generate.cs
|
||||||
|
```
|
||||||
255
docs/03-datamart.md
Normal file
255
docs/03-datamart.md
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
# Data Mart — Design & Details
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The data mart uses a **star schema** stored in an Oracle database (university lab schema). It is optimized for analytical queries against hotel reservation data — revenue analysis, occupancy trends, seasonal patterns, and guest origin breakdowns.
|
||||||
|
|
||||||
|
- **Schema type:** Star schema
|
||||||
|
- **Dimensions:** 6 (+ date dimension)
|
||||||
|
- **Fact table:** `FACT_ROOM_BOOKING`
|
||||||
|
- **Grain:** One row per room_booking (one room, one stay)
|
||||||
|
- **SCD strategy:** Type 2 on DIM_HOTEL, Type 1 on all others
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Star Schema Diagram
|
||||||
|
|
||||||
|
```
|
||||||
|
DIM_DATE
|
||||||
|
(date_key)
|
||||||
|
│
|
||||||
|
┌───────────┴───────────┐
|
||||||
|
│ checkin / checkout │
|
||||||
|
│ │
|
||||||
|
DIM_HOTEL_CHAIN ◄─ DIM_HOTEL ─► DIM_STAR_RATING
|
||||||
|
│ │
|
||||||
|
│ FACT_ROOM_BOOKING ◄──── DIM_ROOM
|
||||||
|
│ │
|
||||||
|
└───────► DIM_COUNTRY ◄───── DIM_GUEST
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dimension Tables
|
||||||
|
|
||||||
|
### DIM_DATE
|
||||||
|
Populated once for the range 2020–2030. Used for both check-in and check-out date lookups.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `date_key` | NUMBER(8) PK | YYYYMMDD integer key |
|
||||||
|
| `full_date` | DATE | Actual date value |
|
||||||
|
| `year` | NUMBER(4) | |
|
||||||
|
| `quarter` | NUMBER(1) | 1–4 |
|
||||||
|
| `month` | NUMBER(2) | 1–12 |
|
||||||
|
| `month_name` | VARCHAR2(10) | e.g. `January` |
|
||||||
|
| `week_number` | NUMBER(2) | ISO week number |
|
||||||
|
| `day_of_month` | NUMBER(2) | |
|
||||||
|
| `day_name` | VARCHAR2(10) | e.g. `Monday` |
|
||||||
|
| `is_weekend` | NUMBER(1) | 0/1 |
|
||||||
|
| `is_business_day` | NUMBER(1) | 0/1 |
|
||||||
|
| `season` | VARCHAR2(10) | Peak / High / Autumn / Winter |
|
||||||
|
|
||||||
|
Using an integer date key (YYYYMMDD) instead of a DATE FK allows efficient range predicates: `checkin_date_key BETWEEN 20240601 AND 20240831`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### DIM_COUNTRY (SCD Type 1)
|
||||||
|
Country attributes are stable. If a name or currency ever changes, the row is simply overwritten (no history needed).
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `country_key` | NUMBER(10) PK | Surrogate (IDENTITY) |
|
||||||
|
| `country_id` | NUMBER(10) UNIQUE | Natural key from MySQL |
|
||||||
|
| `code` | CHAR(2) | ISO alpha-2 |
|
||||||
|
| `name` | VARCHAR2(100) | |
|
||||||
|
| `currency` | VARCHAR2(10) | ISO currency code |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### DIM_STAR_RATING (SCD Type 1)
|
||||||
|
Static lookup. Star rating codes 1–5 never change.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `star_rating_key` | NUMBER(10) PK | Surrogate (IDENTITY) |
|
||||||
|
| `star_rating_id` | NUMBER(10) UNIQUE | Natural key |
|
||||||
|
| `code` | NUMBER(1) | 1–5 |
|
||||||
|
| `description` | VARCHAR2(20) | e.g. `4 Star` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### DIM_HOTEL_CHAIN (SCD Type 1)
|
||||||
|
Chain name/code may be updated (e.g. corporate rebranding), but we do not need a historical record of chain name changes.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `hotel_chain_key` | NUMBER(10) PK | Surrogate (IDENTITY) |
|
||||||
|
| `hotel_chain_id` | NUMBER(10) UNIQUE | Natural key |
|
||||||
|
| `code` | VARCHAR2(10) | e.g. `HLT` |
|
||||||
|
| `name` | VARCHAR2(100) | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### DIM_HOTEL (SCD Type 2)
|
||||||
|
|
||||||
|
This is the most analytically significant dimension and the only one implemented as **Slowly Changing Dimension Type 2**.
|
||||||
|
|
||||||
|
**Why SCD Type 2 here?**
|
||||||
|
|
||||||
|
A hotel's star rating or chain affiliation can change over time — a property gets renovated and reclassified from 3★ to 4★, or switches from one international chain to another. These changes directly affect revenue analysis: a 3★ hotel charges different rates than a 4★ hotel, and grouping all historical bookings under the current star rating would produce misleading averages.
|
||||||
|
|
||||||
|
SCD Type 2 preserves history by creating a **new row** for each version of a hotel, while expiring the old row with an `expiry_date`. The fact table's `hotel_key` always points to the version that was active **at check-in date**, never to the current version if it changed.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `hotel_key` | NUMBER(10) PK | Surrogate (IDENTITY) |
|
||||||
|
| `source_hotel_id` | NUMBER(10) | Natural key from MySQL |
|
||||||
|
| `hotel_chain_key` | NUMBER(10) FK | NULL for independent hotels |
|
||||||
|
| `country_key` | NUMBER(10) FK | |
|
||||||
|
| `star_rating_key` | NUMBER(10) FK | |
|
||||||
|
| `code` | VARCHAR2(20) | |
|
||||||
|
| `name` | VARCHAR2(150) | |
|
||||||
|
| `city` | VARCHAR2(100) | |
|
||||||
|
| `effective_date` | DATE | When this version became active |
|
||||||
|
| `expiry_date` | DATE | When this version was superseded (NULL = current) |
|
||||||
|
| `is_current` | NUMBER(1) | 1 = current version |
|
||||||
|
|
||||||
|
**SCD2 example:**
|
||||||
|
|
||||||
|
| hotel_key | source_hotel_id | star_rating | effective_date | expiry_date | is_current |
|
||||||
|
|-----------|----------------|-------------|----------------|-------------|-----------|
|
||||||
|
| 1 | 42 | 3★ | 2022-01-01 | 2024-05-31 | 0 |
|
||||||
|
| 2 | 42 | 4★ | 2024-06-01 | NULL | 1 |
|
||||||
|
|
||||||
|
Bookings from 2022–2024 point to `hotel_key=1`, bookings from 2024 onward point to `hotel_key=2`. Revenue by star category remains historically correct.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### DIM_ROOM (SCD Type 1)
|
||||||
|
Room type is stable for our dataset. Updated via MERGE if room details ever change.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `room_key` | NUMBER(10) PK | Surrogate (IDENTITY) |
|
||||||
|
| `room_id` | NUMBER(10) UNIQUE | Natural key |
|
||||||
|
| `hotel_key` | NUMBER(10) FK | Points to current DIM_HOTEL version |
|
||||||
|
| `room_number` | VARCHAR2(10) | |
|
||||||
|
| `floor` | NUMBER(3) | |
|
||||||
|
| `room_type_code` | VARCHAR2(20) | e.g. `SUITE` |
|
||||||
|
| `room_type_desc` | VARCHAR2(100) | |
|
||||||
|
| `smoking_yn` | NUMBER(1) | |
|
||||||
|
| `standard_rate` | NUMBER(10,2) | Base rate from OLTP |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### DIM_GUEST (SCD Type 1)
|
||||||
|
Guest personal data (city, country) may change, but tracking historical addresses has no analytical value for this domain. MERGE (upsert) is used.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `guest_key` | NUMBER(10) PK | Surrogate (IDENTITY) |
|
||||||
|
| `guest_id` | NUMBER(10) UNIQUE | Natural key |
|
||||||
|
| `country_key` | NUMBER(10) FK | Home country |
|
||||||
|
| `name` | VARCHAR2(150) | |
|
||||||
|
| `city` | VARCHAR2(100) | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fact Table: FACT_ROOM_BOOKING
|
||||||
|
|
||||||
|
**Grain:** One row per room_booking — one specific room, for one stay.
|
||||||
|
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `fact_id` | NUMBER(10) PK | Surrogate (IDENTITY) |
|
||||||
|
| `source_rb_id` | NUMBER(10) UNIQUE | Natural key — used for idempotent incremental loads |
|
||||||
|
| `hotel_key` | NUMBER(10) FK | SCD2-resolved hotel version at check-in |
|
||||||
|
| `hotel_chain_key` | NUMBER(10) FK | Denormalized from DIM_HOTEL for convenience |
|
||||||
|
| `room_key` | NUMBER(10) FK | |
|
||||||
|
| `guest_key` | NUMBER(10) FK | |
|
||||||
|
| `country_key` | NUMBER(10) FK | Guest's country — denormalized |
|
||||||
|
| `star_rating_key` | NUMBER(10) FK | Denormalized from DIM_HOTEL for convenience |
|
||||||
|
| `checkin_date_key` | NUMBER(8) FK | YYYYMMDD |
|
||||||
|
| `checkout_date_key` | NUMBER(8) FK | YYYYMMDD |
|
||||||
|
| `booking_status` | VARCHAR2(20) | Degenerate dimension: confirmed/completed/cancelled/no_show |
|
||||||
|
| `nights_stayed` | NUMBER(4) | checkout − checkin in days |
|
||||||
|
| `nightly_rate` | NUMBER(10,2) | Rate per night at time of booking |
|
||||||
|
| `total_amount` | NUMBER(12,2) | `nightly_rate × nights_stayed` |
|
||||||
|
|
||||||
|
### Measures
|
||||||
|
|
||||||
|
| Measure | Type | Aggregation |
|
||||||
|
|---------|------|-------------|
|
||||||
|
| `nights_stayed` | Additive | SUM, AVG |
|
||||||
|
| `nightly_rate` | Semi-additive | AVG (not SUM — rate doesn't add across rooms meaningfully) |
|
||||||
|
| `total_amount` | Additive | SUM (main revenue measure) |
|
||||||
|
|
||||||
|
### Degenerate Dimensions
|
||||||
|
`booking_status` is stored directly on the fact row. Splitting it into a separate dimension table would add a table with only 4 rows and no other attributes — not worth the JOIN overhead.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ETL Control Tables
|
||||||
|
|
||||||
|
### ETL_WATERMARK
|
||||||
|
Tracks the highest `room_booking_id` already loaded into the fact table, enabling incremental loads without re-reading the entire source.
|
||||||
|
|
||||||
|
| Column | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `entity_name` | Logical entity name (e.g. `FACT_ROOM_BOOKING`) |
|
||||||
|
| `last_key` | Highest PK value loaded so far |
|
||||||
|
| `last_run_ts` | Timestamp of the last ETL run |
|
||||||
|
|
||||||
|
### STG_HOTEL
|
||||||
|
Staging table used by the SCD2 ETL process. NiFi loads raw hotel data from MySQL here, then SQL applies the expire-and-insert SCD2 logic in a single transaction. Truncated at the start of each ETL run.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Sample Analytical Queries
|
||||||
|
|
||||||
|
### Revenue by country and quarter
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
c.name AS country,
|
||||||
|
d.year,
|
||||||
|
d.quarter,
|
||||||
|
SUM(f.total_amount) AS revenue,
|
||||||
|
COUNT(*) AS room_nights
|
||||||
|
FROM FACT_ROOM_BOOKING f
|
||||||
|
JOIN DIM_DATE d ON d.date_key = f.checkin_date_key
|
||||||
|
JOIN DIM_GUEST g ON g.guest_key = f.guest_key
|
||||||
|
JOIN DIM_COUNTRY c ON c.country_key = g.country_key
|
||||||
|
WHERE f.booking_status = 'completed'
|
||||||
|
GROUP BY c.name, d.year, d.quarter
|
||||||
|
ORDER BY revenue DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Average revenue per star category (correct because of SCD2)
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
sr.code AS stars,
|
||||||
|
d.season,
|
||||||
|
AVG(f.nightly_rate) AS avg_nightly_rate,
|
||||||
|
SUM(f.total_amount) AS total_revenue
|
||||||
|
FROM FACT_ROOM_BOOKING f
|
||||||
|
JOIN DIM_HOTEL h ON h.hotel_key = f.hotel_key
|
||||||
|
JOIN DIM_STAR_RATING sr ON sr.star_rating_key = f.star_rating_key
|
||||||
|
JOIN DIM_DATE d ON d.date_key = f.checkin_date_key
|
||||||
|
GROUP BY sr.code, d.season
|
||||||
|
ORDER BY sr.code, d.season;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Top 10 cities by occupancy (room-nights)
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
h.city,
|
||||||
|
SUM(f.nights_stayed) AS room_nights,
|
||||||
|
SUM(f.total_amount) AS revenue
|
||||||
|
FROM FACT_ROOM_BOOKING f
|
||||||
|
JOIN DIM_HOTEL h ON h.hotel_key = f.hotel_key
|
||||||
|
WHERE f.booking_status IN ('completed','confirmed')
|
||||||
|
GROUP BY h.city
|
||||||
|
ORDER BY room_nights DESC
|
||||||
|
FETCH FIRST 10 ROWS ONLY;
|
||||||
|
```
|
||||||
181
docs/04-setup.md
Normal file
181
docs/04-setup.md
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
# Setup Guide
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
| Tool | Required for | Notes |
|
||||||
|
|------|-------------|-------|
|
||||||
|
| Docker or Podman | MySQL container | Use `--podman` flag on Linux |
|
||||||
|
| .NET 10 SDK | Data generator | `dotnet run file.cs` support |
|
||||||
|
| Apache NiFi | ETL | Running instance with Oracle + MySQL JDBC drivers |
|
||||||
|
| Oracle JDBC driver | NiFi | `ojdbc11.jar` in NiFi's lib directory |
|
||||||
|
| MySQL JDBC driver | NiFi | `mysql-connector-j-*.jar` in NiFi's lib directory |
|
||||||
|
| Oracle DB access | Data mart target | University lab credentials |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 1 — Start MySQL Container
|
||||||
|
|
||||||
|
**Linux / macOS (Docker):**
|
||||||
|
```bash
|
||||||
|
bash docker/start.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Linux / macOS (Podman):**
|
||||||
|
```bash
|
||||||
|
bash docker/start.sh --podman
|
||||||
|
```
|
||||||
|
|
||||||
|
**Windows (PowerShell):**
|
||||||
|
```powershell
|
||||||
|
.\docker\start.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
The script:
|
||||||
|
- Creates a named container `hotel-mysql` with a persistent data volume
|
||||||
|
- Mounts `sql/schema.sql` as an init script — all 13 tables are created automatically on first start
|
||||||
|
- Waits until MySQL is ready before exiting
|
||||||
|
|
||||||
|
**Connection details:**
|
||||||
|
```
|
||||||
|
Host: 127.0.0.1
|
||||||
|
Port: 13306
|
||||||
|
Database: hotel_reservations
|
||||||
|
User: root
|
||||||
|
Password: hotel2025root
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 2 — Generate OLTP Data
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet run generator/generate.cs
|
||||||
|
```
|
||||||
|
|
||||||
|
**Runtime:** ~3 minutes
|
||||||
|
**Output:** 635,000+ rows across 13 tables
|
||||||
|
|
||||||
|
The generator is deterministic (fixed seed `42`) — running it twice on an empty database produces the same data.
|
||||||
|
|
||||||
|
> **Important:** Run the generator only once on an empty database. If you need to restart, truncate all tables first (respecting FK order) or drop and recreate the container + volume.
|
||||||
|
|
||||||
|
### Quick table verification after generation:
|
||||||
|
```bash
|
||||||
|
# Docker
|
||||||
|
docker exec hotel-mysql mysql -uroot -photel2025root hotel_reservations \
|
||||||
|
-e "SELECT table_name, table_rows FROM information_schema.tables WHERE table_schema='hotel_reservations';"
|
||||||
|
|
||||||
|
# Podman
|
||||||
|
podman exec hotel-mysql mysql -uroot -photel2025root hotel_reservations \
|
||||||
|
-e "SELECT table_name, table_rows FROM information_schema.tables WHERE table_schema='hotel_reservations';"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 3 — Prepare Oracle Data Mart
|
||||||
|
|
||||||
|
Connect to the Oracle schema (university lab) and execute `sql/datamart_schema.sql`.
|
||||||
|
|
||||||
|
The script creates:
|
||||||
|
- `ETL_WATERMARK` (with initial row for `FACT_ROOM_BOOKING`)
|
||||||
|
- `STG_HOTEL` (staging)
|
||||||
|
- All 7 dimension tables
|
||||||
|
- `FACT_ROOM_BOOKING`
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Run in SQL*Plus or SQL Developer:
|
||||||
|
@datamart_schema.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 4 — Configure NiFi
|
||||||
|
|
||||||
|
### 4.1 Add JDBC drivers to NiFi
|
||||||
|
|
||||||
|
Copy the following JARs to `$NIFI_HOME/lib/` (or the NiFi extensions directory):
|
||||||
|
- `mysql-connector-j-8.x.jar`
|
||||||
|
- `ojdbc11.jar`
|
||||||
|
|
||||||
|
Restart NiFi after adding drivers.
|
||||||
|
|
||||||
|
### 4.2 Create Controller Services
|
||||||
|
|
||||||
|
In NiFi UI → Controller Settings → Controller Services:
|
||||||
|
|
||||||
|
**MySQL connection:**
|
||||||
|
- Type: `DBCPConnectionPool`
|
||||||
|
- Database Driver Class Name: `com.mysql.cj.jdbc.Driver`
|
||||||
|
- Database Connection URL: `jdbc:mysql://127.0.0.1:13306/hotel_reservations`
|
||||||
|
- Database User: `root`
|
||||||
|
- Password: `hotel2025root`
|
||||||
|
|
||||||
|
**Oracle connection:**
|
||||||
|
- Type: `DBCPConnectionPool`
|
||||||
|
- Database Driver Class Name: `oracle.jdbc.OracleDriver`
|
||||||
|
- Database Connection URL: `jdbc:oracle:thin:@<host>:1521:<sid>`
|
||||||
|
- Database User: `<your_schema>`
|
||||||
|
- Password: `<your_password>`
|
||||||
|
|
||||||
|
Enable both services.
|
||||||
|
|
||||||
|
### 4.3 Build Process Groups
|
||||||
|
|
||||||
|
Follow the detailed processor configuration in `docs/nifi-flow.md`.
|
||||||
|
|
||||||
|
**Recommended build order:**
|
||||||
|
1. PG-1: Date Dimension (simplest, test first)
|
||||||
|
2. PG-2: Static Dimensions (verify MERGE logic)
|
||||||
|
3. PG-3: DIM_HOTEL SCD2 (most complex — check staging table after run)
|
||||||
|
4. PG-4: DIM_GUEST SCD1
|
||||||
|
5. PG-5: Fact Incremental Load
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 5 — Run ETL
|
||||||
|
|
||||||
|
### First full load
|
||||||
|
|
||||||
|
1. Run **PG-1** (Date Dimension) manually — run once
|
||||||
|
2. Start **PG-2, PG-3, PG-4** — these are idempotent, safe to re-run
|
||||||
|
3. Start **PG-5** — runs incrementally; first run loads all 531k room_bookings
|
||||||
|
|
||||||
|
### Verify load
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Oracle
|
||||||
|
SELECT COUNT(*) FROM DIM_HOTEL; -- should be 200 (+ more after SCD2 changes)
|
||||||
|
SELECT COUNT(*) FROM DIM_GUEST; -- 100,000
|
||||||
|
SELECT COUNT(*) FROM FACT_ROOM_BOOKING; -- 531,382
|
||||||
|
SELECT last_key FROM ETL_WATERMARK WHERE entity_name = 'FACT_ROOM_BOOKING'; -- 531,382
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verify SCD2 is working
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Should show 1 current version per hotel on initial load
|
||||||
|
SELECT is_current, COUNT(*) FROM DIM_HOTEL GROUP BY is_current;
|
||||||
|
-- Expected: IS_CURRENT=1, COUNT=200
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stop / Restart
|
||||||
|
|
||||||
|
**Stop MySQL (preserves data):**
|
||||||
|
```bash
|
||||||
|
bash docker/stop.sh [--podman]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Restart MySQL:**
|
||||||
|
```bash
|
||||||
|
bash docker/start.sh [--podman]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Full reset (delete all data):**
|
||||||
|
```bash
|
||||||
|
bash docker/stop.sh --podman
|
||||||
|
podman volume rm hotel-mysql-data
|
||||||
|
bash docker/start.sh --podman
|
||||||
|
dotnet run generator/generate.cs
|
||||||
|
```
|
||||||
83
docs/05-conclusion.md
Normal file
83
docs/05-conclusion.md
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# Conclusion
|
||||||
|
|
||||||
|
## What Was Built
|
||||||
|
|
||||||
|
This project delivers a complete, working **Data Warehouse pipeline** for the Hotel Reservations domain:
|
||||||
|
|
||||||
|
| Layer | What was built | Scale |
|
||||||
|
|-------|---------------|-------|
|
||||||
|
| OLTP | MySQL 8.4, 13-table normalized schema | ~635,000 rows |
|
||||||
|
| Data generation | .NET 10 C# script, realistic seasonal distribution | 500K bookings in ~3 min |
|
||||||
|
| ETL | Apache NiFi, 5 process groups | full + incremental loads |
|
||||||
|
| Data Mart | Oracle star schema, SCD Type 2 on DIM_HOTEL | 1 fact + 6 dims |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Design Decisions
|
||||||
|
|
||||||
|
### Synthetic data generation instead of a Kaggle dataset
|
||||||
|
|
||||||
|
The decision to generate data rather than use a pre-existing dataset was deliberate. Publicly available hotel datasets are either too small (thousands of rows) or lack the normalized relational structure needed to demonstrate a realistic OLTP-to-DW pipeline. The generator produces statistically realistic data:
|
||||||
|
|
||||||
|
- Seasonal booking distribution (summer peak, winter trough)
|
||||||
|
- Realistic stay-length distribution (30% one-night stays)
|
||||||
|
- Varied status distribution (80% completed, 10% confirmed, 7% cancelled, 3% no-show)
|
||||||
|
- Revenue rates tied to actual seasonal pricing periods
|
||||||
|
|
||||||
|
### SCD Type 2 on DIM_HOTEL only
|
||||||
|
|
||||||
|
SCD Type 2 adds operational complexity — it requires staging tables, a two-phase SQL update, and SCD2-aware fact inserts. Applying it to every dimension would make the ETL unnecessarily complex for the analytical benefit gained.
|
||||||
|
|
||||||
|
DIM_HOTEL is the right candidate because:
|
||||||
|
- Star rating changes (3★→4★ after renovation) directly affect revenue benchmarks
|
||||||
|
- Chain affiliation changes (hotel joins or leaves a franchise) affect chain-level reporting
|
||||||
|
- Tracking these historically is the core value proposition of dimensional modelling
|
||||||
|
|
||||||
|
Guests, countries, room types, and hotel chains all change rarely or in ways that don't affect historical analysis — SCD Type 1 (overwrite) is appropriate.
|
||||||
|
|
||||||
|
### Watermark-based incremental fact loading
|
||||||
|
|
||||||
|
The fact table uses `source_rb_id` (the MySQL `room_booking_id`) as a natural key and applies a `NOT EXISTS` guard on every insert. Combined with the `ETL_WATERMARK` table, this makes PG-5 both **incremental** (only processes new rows) and **idempotent** (safe to re-run without creating duplicates). This pattern is production-standard and would scale cleanly to a real operational system.
|
||||||
|
|
||||||
|
### Integer date keys in DIM_DATE
|
||||||
|
|
||||||
|
`date_key` is stored as `NUMBER(8)` in YYYYMMDD format rather than a FK to a DATE column. This allows:
|
||||||
|
- Fast range predicates: `WHERE checkin_date_key BETWEEN 20240601 AND 20240831`
|
||||||
|
- No JOIN to get the date value when it's used directly in GROUP BY
|
||||||
|
- Human-readable values in query results without formatting
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Analytical Capabilities
|
||||||
|
|
||||||
|
The data mart enables the following categories of OLAP queries:
|
||||||
|
|
||||||
|
**Revenue analysis:**
|
||||||
|
- Total revenue by country, city, hotel chain, star category
|
||||||
|
- Revenue trend over time (monthly, quarterly, yearly)
|
||||||
|
- Revenue split by booking status and room type
|
||||||
|
|
||||||
|
**Occupancy analysis:**
|
||||||
|
- Room-nights sold per hotel, per season
|
||||||
|
- Average stay duration by guest country
|
||||||
|
- Cancellation rates by period and hotel category
|
||||||
|
|
||||||
|
**SCD2-specific analysis:**
|
||||||
|
- Compare revenue performance of hotels before and after star rating upgrade
|
||||||
|
- Identify which hotel version (chain affiliation) was more profitable
|
||||||
|
|
||||||
|
**Guest origin analysis:**
|
||||||
|
- Which countries generate the most bookings and revenue
|
||||||
|
- Cross-country booking patterns (guest country vs hotel country)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Limitations and Possible Extensions
|
||||||
|
|
||||||
|
| Limitation | Possible extension |
|
||||||
|
|------------|-------------------|
|
||||||
|
| Static OLTP data (no live updates) | Add a NiFi timer to simulate ongoing bookings |
|
||||||
|
| No SCD2 on DIM_ROOM | Add room type tracking for renovation analysis |
|
||||||
|
| Single fact table | Add a second fact table for daily hotel occupancy (snapshot fact) |
|
||||||
|
| No data quality checks in NiFi | Add RouteOnAttribute + dead-letter queue for failed records |
|
||||||
|
| Oracle target is university lab | Package with Oracle XE Docker container for self-contained demo |
|
||||||
451
docs/nifi-flow.md
Normal file
451
docs/nifi-flow.md
Normal file
@@ -0,0 +1,451 @@
|
|||||||
|
# NiFi ETL Flow — Hotel Reservations Data Mart
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The flow moves data from **MySQL 8.4 OLTP** (source) into **Oracle Data Mart** (target).
|
||||||
|
It is organized into **5 Process Groups** that run in sequence, controlled by a top-level scheduler.
|
||||||
|
|
||||||
|
```
|
||||||
|
[PG-1: Date Dim] → [PG-2: Static Dims] → [PG-3: SCD2 Hotel Dim] → [PG-4: SCD1 Guest] → [PG-5: Fact (incremental)]
|
||||||
|
```
|
||||||
|
|
||||||
|
Each PG has a single **Input Port** and **Output Port** so the orchestrator can chain them with connections.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Controller Services (shared by all PGs)
|
||||||
|
|
||||||
|
| Name | Type | Config |
|
||||||
|
|------|------|--------|
|
||||||
|
| `MySQL_DBCPService` | DBCPConnectionPool | Driver: `com.mysql.cj.jdbc.Driver`; URL: `jdbc:mysql://127.0.0.1:13306/hotel_reservations`; User: `root`; Pwd: `hotel2025root` |
|
||||||
|
| `Oracle_DBCPService` | DBCPConnectionPool | Driver: `oracle.jdbc.OracleDriver`; URL: `jdbc:oracle:thin:@<host>:1521:<sid>`; User: `<schema>`; Pwd: `<pwd>` |
|
||||||
|
| `JsonReader` | JsonTreeReader | default settings |
|
||||||
|
| `JsonWriter` | JsonRecordSetWriter | default settings |
|
||||||
|
| `AvroReader` | AvroReader | default settings |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PG-1: Load Date Dimension
|
||||||
|
|
||||||
|
**Runs once** (or when extending the date range). Populates `DIM_DATE` for 2020–2030.
|
||||||
|
|
||||||
|
```
|
||||||
|
GenerateFlowFile → ExecuteScript → SplitJson → EvaluateJsonPath → PutSQL
|
||||||
|
```
|
||||||
|
|
||||||
|
### Processors
|
||||||
|
|
||||||
|
**GenerateFlowFile**
|
||||||
|
- Run Schedule: manual (run once via right-click → Run Once)
|
||||||
|
- Custom Text: `{}`
|
||||||
|
|
||||||
|
**ExecuteScript** (Groovy)
|
||||||
|
```groovy
|
||||||
|
import groovy.json.JsonOutput
|
||||||
|
import java.time.*
|
||||||
|
|
||||||
|
def rows = []
|
||||||
|
def d = LocalDate.of(2020, 1, 1)
|
||||||
|
def end = LocalDate.of(2030, 12, 31)
|
||||||
|
while (!d.isAfter(end)) {
|
||||||
|
def m = d.monthValue
|
||||||
|
def season = (m >= 6 && m <= 8) ? 'Peak'
|
||||||
|
: (m >= 3 && m <= 5) ? 'High'
|
||||||
|
: (m >= 9 && m <= 11) ? 'Autumn'
|
||||||
|
: 'Winter'
|
||||||
|
rows << [
|
||||||
|
date_key: d.format(java.time.format.DateTimeFormatter.ofPattern('yyyyMMdd')) as int,
|
||||||
|
full_date: d.toString(),
|
||||||
|
year: d.year,
|
||||||
|
quarter: ((m - 1) / 3 + 1) as int,
|
||||||
|
month: m,
|
||||||
|
month_name: d.month.toString().capitalize(),
|
||||||
|
week_number: d.get(java.time.temporal.WeekFields.ISO.weekOfYear()),
|
||||||
|
day_of_month: d.dayOfMonth,
|
||||||
|
day_name: d.dayOfWeek.toString().capitalize(),
|
||||||
|
is_weekend: (d.dayOfWeek.value >= 6) ? 1 : 0,
|
||||||
|
is_business_day: (d.dayOfWeek.value <= 5) ? 1 : 0,
|
||||||
|
season: season
|
||||||
|
]
|
||||||
|
d = d.plusDays(1)
|
||||||
|
}
|
||||||
|
def ff = session.create()
|
||||||
|
ff = session.write(ff, { out -> out.write(JsonOutput.toJson(rows).bytes) } as OutputStreamCallback)
|
||||||
|
ff = session.putAttribute(ff, 'mime.type', 'application/json')
|
||||||
|
session.transfer(ff, REL_SUCCESS)
|
||||||
|
```
|
||||||
|
|
||||||
|
**SplitJson**
|
||||||
|
- JsonPath Expression: `$.*`
|
||||||
|
|
||||||
|
**EvaluateJsonPath**
|
||||||
|
- Destination: `flowfile-attribute`
|
||||||
|
- Attributes: `date_key`, `full_date`, `year`, `quarter`, `month`, `month_name`, `week_number`, `day_of_month`, `day_name`, `is_weekend`, `is_business_day`, `season`
|
||||||
|
|
||||||
|
**PutSQL**
|
||||||
|
- JDBC Connection Pool: `Oracle_DBCPService`
|
||||||
|
- SQL Statement:
|
||||||
|
```sql
|
||||||
|
INSERT INTO DIM_DATE (date_key, full_date, year, quarter, month, month_name,
|
||||||
|
week_number, day_of_month, day_name, is_weekend, is_business_day, season)
|
||||||
|
VALUES (${date_key}, TO_DATE('${full_date}','YYYY-MM-DD'), ${year}, ${quarter},
|
||||||
|
${month}, '${month_name}', ${week_number}, ${day_of_month},
|
||||||
|
'${day_name}', ${is_weekend}, ${is_business_day}, '${season}')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PG-2: Static Dimensions (SCD Type 1)
|
||||||
|
|
||||||
|
Loads `DIM_COUNTRY`, `DIM_STAR_RATING`, `DIM_HOTEL_CHAIN` from MySQL.
|
||||||
|
Uses **MERGE INTO** so the flow is idempotent — re-running it updates changed rows and inserts new ones.
|
||||||
|
|
||||||
|
Each sub-flow follows the same pattern:
|
||||||
|
|
||||||
|
```
|
||||||
|
ExecuteSQL(MySQL) → ConvertAvroToJSON → SplitJson → EvaluateJsonPath → PutSQL(MERGE)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2a — DIM_COUNTRY
|
||||||
|
|
||||||
|
**ExecuteSQL** — Connection Pool: `MySQL_DBCPService`
|
||||||
|
```sql
|
||||||
|
SELECT country_id, code, name, currency FROM country ORDER BY country_id
|
||||||
|
```
|
||||||
|
|
||||||
|
**EvaluateJsonPath** attributes: `country_id`, `code`, `name`, `currency`
|
||||||
|
|
||||||
|
**PutSQL**
|
||||||
|
```sql
|
||||||
|
MERGE INTO DIM_COUNTRY tgt
|
||||||
|
USING (SELECT 1 FROM DUAL) src ON (tgt.country_id = ${country_id})
|
||||||
|
WHEN MATCHED THEN
|
||||||
|
UPDATE SET tgt.code = '${code}', tgt.name = '${name}', tgt.currency = '${currency}'
|
||||||
|
WHEN NOT MATCHED THEN
|
||||||
|
INSERT (country_id, code, name, currency)
|
||||||
|
VALUES (${country_id}, '${code}', '${name}', '${currency}')
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2b — DIM_STAR_RATING
|
||||||
|
|
||||||
|
**ExecuteSQL**
|
||||||
|
```sql
|
||||||
|
SELECT star_rating_id, code, description FROM star_rating ORDER BY code
|
||||||
|
```
|
||||||
|
|
||||||
|
**PutSQL**
|
||||||
|
```sql
|
||||||
|
MERGE INTO DIM_STAR_RATING tgt
|
||||||
|
USING (SELECT 1 FROM DUAL) src ON (tgt.star_rating_id = ${star_rating_id})
|
||||||
|
WHEN MATCHED THEN
|
||||||
|
UPDATE SET tgt.code = ${code}, tgt.description = '${description}'
|
||||||
|
WHEN NOT MATCHED THEN
|
||||||
|
INSERT (star_rating_id, code, description)
|
||||||
|
VALUES (${star_rating_id}, ${code}, '${description}')
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2c — DIM_HOTEL_CHAIN
|
||||||
|
|
||||||
|
**ExecuteSQL**
|
||||||
|
```sql
|
||||||
|
SELECT hotel_chain_id, code, name FROM hotel_chain ORDER BY hotel_chain_id
|
||||||
|
```
|
||||||
|
|
||||||
|
**PutSQL**
|
||||||
|
```sql
|
||||||
|
MERGE INTO DIM_HOTEL_CHAIN tgt
|
||||||
|
USING (SELECT 1 FROM DUAL) src ON (tgt.hotel_chain_id = ${hotel_chain_id})
|
||||||
|
WHEN MATCHED THEN
|
||||||
|
UPDATE SET tgt.code = '${code}', tgt.name = '${name}'
|
||||||
|
WHEN NOT MATCHED THEN
|
||||||
|
INSERT (hotel_chain_id, code, name)
|
||||||
|
VALUES (${hotel_chain_id}, '${code}', '${name}')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PG-3: DIM_HOTEL — SCD Type 2
|
||||||
|
|
||||||
|
This is the analytically significant dimension. Hotels change star rating and chain affiliation over time (renovations, rebrandings). SCD Type 2 preserves history so reports can accurately show revenue by star category **at the time of booking**, not just today's category.
|
||||||
|
|
||||||
|
**Architecture:** NiFi stages raw data into `STG_HOTEL`, then an `ExecuteScript` runs the SCD2 SQL logic in a single Oracle transaction.
|
||||||
|
|
||||||
|
```
|
||||||
|
[Truncate STG] → [Load STG from MySQL] → [Apply SCD2 SQL]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step A: Truncate staging
|
||||||
|
|
||||||
|
**GenerateFlowFile** → **PutSQL**
|
||||||
|
```sql
|
||||||
|
TRUNCATE TABLE STG_HOTEL
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step B: Load staging from MySQL
|
||||||
|
|
||||||
|
**ExecuteSQL** — `MySQL_DBCPService`
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
h.hotel_id,
|
||||||
|
hc.code AS chain_code,
|
||||||
|
c.code AS country_code,
|
||||||
|
sr.code AS star_code,
|
||||||
|
h.code,
|
||||||
|
h.name,
|
||||||
|
h.city
|
||||||
|
FROM hotel h
|
||||||
|
JOIN country c ON c.country_id = h.country_id
|
||||||
|
JOIN star_rating sr ON sr.star_rating_id = h.star_rating_id
|
||||||
|
LEFT JOIN hotel_chain hc ON hc.hotel_chain_id = h.hotel_chain_id
|
||||||
|
ORDER BY h.hotel_id
|
||||||
|
```
|
||||||
|
|
||||||
|
**ConvertAvroToJSON** → **SplitJson** (`$.*`)
|
||||||
|
|
||||||
|
**EvaluateJsonPath** attributes: `hotel_id`, `chain_code`, `country_code`, `star_code`, `code`, `name`, `city`
|
||||||
|
|
||||||
|
**PutSQL** → `STG_HOTEL`
|
||||||
|
```sql
|
||||||
|
INSERT INTO STG_HOTEL (hotel_id, chain_code, country_code, star_code, code, name, city)
|
||||||
|
VALUES (${hotel_id}, NULLIF('${chain_code}',''), '${country_code}', ${star_code}, '${code}', '${name}', '${city}')
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step C: Apply SCD2 logic
|
||||||
|
|
||||||
|
**GenerateFlowFile** (runs after B finishes) → **ExecuteScript** (Groovy)
|
||||||
|
|
||||||
|
The Groovy script opens a JDBC connection and executes two SQL statements in one transaction:
|
||||||
|
|
||||||
|
```groovy
|
||||||
|
import java.sql.*
|
||||||
|
|
||||||
|
def conn = context.controllerServiceLookup
|
||||||
|
.getControllerService('Oracle_DBCPService_ID')
|
||||||
|
.getConnection()
|
||||||
|
conn.autoCommit = false
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. Expire records whose tracked attributes changed
|
||||||
|
conn.prepareStatement("""
|
||||||
|
UPDATE DIM_HOTEL dh
|
||||||
|
SET dh.expiry_date = TRUNC(SYSDATE) - 1,
|
||||||
|
dh.is_current = 0
|
||||||
|
WHERE dh.is_current = 1
|
||||||
|
AND EXISTS (
|
||||||
|
SELECT 1 FROM STG_HOTEL s
|
||||||
|
WHERE s.hotel_id = dh.source_hotel_id
|
||||||
|
AND (
|
||||||
|
NVL(s.chain_code,'~') != NVL((
|
||||||
|
SELECT hc.code FROM DIM_HOTEL_CHAIN hc
|
||||||
|
WHERE hc.hotel_chain_key = dh.hotel_chain_key),'~')
|
||||||
|
OR s.star_code != (
|
||||||
|
SELECT ds.code FROM DIM_STAR_RATING ds
|
||||||
|
WHERE ds.star_rating_key = dh.star_rating_key)
|
||||||
|
OR s.city != dh.city
|
||||||
|
)
|
||||||
|
)
|
||||||
|
""").executeUpdate()
|
||||||
|
|
||||||
|
// 2. Insert new version for changed hotels + insert brand-new hotels
|
||||||
|
conn.prepareStatement("""
|
||||||
|
INSERT INTO DIM_HOTEL (
|
||||||
|
source_hotel_id, hotel_chain_key, country_key, star_rating_key,
|
||||||
|
code, name, city, effective_date, expiry_date, is_current)
|
||||||
|
SELECT
|
||||||
|
s.hotel_id,
|
||||||
|
(SELECT hc.hotel_chain_key FROM DIM_HOTEL_CHAIN hc WHERE hc.code = s.chain_code),
|
||||||
|
(SELECT dc.country_key FROM DIM_COUNTRY dc WHERE dc.code = s.country_code),
|
||||||
|
(SELECT ds.star_rating_key FROM DIM_STAR_RATING ds WHERE ds.code = s.star_code),
|
||||||
|
s.code, s.name, s.city,
|
||||||
|
TRUNC(SYSDATE), NULL, 1
|
||||||
|
FROM STG_HOTEL s
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM DIM_HOTEL d
|
||||||
|
WHERE d.source_hotel_id = s.hotel_id
|
||||||
|
AND d.is_current = 1
|
||||||
|
)
|
||||||
|
""").executeUpdate()
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
} catch (Exception e) {
|
||||||
|
conn.rollback()
|
||||||
|
throw e
|
||||||
|
} finally {
|
||||||
|
conn.close()
|
||||||
|
}
|
||||||
|
def ff = session.create()
|
||||||
|
session.transfer(ff, REL_SUCCESS)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PG-4: DIM_GUEST — SCD Type 1
|
||||||
|
|
||||||
|
Guest personal data (city, country) can change without any analytical value in tracking the history. Plain MERGE/upsert is correct here.
|
||||||
|
|
||||||
|
```
|
||||||
|
ExecuteSQL(MySQL) → ConvertAvroToJSON → SplitJson → EvaluateJsonPath → PutSQL(MERGE)
|
||||||
|
```
|
||||||
|
|
||||||
|
**ExecuteSQL** — `MySQL_DBCPService`
|
||||||
|
```sql
|
||||||
|
SELECT g.guest_id, c.code AS country_code, g.name, g.city
|
||||||
|
FROM guest g
|
||||||
|
LEFT JOIN country c ON c.country_id = g.country_id
|
||||||
|
ORDER BY g.guest_id
|
||||||
|
```
|
||||||
|
|
||||||
|
**EvaluateJsonPath** attributes: `guest_id`, `country_code`, `name`, `city`
|
||||||
|
|
||||||
|
**PutSQL**
|
||||||
|
```sql
|
||||||
|
MERGE INTO DIM_GUEST tgt
|
||||||
|
USING (SELECT 1 FROM DUAL) src ON (tgt.guest_id = ${guest_id})
|
||||||
|
WHEN MATCHED THEN
|
||||||
|
UPDATE SET
|
||||||
|
tgt.country_key = (SELECT country_key FROM DIM_COUNTRY WHERE code = NULLIF('${country_code}','')),
|
||||||
|
tgt.name = '${name}',
|
||||||
|
tgt.city = NULLIF('${city}','')
|
||||||
|
WHEN NOT MATCHED THEN
|
||||||
|
INSERT (guest_id, country_key, name, city)
|
||||||
|
VALUES (
|
||||||
|
${guest_id},
|
||||||
|
(SELECT country_key FROM DIM_COUNTRY WHERE code = NULLIF('${country_code}','')),
|
||||||
|
'${name}',
|
||||||
|
NULLIF('${city}','')
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** DIM_ROOM is also SCD Type 1 — load it the same way as DIM_GUEST, joining `hotel_room` with `room_type` in MySQL and MERGEing into `DIM_ROOM` (surrogate key lookup via `source_hotel_id + IS_CURRENT=1` from DIM_HOTEL).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PG-5: FACT_ROOM_BOOKING — Incremental Load (Watermark)
|
||||||
|
|
||||||
|
The fact table is loaded **incrementally**: only `room_booking` rows with `room_booking_id` greater than the last loaded value are processed. The watermark is stored in `ETL_WATERMARK` in Oracle.
|
||||||
|
|
||||||
|
`source_rb_id` on `FACT_ROOM_BOOKING` has a UNIQUE constraint, so re-running is safe — duplicates are silently skipped.
|
||||||
|
|
||||||
|
```
|
||||||
|
[Read Watermark] → [ExecuteSQL MySQL] → [ConvertAvroToJSON] → [SplitJson]
|
||||||
|
→ [EvaluateJsonPath] → [PutSQL FACT] → [Update Watermark]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step A: Read watermark
|
||||||
|
|
||||||
|
**ExecuteSQL** — `Oracle_DBCPService`
|
||||||
|
```sql
|
||||||
|
SELECT last_key FROM ETL_WATERMARK WHERE entity_name = 'FACT_ROOM_BOOKING'
|
||||||
|
```
|
||||||
|
|
||||||
|
**ConvertAvroToJSON** → **EvaluateJsonPath**
|
||||||
|
- `watermark` ← `$.last_key`
|
||||||
|
|
||||||
|
### Step B: Load from MySQL
|
||||||
|
|
||||||
|
**ExecuteSQL** — `MySQL_DBCPService`
|
||||||
|
SQL Statement (use attribute `${watermark}`):
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
rb.room_booking_id,
|
||||||
|
rb.room_id,
|
||||||
|
rb.date_from,
|
||||||
|
rb.date_to,
|
||||||
|
rb.nightly_rate,
|
||||||
|
rb.total_amount,
|
||||||
|
b.guest_id,
|
||||||
|
b.status AS booking_status,
|
||||||
|
DATEDIFF(rb.date_to, rb.date_from) AS nights_stayed
|
||||||
|
FROM room_booking rb
|
||||||
|
JOIN booking b ON b.booking_id = rb.booking_id
|
||||||
|
WHERE rb.room_booking_id > ${watermark}
|
||||||
|
ORDER BY rb.room_booking_id
|
||||||
|
LIMIT 50000
|
||||||
|
```
|
||||||
|
|
||||||
|
> Set LIMIT to control batch size. Run PG-5 in a loop (using a Timer-driven GenerateFlowFile) until no rows come back.
|
||||||
|
|
||||||
|
### Step C: Split + extract attributes
|
||||||
|
|
||||||
|
**ConvertAvroToJSON** → **SplitJson** (`$.*`)
|
||||||
|
|
||||||
|
**EvaluateJsonPath** attributes:
|
||||||
|
`room_booking_id`, `room_id`, `guest_id`, `date_from`, `date_to`, `nightly_rate`, `total_amount`, `booking_status`, `nights_stayed`
|
||||||
|
|
||||||
|
### Step D: Insert into fact table
|
||||||
|
|
||||||
|
**PutSQL** — `Oracle_DBCPService`
|
||||||
|
```sql
|
||||||
|
INSERT INTO FACT_ROOM_BOOKING (
|
||||||
|
source_rb_id, hotel_key, hotel_chain_key, room_key, guest_key, country_key,
|
||||||
|
star_rating_key, checkin_date_key, checkout_date_key,
|
||||||
|
booking_status, nights_stayed, nightly_rate, total_amount)
|
||||||
|
SELECT
|
||||||
|
${room_booking_id},
|
||||||
|
dh.hotel_key,
|
||||||
|
dh.hotel_chain_key,
|
||||||
|
dr.room_key,
|
||||||
|
dg.guest_key,
|
||||||
|
dg.country_key,
|
||||||
|
dh.star_rating_key,
|
||||||
|
TO_NUMBER(TO_CHAR(TO_DATE('${date_from}','YYYY-MM-DD'), 'YYYYMMDD')),
|
||||||
|
TO_NUMBER(TO_CHAR(TO_DATE('${date_to}', 'YYYY-MM-DD'), 'YYYYMMDD')),
|
||||||
|
'${booking_status}',
|
||||||
|
${nights_stayed},
|
||||||
|
TO_NUMBER('${nightly_rate}', '9999990D99', 'NLS_NUMERIC_CHARACTERS=''.,'''),
|
||||||
|
TO_NUMBER('${total_amount}', '9999990D99', 'NLS_NUMERIC_CHARACTERS=''.,''')
|
||||||
|
FROM
|
||||||
|
DIM_ROOM dr,
|
||||||
|
DIM_GUEST dg,
|
||||||
|
DIM_HOTEL dh
|
||||||
|
WHERE
|
||||||
|
dr.room_id = ${room_id}
|
||||||
|
AND dg.guest_id = ${guest_id}
|
||||||
|
AND dh.hotel_key = dr.hotel_key
|
||||||
|
-- SCD2 lookup: find hotel version active at check-in date
|
||||||
|
AND dh.effective_date <= TO_DATE('${date_from}','YYYY-MM-DD')
|
||||||
|
AND (dh.expiry_date IS NULL OR dh.expiry_date > TO_DATE('${date_from}','YYYY-MM-DD'))
|
||||||
|
-- Idempotent: skip if already loaded
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT 1 FROM FACT_ROOM_BOOKING f WHERE f.source_rb_id = ${room_booking_id}
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
> The `DH.EFFECTIVE_DATE / EXPIRY_DATE` condition is the payoff of SCD Type 2: the fact row always references the hotel dimension version that was true **when the guest actually checked in**, not what the hotel looks like today.
|
||||||
|
|
||||||
|
**Ignore Errors** on PutSQL (route `failure` → funnel) — UNIQUE constraint violations on `source_rb_id` are expected and harmless on re-runs.
|
||||||
|
|
||||||
|
### Step E: Update watermark
|
||||||
|
|
||||||
|
After the PutSQL succeeds, update the watermark with the highest `room_booking_id` seen in this batch.
|
||||||
|
|
||||||
|
**UpdateAttribute**
|
||||||
|
- `max_rb_id` ← `${room_booking_id}` (NiFi Expression Language `max()` across the batch via a custom processor or MergeContent trick)
|
||||||
|
|
||||||
|
> Simplest approach: add a final **ExecuteSQL** that runs after the batch:
|
||||||
|
```sql
|
||||||
|
UPDATE ETL_WATERMARK
|
||||||
|
SET last_key = (SELECT MAX(source_rb_id) FROM FACT_ROOM_BOOKING),
|
||||||
|
last_run_ts = SYSTIMESTAMP
|
||||||
|
WHERE entity_name = 'FACT_ROOM_BOOKING'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Execution Order & Scheduling
|
||||||
|
|
||||||
|
| PG | Trigger | Frequency |
|
||||||
|
|----|---------|-----------|
|
||||||
|
| PG-1 (Date Dim) | Manual (run once) | — |
|
||||||
|
| PG-2 (Static Dims) | Timer — 24h | Daily |
|
||||||
|
| PG-3 (DIM_HOTEL SCD2) | Timer — 24h | Daily, after PG-2 |
|
||||||
|
| PG-4 (DIM_GUEST SCD1) | Timer — 24h | Daily, after PG-3 |
|
||||||
|
| PG-5 (Fact incremental) | Timer — 1h | Hourly |
|
||||||
|
|
||||||
|
Chain PG-2 → PG-3 → PG-4 by connecting each PG's Output Port to the next PG's Input Port via a **success** relationship.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Why SCD Type 2 for DIM_HOTEL?
|
||||||
|
|
||||||
|
A hotel being upgraded from 3★ to 4★ changes its rate tier going forward. If we just overwrite the dimension (SCD1), all historical bookings would suddenly appear to have been made in a 4★ hotel — inflating average revenue per star category in reports. SCD2 preserves the correct picture: every fact row points to the exact hotel version that was true at check-in.
|
||||||
540
generator/generate.cs
Normal file
540
generator/generate.cs
Normal file
@@ -0,0 +1,540 @@
|
|||||||
|
#:package MySqlConnector@2.3.7
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
|
using System.Globalization;
|
||||||
|
using MySqlConnector;
|
||||||
|
|
||||||
|
// ── Config ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
const string DSN = "Server=127.0.0.1;Port=13306;Database=hotel_reservations;Uid=root;Pwd=hotel2025root;AllowLoadLocalInfile=true;";
|
||||||
|
const int HOTEL_COUNT = 200;
|
||||||
|
const int GUEST_COUNT = 100_000;
|
||||||
|
const int BOOKING_COUNT = 500_000;
|
||||||
|
const int BATCH = 500;
|
||||||
|
const int SEED = 42;
|
||||||
|
|
||||||
|
var rng = new Random(SEED);
|
||||||
|
|
||||||
|
// ── DB helpers ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
await using var conn = new MySqlConnection(DSN);
|
||||||
|
await conn.OpenAsync();
|
||||||
|
Console.WriteLine("Connected.");
|
||||||
|
await new MySqlCommand("SET foreign_key_checks=0, unique_checks=0", conn).ExecuteNonQueryAsync();
|
||||||
|
|
||||||
|
async Task Exec(string sql)
|
||||||
|
{
|
||||||
|
await using var cmd = new MySqlCommand(sql, conn);
|
||||||
|
cmd.CommandTimeout = 300;
|
||||||
|
await cmd.ExecuteNonQueryAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<long> ExecScalar(string sql)
|
||||||
|
{
|
||||||
|
await using var cmd = new MySqlCommand(sql, conn);
|
||||||
|
return Convert.ToInt64(await cmd.ExecuteScalarAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bulk insert: builds a single INSERT ... VALUES (...),(...),...
|
||||||
|
async Task BulkInsert(string table, string columns, List<string> valueTuples)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < valueTuples.Count; i += BATCH)
|
||||||
|
{
|
||||||
|
var batch = valueTuples.Skip(i).Take(BATCH);
|
||||||
|
await Exec($"INSERT INTO {table} ({columns}) VALUES {string.Join(',', batch)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string S(string? s) => s == null ? "NULL" : $"'{s.Replace("'", "''")}'";
|
||||||
|
string N(object? n) => n == null ? "NULL" : (n is IFormattable f) ? f.ToString(null, CultureInfo.InvariantCulture) : n.ToString()!;
|
||||||
|
string D(DateTime d) => $"'{d:yyyy-MM-dd}'";
|
||||||
|
string DT(DateTime d) => $"'{d:yyyy-MM-dd HH:mm:ss}'";
|
||||||
|
|
||||||
|
// ── Reference data ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
// ── 1. hotel_chain ────────────────────────────────────────────────────────────
|
||||||
|
Console.WriteLine("[1/8] hotel_chain");
|
||||||
|
|
||||||
|
var chains = new (string Code, string Name)[]
|
||||||
|
{
|
||||||
|
("HLT", "Hilton Worldwide"),
|
||||||
|
("MRT", "Marriott International"),
|
||||||
|
("HYT", "Hyatt Hotels Corporation"),
|
||||||
|
("IHG", "InterContinental Hotels Group"),
|
||||||
|
("WYN", "Wyndham Hotels & Resorts"),
|
||||||
|
("ACC", "Accor"),
|
||||||
|
("BW", "Best Western Hotels"),
|
||||||
|
("RAD", "Radisson Hotels"),
|
||||||
|
("MEL", "Meliá Hotels International"),
|
||||||
|
("NH", "NH Hotel Group"),
|
||||||
|
};
|
||||||
|
|
||||||
|
await BulkInsert("hotel_chain", "code, name",
|
||||||
|
chains.Select(c => $"({S(c.Code)},{S(c.Name)})").ToList());
|
||||||
|
|
||||||
|
var chainIds = new Dictionary<string, int>();
|
||||||
|
{
|
||||||
|
await using var cmd = new MySqlCommand("SELECT hotel_chain_id, code FROM hotel_chain", conn);
|
||||||
|
await using var r = await cmd.ExecuteReaderAsync();
|
||||||
|
while (await r.ReadAsync()) chainIds[r.GetString(1)] = r.GetInt32(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 2. country ────────────────────────────────────────────────────────────────
|
||||||
|
Console.WriteLine("[2/8] country");
|
||||||
|
|
||||||
|
var countries = new (string Code, string Name, string Currency)[]
|
||||||
|
{
|
||||||
|
("GB","United Kingdom","GBP"), ("FR","France","EUR"), ("DE","Germany","EUR"),
|
||||||
|
("ES","Spain","EUR"), ("IT","Italy","EUR"), ("PT","Portugal","EUR"),
|
||||||
|
("NL","Netherlands","EUR"), ("BE","Belgium","EUR"), ("AT","Austria","EUR"),
|
||||||
|
("CH","Switzerland","CHF"), ("SE","Sweden","SEK"), ("NO","Norway","NOK"),
|
||||||
|
("DK","Denmark","DKK"), ("PL","Poland","PLN"), ("CZ","Czech Republic","CZK"),
|
||||||
|
("HU","Hungary","HUF"), ("HR","Croatia","EUR"), ("GR","Greece","EUR"),
|
||||||
|
("TR","Turkey","TRY"), ("US","United States","USD"), ("CA","Canada","CAD"),
|
||||||
|
("MX","Mexico","MXN"), ("BR","Brazil","BRL"), ("AR","Argentina","ARS"),
|
||||||
|
("AU","Australia","AUD"), ("NZ","New Zealand","NZD"), ("JP","Japan","JPY"),
|
||||||
|
("CN","China","CNY"), ("KR","South Korea","KRW"), ("SG","Singapore","SGD"),
|
||||||
|
("TH","Thailand","THB"), ("AE","United Arab Emirates","AED"),
|
||||||
|
("SA","Saudi Arabia","SAR"), ("EG","Egypt","EGP"), ("ZA","South Africa","ZAR"),
|
||||||
|
("IN","India","INR"), ("MA","Morocco","MAD"), ("TN","Tunisia","TND"),
|
||||||
|
("ID","Indonesia","IDR"), ("MY","Malaysia","MYR"),
|
||||||
|
};
|
||||||
|
|
||||||
|
await BulkInsert("country", "code, name, currency",
|
||||||
|
countries.Select(c => $"({S(c.Code)},{S(c.Name)},{S(c.Currency)})").ToList());
|
||||||
|
|
||||||
|
var countryIds = new Dictionary<string, int>();
|
||||||
|
{
|
||||||
|
await using var cmd = new MySqlCommand("SELECT country_id, code FROM country", conn);
|
||||||
|
await using var r = await cmd.ExecuteReaderAsync();
|
||||||
|
while (await r.ReadAsync()) countryIds[r.GetString(1)] = r.GetInt32(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 3. star_rating ────────────────────────────────────────────────────────────
|
||||||
|
Console.WriteLine("[3/8] star_rating");
|
||||||
|
|
||||||
|
await BulkInsert("star_rating", "code, description",
|
||||||
|
Enumerable.Range(1, 5).Select(i => $"({i},{S(i + " Star")})").ToList());
|
||||||
|
|
||||||
|
var starIds = new Dictionary<int, int>();
|
||||||
|
{
|
||||||
|
await using var cmd = new MySqlCommand("SELECT star_rating_id, code FROM star_rating", conn);
|
||||||
|
await using var r = await cmd.ExecuteReaderAsync();
|
||||||
|
while (await r.ReadAsync()) starIds[r.GetInt32(1)] = r.GetInt32(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 4. hotel_characteristic ───────────────────────────────────────────────────
|
||||||
|
Console.WriteLine("[4/8] hotel_characteristic");
|
||||||
|
|
||||||
|
var characteristics = new (string Code, string Desc)[]
|
||||||
|
{
|
||||||
|
("WIFI", "Free WiFi"), ("POOL", "Swimming Pool"),
|
||||||
|
("GYM", "Fitness Center"), ("SPA", "Spa & Wellness"),
|
||||||
|
("RESTAURANT", "On-site Restaurant"), ("BAR", "Hotel Bar"),
|
||||||
|
("PARKING", "Free Parking"), ("VALET", "Valet Parking"),
|
||||||
|
("CONFERENCE", "Conference Rooms"), ("SHUTTLE", "Airport Shuttle"),
|
||||||
|
("ROOM_SVC", "Room Service"), ("PETS", "Pet Friendly"),
|
||||||
|
};
|
||||||
|
|
||||||
|
await BulkInsert("hotel_characteristic", "code, description",
|
||||||
|
characteristics.Select(c => $"({S(c.Code)},{S(c.Desc)})").ToList());
|
||||||
|
|
||||||
|
var charIds = new Dictionary<string, int>();
|
||||||
|
{
|
||||||
|
await using var cmd = new MySqlCommand("SELECT characteristic_id, code FROM hotel_characteristic", conn);
|
||||||
|
await using var r = await cmd.ExecuteReaderAsync();
|
||||||
|
while (await r.ReadAsync()) charIds[r.GetString(1)] = r.GetInt32(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 5. room_type + rate_period + period_room_rate ─────────────────────────────
|
||||||
|
Console.WriteLine("[5/8] room_type / rate_period / period_room_rate");
|
||||||
|
|
||||||
|
var roomTypes = new (string Code, string Desc, decimal BaseRate, bool Smoking)[]
|
||||||
|
{
|
||||||
|
("SINGLE", "Single Room", 80m, false),
|
||||||
|
("DOUBLE", "Double Room", 120m, false),
|
||||||
|
("TWIN", "Twin Room", 115m, false),
|
||||||
|
("DELUXE", "Deluxe Double", 180m, false),
|
||||||
|
("SUITE", "Junior Suite", 280m, false),
|
||||||
|
("EXEC", "Executive Suite", 450m, false),
|
||||||
|
("FAMILY", "Family Room", 200m, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
await BulkInsert("room_type", "code, description, standard_rate, smoking_yn",
|
||||||
|
roomTypes.Select(rt => $"({S(rt.Code)},{S(rt.Desc)},{N(rt.BaseRate)},0)").ToList());
|
||||||
|
|
||||||
|
var roomTypeIds = new Dictionary<string, int>();
|
||||||
|
{
|
||||||
|
await using var cmd = new MySqlCommand("SELECT room_type_id, code FROM room_type", conn);
|
||||||
|
await using var r = await cmd.ExecuteReaderAsync();
|
||||||
|
while (await r.ReadAsync()) roomTypeIds[r.GetString(1)] = r.GetInt32(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seasons: month → multiplier
|
||||||
|
var ratePeriods = new (string Code, string Desc, int MonthFrom, int MonthTo, decimal Multiplier)[]
|
||||||
|
{
|
||||||
|
("PEAK", "Peak Season (Jun-Aug)", 6, 8, 1.5m),
|
||||||
|
("HIGH", "High Season (Mar-May)", 3, 5, 1.2m),
|
||||||
|
("AUTUMN", "Autumn Season (Sep-Nov)", 9, 11, 1.1m),
|
||||||
|
("WINTER", "Winter Season (Dec-Feb)", 12, 2, 0.9m),
|
||||||
|
};
|
||||||
|
|
||||||
|
await BulkInsert("rate_period", "code, description, month_from, month_to",
|
||||||
|
ratePeriods.Select(rp => $"({S(rp.Code)},{S(rp.Desc)},{rp.MonthFrom},{rp.MonthTo})").ToList());
|
||||||
|
|
||||||
|
var ratePeriodIds = new Dictionary<string, int>();
|
||||||
|
{
|
||||||
|
await using var cmd = new MySqlCommand("SELECT rate_period_id, code FROM rate_period", conn);
|
||||||
|
await using var r = await cmd.ExecuteReaderAsync();
|
||||||
|
while (await r.ReadAsync()) ratePeriodIds[r.GetString(1)] = r.GetInt32(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// period_room_rate: rate = base_rate * season_multiplier
|
||||||
|
var prrRows = new List<string>();
|
||||||
|
foreach (var rt in roomTypes)
|
||||||
|
foreach (var rp in ratePeriods)
|
||||||
|
{
|
||||||
|
var rate = Math.Round(rt.BaseRate * rp.Multiplier, 2);
|
||||||
|
prrRows.Add($"({roomTypeIds[rt.Code]},{ratePeriodIds[rp.Code]},{N(rate)})");
|
||||||
|
}
|
||||||
|
await BulkInsert("period_room_rate", "room_type_id, rate_period_id, rate", prrRows);
|
||||||
|
|
||||||
|
// Build month → rate lookup in memory
|
||||||
|
var monthToRatePeriodId = new Dictionary<int, int>();
|
||||||
|
foreach (var rp in ratePeriods)
|
||||||
|
{
|
||||||
|
if (rp.MonthFrom <= rp.MonthTo)
|
||||||
|
for (int m = rp.MonthFrom; m <= rp.MonthTo; m++)
|
||||||
|
monthToRatePeriodId[m] = ratePeriodIds[rp.Code];
|
||||||
|
else // wraps year (Dec-Feb)
|
||||||
|
{
|
||||||
|
for (int m = rp.MonthFrom; m <= 12; m++) monthToRatePeriodId[m] = ratePeriodIds[rp.Code];
|
||||||
|
for (int m = 1; m <= rp.MonthTo; m++) monthToRatePeriodId[m] = ratePeriodIds[rp.Code];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build (room_type_id, rate_period_id) → rate lookup
|
||||||
|
var rateMap = new Dictionary<(int, int), decimal>();
|
||||||
|
foreach (var rt in roomTypes)
|
||||||
|
foreach (var rp in ratePeriods)
|
||||||
|
rateMap[(roomTypeIds[rt.Code], ratePeriodIds[rp.Code])] =
|
||||||
|
Math.Round(rt.BaseRate * rp.Multiplier, 2);
|
||||||
|
|
||||||
|
// ── 6. hotel + hotel_room + hotel_hotel_characteristic ────────────────────────
|
||||||
|
Console.WriteLine("[6/8] hotel / hotel_room / hotel_hotel_characteristic");
|
||||||
|
|
||||||
|
var hotelCities = new (string City, string Country)[]
|
||||||
|
{
|
||||||
|
("London","GB"), ("Manchester","GB"), ("Edinburgh","GB"),
|
||||||
|
("Paris","FR"), ("Lyon","FR"), ("Nice","FR"),
|
||||||
|
("Berlin","DE"), ("Munich","DE"), ("Hamburg","DE"),
|
||||||
|
("Madrid","ES"), ("Barcelona","ES"), ("Seville","ES"),
|
||||||
|
("Rome","IT"), ("Milan","IT"), ("Florence","IT"),
|
||||||
|
("Lisbon","PT"), ("Porto","PT"), ("Amsterdam","NL"),
|
||||||
|
("Vienna","AT"), ("Zurich","CH"), ("Geneva","CH"),
|
||||||
|
("Stockholm","SE"), ("Oslo","NO"), ("Copenhagen","DK"),
|
||||||
|
("Warsaw","PL"), ("Prague","CZ"), ("Budapest","HU"),
|
||||||
|
("Athens","GR"), ("Istanbul","TR"), ("New York","US"),
|
||||||
|
("Los Angeles","US"), ("Miami","US"), ("Chicago","US"),
|
||||||
|
("Toronto","CA"), ("Vancouver","CA"), ("Sydney","AU"),
|
||||||
|
("Melbourne","AU"), ("Tokyo","JP"), ("Osaka","JP"),
|
||||||
|
("Singapore","SG"), ("Bangkok","TH"), ("Dubai","AE"),
|
||||||
|
("Mumbai","IN"), ("Cape Town","ZA"), ("Marrakech","MA"),
|
||||||
|
("Cairo","EG"), ("Cancun","MX"), ("Rio de Janeiro","BR"),
|
||||||
|
("Seoul","KR"), ("Kuala Lumpur","MY"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Star rating distribution: 3★ most common, 5★ rarest
|
||||||
|
int[] starWeights = [0, 5, 10, 40, 30, 15]; // index = star, value = weight
|
||||||
|
int PickStar()
|
||||||
|
{
|
||||||
|
int roll = rng.Next(100);
|
||||||
|
int cum = 0;
|
||||||
|
for (int s = 1; s <= 5; s++) { cum += starWeights[s]; if (roll < cum) return s; }
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hotelRows = new List<string>();
|
||||||
|
var roomRows = new List<string>();
|
||||||
|
var hotelCharRows = new List<string>();
|
||||||
|
var charCodes = characteristics.Select(c => c.Code).ToArray();
|
||||||
|
|
||||||
|
// Track room_type per hotel_room for later rate lookups (in-memory)
|
||||||
|
// hotel_room gets an auto-increment ID; we'll load them after insert
|
||||||
|
// So store: hotel index → list of (room_number, room_type_code)
|
||||||
|
var hotelRoomTypes = new List<(int hotelIndex, string roomNumber, string roomTypeCode)>();
|
||||||
|
|
||||||
|
string[] streetNames = ["Main St","Park Ave","King Rd","Grand Blvd","Lake Dr",
|
||||||
|
"Ocean Blvd","Hill Rd","Market St","Central Ave","Palace Rd"];
|
||||||
|
|
||||||
|
for (int h = 0; h < HOTEL_COUNT; h++)
|
||||||
|
{
|
||||||
|
var (city, ctryCode) = hotelCities[h % hotelCities.Length];
|
||||||
|
int chainIndex = rng.Next(chains.Length);
|
||||||
|
// 20% of hotels are independent (no chain)
|
||||||
|
int? chainId = rng.Next(100) < 20 ? null : chainIds[chains[chainIndex].Code];
|
||||||
|
int star = PickStar();
|
||||||
|
int starId = starIds[star];
|
||||||
|
int ctryId = countryIds[ctryCode];
|
||||||
|
|
||||||
|
string code = $"HTL{h+1:D4}";
|
||||||
|
string name = chainId == null
|
||||||
|
? $"The {city} Hotel"
|
||||||
|
: $"{chains[chainIndex].Name.Split(' ')[0]} {city}";
|
||||||
|
string addr = $"{rng.Next(1, 200)} {streetNames[rng.Next(streetNames.Length)]}";
|
||||||
|
string url = $"https://www.{code.ToLower()}.example.com";
|
||||||
|
|
||||||
|
hotelRows.Add($"({N(chainId)},{ctryId},{starId},{S(code)},{S(name)},{S(addr)},{S("00000")},{S(city)},{S(url)})");
|
||||||
|
|
||||||
|
// Characteristics: 5★ gets all, lower stars get fewer
|
||||||
|
int charCount = star switch { 5 => 11, 4 => 8, 3 => 6, 2 => 4, _ => 3 };
|
||||||
|
var shuffled = charCodes.OrderBy(_ => rng.Next()).Take(charCount).ToArray();
|
||||||
|
// Store char codes for later — we need hotel_id from DB first
|
||||||
|
// Mark with h as placeholder; we'll match after insert
|
||||||
|
foreach (var cc in shuffled)
|
||||||
|
hotelCharRows.Add($"__HOTEL_{h}__,{charIds[cc]}");
|
||||||
|
|
||||||
|
// Rooms: more rooms for higher star hotels
|
||||||
|
int roomCount = star switch { 5 => rng.Next(40, 60), 4 => rng.Next(25, 40),
|
||||||
|
3 => rng.Next(15, 25), 2 => rng.Next(8, 15), _ => rng.Next(5, 10) };
|
||||||
|
|
||||||
|
// Room type distribution per star rating
|
||||||
|
string[] typePool = star switch
|
||||||
|
{
|
||||||
|
5 => ["DOUBLE","DOUBLE","DELUXE","DELUXE","SUITE","SUITE","EXEC","FAMILY"],
|
||||||
|
4 => ["SINGLE","DOUBLE","DOUBLE","DELUXE","SUITE","FAMILY"],
|
||||||
|
3 => ["SINGLE","SINGLE","DOUBLE","DOUBLE","TWIN","FAMILY"],
|
||||||
|
2 => ["SINGLE","SINGLE","DOUBLE","TWIN"],
|
||||||
|
_ => ["SINGLE","SINGLE","DOUBLE"],
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int r = 0; r < roomCount; r++)
|
||||||
|
{
|
||||||
|
int floor = r / 10 + 1;
|
||||||
|
string rnum = $"{floor}{(r % 10 + 1):D2}";
|
||||||
|
string rtype = typePool[rng.Next(typePool.Length)];
|
||||||
|
// Store for later (after we get real hotel IDs from DB)
|
||||||
|
hotelRoomTypes.Add((h, rnum, rtype));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await BulkInsert("hotel",
|
||||||
|
"hotel_chain_id, country_id, star_rating_id, code, name, address, postcode, city, url",
|
||||||
|
hotelRows);
|
||||||
|
|
||||||
|
// Load hotel IDs in order
|
||||||
|
var hotelIds = new List<int>();
|
||||||
|
{
|
||||||
|
await using var cmd = new MySqlCommand("SELECT hotel_id FROM hotel ORDER BY hotel_id", conn);
|
||||||
|
await using var r = await cmd.ExecuteReaderAsync();
|
||||||
|
while (await r.ReadAsync()) hotelIds.Add(r.GetInt32(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now build hotel_room rows with real hotel IDs
|
||||||
|
foreach (var (hIdx, rnum, rtype) in hotelRoomTypes)
|
||||||
|
roomRows.Add($"({hotelIds[hIdx]},{roomTypeIds[rtype]},{S(rnum)},{rnum[0] - '0'})");
|
||||||
|
|
||||||
|
await BulkInsert("hotel_room", "hotel_id, room_type_id, room_number, floor", roomRows);
|
||||||
|
|
||||||
|
// hotel_hotel_characteristic — replace placeholder with real hotel_id
|
||||||
|
var hhcRows = hotelCharRows
|
||||||
|
.Select(row => {
|
||||||
|
var parts = row.Split(',');
|
||||||
|
var hIdx = int.Parse(parts[0].Replace("__HOTEL_", "").Replace("__", ""));
|
||||||
|
var charId = parts[1];
|
||||||
|
return $"({hotelIds[hIdx]},{charId})";
|
||||||
|
})
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
await BulkInsert("hotel_hotel_characteristic", "hotel_id, characteristic_id", hhcRows);
|
||||||
|
|
||||||
|
// Load rooms into memory: hotel_id → list of (room_id, room_type_id)
|
||||||
|
var hotelRooms = new Dictionary<int, List<(int RoomId, int RoomTypeId)>>();
|
||||||
|
{
|
||||||
|
await using var cmd = new MySqlCommand("SELECT room_id, hotel_id, room_type_id FROM hotel_room", conn);
|
||||||
|
await using var r = await cmd.ExecuteReaderAsync();
|
||||||
|
while (await r.ReadAsync())
|
||||||
|
{
|
||||||
|
int rid = r.GetInt32(0), hid = r.GetInt32(1), rtid = r.GetInt32(2);
|
||||||
|
if (!hotelRooms.ContainsKey(hid)) hotelRooms[hid] = [];
|
||||||
|
hotelRooms[hid].Add((rid, rtid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 7. guest ──────────────────────────────────────────────────────────────────
|
||||||
|
Console.WriteLine("[7/8] guest");
|
||||||
|
|
||||||
|
string[] firstNames =
|
||||||
|
[
|
||||||
|
"James","Mary","John","Patricia","Robert","Jennifer","Michael","Linda","William","Barbara",
|
||||||
|
"David","Elizabeth","Richard","Susan","Joseph","Jessica","Thomas","Sarah","Charles","Karen",
|
||||||
|
"Luca","Sofia","Marco","Giulia","Hans","Anna","Klaus","Maria","Pierre","Marie","Jean","Claire",
|
||||||
|
"Miguel","Ana","Carlos","Carmen","Andrei","Ioana","Mihai","Elena","Tomasz","Agnieszka",
|
||||||
|
"Dimitri","Eleni","Mehmet","Fatima","Yuki","Kenji","Haruto","Yuna","Wei","Fang","Li","Mei",
|
||||||
|
"Ahmed","Layla","Omar","Nour","Raj","Priya","Arjun","Ananya","Lucas","Emma","Noah","Olivia",
|
||||||
|
"Ethan","Ava","Mason","Isabella","Liam","Sophia","Oliver","Charlotte","Elijah","Amelia",
|
||||||
|
];
|
||||||
|
|
||||||
|
string[] lastNames =
|
||||||
|
[
|
||||||
|
"Smith","Johnson","Williams","Brown","Jones","Garcia","Miller","Davis","Wilson","Moore",
|
||||||
|
"Taylor","Anderson","Thomas","Jackson","White","Harris","Martin","Thompson","Young","Lee",
|
||||||
|
"Rossi","Ferrari","Esposito","Romano","Müller","Schmidt","Fischer","Weber","Meyer","Wagner",
|
||||||
|
"Dupont","Martin","Bernard","Petit","Dubois","Moreau","Laurent","Simon","Michel","Garcia",
|
||||||
|
"Kowalski","Nowak","Wiśniewski","Wójcik","Kowalczyk","Kamiński","Lewandowski","Zieliński",
|
||||||
|
"Papadopoulos","Georgiou","Yilmaz","Kaya","Tanaka","Sato","Suzuki","Watanabe","Ito","Yamamoto",
|
||||||
|
"Wang","Li","Zhang","Liu","Chen","Yang","Huang","Zhao","Kim","Park","Lee","Choi","Patel",
|
||||||
|
"Singh","Kumar","Sharma","Gupta","Ali","Hassan","Ahmed","Mohamed","Silva","Santos","Oliveira",
|
||||||
|
];
|
||||||
|
|
||||||
|
string[] guestCities =
|
||||||
|
[
|
||||||
|
"London","Paris","Berlin","Madrid","Rome","Amsterdam","Vienna","Zurich","Brussels","Stockholm",
|
||||||
|
"New York","Los Angeles","Chicago","Houston","Phoenix","Toronto","Vancouver","Sydney","Melbourne",
|
||||||
|
"Tokyo","Seoul","Beijing","Shanghai","Singapore","Bangkok","Dubai","Mumbai","Cape Town",
|
||||||
|
"Warsaw","Prague","Budapest","Athens","Istanbul","Lisbon","Oslo","Copenhagen","Helsinki",
|
||||||
|
];
|
||||||
|
|
||||||
|
var countryList = countries.Select(c => c.Code).ToArray();
|
||||||
|
|
||||||
|
var guestRows = new List<string>();
|
||||||
|
for (int g = 0; g < GUEST_COUNT; g++)
|
||||||
|
{
|
||||||
|
string fn = firstNames[rng.Next(firstNames.Length)];
|
||||||
|
string ln = lastNames[rng.Next(lastNames.Length)];
|
||||||
|
string name = $"{fn} {ln}";
|
||||||
|
string email = $"{fn.ToLower()}.{ln.ToLower()}{rng.Next(100, 999)}@example.com";
|
||||||
|
string city = guestCities[rng.Next(guestCities.Length)];
|
||||||
|
int ctryId = countryIds[countryList[rng.Next(countryList.Length)]];
|
||||||
|
guestRows.Add($"({ctryId},{S(name)},{S(email)},{S(city)})");
|
||||||
|
}
|
||||||
|
await BulkInsert("guest", "country_id, name, email, city", guestRows);
|
||||||
|
|
||||||
|
var guestIdMin = (int)await ExecScalar("SELECT MIN(guest_id) FROM guest");
|
||||||
|
var guestIdMax = (int)await ExecScalar("SELECT MAX(guest_id) FROM guest");
|
||||||
|
|
||||||
|
// ── 8. booking + room_booking ─────────────────────────────────────────────────
|
||||||
|
Console.WriteLine("[8/8] booking + room_booking");
|
||||||
|
|
||||||
|
var dateStart = new DateTime(2022, 1, 1);
|
||||||
|
var dateEnd = new DateTime(2025, 12, 31);
|
||||||
|
int dateRange = (dateEnd - dateStart).Days;
|
||||||
|
|
||||||
|
// Seasonal weight: month → weight (higher = more bookings)
|
||||||
|
int[] monthWeight = [0, 6, 5, 7, 9, 10, 14, 16, 15, 11, 9, 7, 11]; // Jan-Dec
|
||||||
|
|
||||||
|
DateTime RandomCheckin()
|
||||||
|
{
|
||||||
|
// Rejection sampling to simulate seasonal distribution
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var d = dateStart.AddDays(rng.Next(dateRange));
|
||||||
|
if (rng.Next(16) < monthWeight[d.Month]) return d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int RandomNights() => rng.Next(100) switch
|
||||||
|
{
|
||||||
|
< 30 => 1,
|
||||||
|
< 55 => 2,
|
||||||
|
< 75 => 3,
|
||||||
|
< 85 => 4,
|
||||||
|
< 92 => 5,
|
||||||
|
< 96 => rng.Next(6, 8),
|
||||||
|
_ => rng.Next(8, 15),
|
||||||
|
};
|
||||||
|
|
||||||
|
string RandomStatus() => rng.Next(100) switch
|
||||||
|
{
|
||||||
|
< 80 => "completed",
|
||||||
|
< 90 => "confirmed",
|
||||||
|
< 97 => "cancelled",
|
||||||
|
_ => "no_show",
|
||||||
|
};
|
||||||
|
|
||||||
|
// 90% single room, 8% two rooms, 2% three rooms
|
||||||
|
int RandomRoomCount() => rng.Next(100) switch { < 90 => 1, < 98 => 2, _ => 3 };
|
||||||
|
|
||||||
|
var bookingRows = new List<string>();
|
||||||
|
var roomBookingRows = new List<string>();
|
||||||
|
|
||||||
|
// We need booking_id for room_booking FK.
|
||||||
|
// Strategy: flush bookings in batches, then read back the auto-increment IDs,
|
||||||
|
// then insert room_bookings for that batch.
|
||||||
|
|
||||||
|
int bookingsDone = 0;
|
||||||
|
while (bookingsDone < BOOKING_COUNT)
|
||||||
|
{
|
||||||
|
int batchSize = Math.Min(BATCH, BOOKING_COUNT - bookingsDone);
|
||||||
|
bookingRows.Clear();
|
||||||
|
roomBookingRows.Clear();
|
||||||
|
|
||||||
|
for (int b = 0; b < batchSize; b++)
|
||||||
|
{
|
||||||
|
int guestId = guestIdMin + rng.Next(guestIdMax - guestIdMin + 1);
|
||||||
|
int hotelId = hotelIds[rng.Next(hotelIds.Count)];
|
||||||
|
DateTime checkin = RandomCheckin();
|
||||||
|
int nights = RandomNights();
|
||||||
|
DateTime checkout = checkin.AddDays(nights);
|
||||||
|
string status = RandomStatus();
|
||||||
|
DateTime created = checkin.AddDays(-rng.Next(1, 180));
|
||||||
|
|
||||||
|
bookingRows.Add($"({guestId},{hotelId},{D(checkin)},{D(checkout)},{S(status)},{DT(created)})");
|
||||||
|
}
|
||||||
|
|
||||||
|
await Exec($"INSERT INTO booking (guest_id, hotel_id, date_from, date_to, status, created_at) VALUES {string.Join(',', bookingRows)}");
|
||||||
|
long firstId = await ExecScalar("SELECT LAST_INSERT_ID()");
|
||||||
|
|
||||||
|
// Re-derive checkin/nights from the same rng sequence is impossible after the fact,
|
||||||
|
// so re-parse from inserted rows to build room_bookings
|
||||||
|
// Simpler: re-read the batch back
|
||||||
|
await using (var cmd = new MySqlCommand(
|
||||||
|
$"SELECT booking_id, hotel_id, date_from, date_to, status FROM booking WHERE booking_id >= {firstId} ORDER BY booking_id", conn))
|
||||||
|
await using (var reader = await cmd.ExecuteReaderAsync())
|
||||||
|
{
|
||||||
|
while (await reader.ReadAsync())
|
||||||
|
{
|
||||||
|
long bookingId = reader.GetInt64(0);
|
||||||
|
int hid = reader.GetInt32(1);
|
||||||
|
DateTime dfrom = reader.GetDateTime(2);
|
||||||
|
DateTime dto = reader.GetDateTime(3);
|
||||||
|
string status = reader.GetString(4);
|
||||||
|
int nights = (dto - dfrom).Days;
|
||||||
|
|
||||||
|
if (!hotelRooms.ContainsKey(hid) || hotelRooms[hid].Count == 0) continue;
|
||||||
|
|
||||||
|
// Skip room_bookings for cancelled/no_show sometimes
|
||||||
|
if (status == "cancelled" && rng.Next(100) < 60) continue;
|
||||||
|
if (status == "no_show" && rng.Next(100) < 30) continue;
|
||||||
|
|
||||||
|
int roomCount = RandomRoomCount();
|
||||||
|
var available = hotelRooms[hid].OrderBy(_ => rng.Next()).Take(roomCount).ToList();
|
||||||
|
|
||||||
|
foreach (var (roomId, roomTypeId) in available)
|
||||||
|
{
|
||||||
|
int ratePeriodId = monthToRatePeriodId[dfrom.Month];
|
||||||
|
decimal nightly = rateMap[(roomTypeId, ratePeriodId)];
|
||||||
|
decimal total = Math.Round(nightly * nights, 2);
|
||||||
|
roomBookingRows.Add($"({bookingId},{roomId},{D(dfrom)},{D(dto)},{N(nightly)},{N(total)})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roomBookingRows.Count > 0)
|
||||||
|
await Exec($"INSERT INTO room_booking (booking_id, room_id, date_from, date_to, nightly_rate, total_amount) VALUES {string.Join(',', roomBookingRows)}");
|
||||||
|
|
||||||
|
bookingsDone += batchSize;
|
||||||
|
if (bookingsDone % 10_000 == 0)
|
||||||
|
Console.WriteLine($" bookings: {bookingsDone:N0} / {BOOKING_COUNT:N0}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("── Row counts ───────────────────────────────");
|
||||||
|
foreach (var t in new[]{"hotel_chain","country","star_rating","hotel_characteristic",
|
||||||
|
"room_type","rate_period","period_room_rate","hotel",
|
||||||
|
"hotel_room","hotel_hotel_characteristic","guest","booking","room_booking"})
|
||||||
|
{
|
||||||
|
long cnt = await ExecScalar($"SELECT COUNT(*) FROM {t}");
|
||||||
|
Console.WriteLine($" {t,-35} {cnt,10:N0}");
|
||||||
|
}
|
||||||
|
Console.WriteLine("Done.");
|
||||||
187
sql/datamart_schema.sql
Normal file
187
sql/datamart_schema.sql
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
create table ETL_WATERMARK
|
||||||
|
(
|
||||||
|
ENTITY_NAME VARCHAR2(50) not null
|
||||||
|
constraint PK_ETL_WATERMARK
|
||||||
|
primary key,
|
||||||
|
LAST_KEY NUMBER(20) default 0 not null,
|
||||||
|
LAST_RUN_TS TIMESTAMP(6) default SYSTIMESTAMP
|
||||||
|
)
|
||||||
|
/
|
||||||
|
|
||||||
|
create table STG_HOTEL
|
||||||
|
(
|
||||||
|
HOTEL_ID NUMBER(10) not null,
|
||||||
|
HOTEL_CODE VARCHAR2(20) not null,
|
||||||
|
HOTEL_NAME VARCHAR2(150) not null,
|
||||||
|
CITY VARCHAR2(100) not null,
|
||||||
|
COUNTRY_CODE CHAR(2) not null,
|
||||||
|
COUNTRY_NAME VARCHAR2(100) not null,
|
||||||
|
CURRENCY VARCHAR2(10) not null,
|
||||||
|
CHAIN_CODE VARCHAR2(10),
|
||||||
|
CHAIN_NAME VARCHAR2(100),
|
||||||
|
STAR_RATING NUMBER(1) not null,
|
||||||
|
STAR_DESCRIPTION VARCHAR2(20)
|
||||||
|
)
|
||||||
|
/
|
||||||
|
|
||||||
|
create table DIM_DATE
|
||||||
|
(
|
||||||
|
DATE_KEY NUMBER(8) not null
|
||||||
|
constraint PK_DIM_DATE
|
||||||
|
primary key,
|
||||||
|
FULL_DATE DATE not null,
|
||||||
|
YEAR NUMBER(4) not null,
|
||||||
|
QUARTER NUMBER(1) not null,
|
||||||
|
MONTH NUMBER(2) not null,
|
||||||
|
MONTH_NAME VARCHAR2(10) not null,
|
||||||
|
WEEK_NUMBER NUMBER(2) not null,
|
||||||
|
DAY_OF_MONTH NUMBER(2) not null,
|
||||||
|
DAY_NAME VARCHAR2(10) not null,
|
||||||
|
IS_WEEKEND NUMBER(1) not null
|
||||||
|
constraint CK_DIM_DATE_WEEKEND
|
||||||
|
check (is_weekend IN (0, 1)),
|
||||||
|
IS_BUSINESS_DAY NUMBER(1) not null
|
||||||
|
constraint CK_DIM_DATE_BUSINESS
|
||||||
|
check (is_business_day IN (0, 1)),
|
||||||
|
SEASON VARCHAR2(10) not null
|
||||||
|
)
|
||||||
|
/
|
||||||
|
|
||||||
|
create table DIM_HOTEL
|
||||||
|
(
|
||||||
|
HOTEL_KEY NUMBER(10) default "IPZ19438"."ISEQ$$_303891".nextval generated as identity
|
||||||
|
constraint PK_DIM_HOTEL
|
||||||
|
primary key,
|
||||||
|
SOURCE_HOTEL_ID NUMBER(10) not null,
|
||||||
|
HOTEL_CODE VARCHAR2(20) not null,
|
||||||
|
HOTEL_NAME VARCHAR2(150) not null,
|
||||||
|
CITY VARCHAR2(100) not null,
|
||||||
|
COUNTRY_CODE CHAR(2) not null,
|
||||||
|
COUNTRY_NAME VARCHAR2(100) not null,
|
||||||
|
CURRENCY VARCHAR2(10) not null,
|
||||||
|
CHAIN_CODE VARCHAR2(10),
|
||||||
|
CHAIN_NAME VARCHAR2(100),
|
||||||
|
STAR_RATING NUMBER(1) not null,
|
||||||
|
STAR_DESCRIPTION VARCHAR2(20),
|
||||||
|
EFFECTIVE_DATE DATE not null,
|
||||||
|
EXPIRY_DATE DATE,
|
||||||
|
IS_CURRENT NUMBER(1) default 1 not null
|
||||||
|
constraint CK_DIM_HOTEL_CURRENT
|
||||||
|
check (is_current IN (0, 1))
|
||||||
|
)
|
||||||
|
/
|
||||||
|
|
||||||
|
create table DIM_ROOM
|
||||||
|
(
|
||||||
|
ROOM_KEY NUMBER(10) generated as identity
|
||||||
|
constraint PK_DIM_ROOM
|
||||||
|
primary key,
|
||||||
|
SOURCE_ROOM_ID NUMBER(10) not null
|
||||||
|
constraint UQ_DIM_ROOM
|
||||||
|
unique,
|
||||||
|
HOTEL_KEY NUMBER(10) not null
|
||||||
|
constraint FK_DIM_ROOM_HOTEL
|
||||||
|
references DIM_HOTEL,
|
||||||
|
ROOM_NUMBER VARCHAR2(10) not null,
|
||||||
|
FLOOR NUMBER(3) not null,
|
||||||
|
ROOM_TYPE_CODE VARCHAR2(20) not null,
|
||||||
|
ROOM_TYPE_DESCRIPTION VARCHAR2(100) not null,
|
||||||
|
SMOKING_YN NUMBER(1) not null
|
||||||
|
constraint CK_DIM_ROOM_SMOKING
|
||||||
|
check (smoking_yn IN (0, 1)),
|
||||||
|
STANDARD_RATE NUMBER(10, 2) not null
|
||||||
|
)
|
||||||
|
/
|
||||||
|
|
||||||
|
create table DIM_GUEST
|
||||||
|
(
|
||||||
|
GUEST_KEY NUMBER(10) generated as identity
|
||||||
|
constraint PK_DIM_GUEST
|
||||||
|
primary key,
|
||||||
|
SOURCE_GUEST_ID NUMBER(10) not null
|
||||||
|
constraint UQ_DIM_GUEST
|
||||||
|
unique,
|
||||||
|
GUEST_NAME VARCHAR2(150) not null,
|
||||||
|
CITY VARCHAR2(100),
|
||||||
|
COUNTRY_CODE CHAR(2),
|
||||||
|
COUNTRY_NAME VARCHAR2(100)
|
||||||
|
)
|
||||||
|
/
|
||||||
|
|
||||||
|
create table FACT_ROOM_BOOKING
|
||||||
|
(
|
||||||
|
FACT_ID NUMBER(10) default "IPZ19438"."ISEQ$$_303902".nextval generated as identity
|
||||||
|
constraint PK_FACT_ROOM_BOOKING
|
||||||
|
primary key,
|
||||||
|
SOURCE_RB_ID NUMBER(10) not null
|
||||||
|
constraint UQ_FACT_ROOM_BOOKING_SRC
|
||||||
|
unique,
|
||||||
|
HOTEL_KEY NUMBER(10) not null
|
||||||
|
constraint FK_FACT_HOTEL
|
||||||
|
references DIM_HOTEL,
|
||||||
|
ROOM_KEY NUMBER(10) not null
|
||||||
|
constraint FK_FACT_ROOM
|
||||||
|
references DIM_ROOM,
|
||||||
|
GUEST_KEY NUMBER(10) not null
|
||||||
|
constraint FK_FACT_GUEST
|
||||||
|
references DIM_GUEST,
|
||||||
|
BOOKING_CREATED_DATE_KEY NUMBER(8) not null
|
||||||
|
constraint FK_FACT_BOOKING_DATE
|
||||||
|
references DIM_DATE,
|
||||||
|
CHECKIN_DATE_KEY NUMBER(8) not null
|
||||||
|
constraint FK_FACT_CHECKIN_DATE
|
||||||
|
references DIM_DATE,
|
||||||
|
CHECKOUT_DATE_KEY NUMBER(8) not null
|
||||||
|
constraint FK_FACT_CHECKOUT_DATE
|
||||||
|
references DIM_DATE,
|
||||||
|
BOOKING_STATUS VARCHAR2(20) not null,
|
||||||
|
BOOKING_COUNT NUMBER(1) default 1 not null
|
||||||
|
constraint CK_FACT_BOOKING_COUNT
|
||||||
|
check (booking_count = 1),
|
||||||
|
NIGHTS_STAYED NUMBER(4) not null,
|
||||||
|
NIGHTLY_RATE NUMBER(10, 2) not null,
|
||||||
|
TOTAL_AMOUNT NUMBER(12, 2) not null
|
||||||
|
)
|
||||||
|
/
|
||||||
|
|
||||||
|
create table STG_GUEST
|
||||||
|
(
|
||||||
|
SOURCE_GUEST_ID NUMBER(10) not null,
|
||||||
|
GUEST_NAME VARCHAR2(150) not null,
|
||||||
|
CITY VARCHAR2(100),
|
||||||
|
COUNTRY_CODE CHAR(2),
|
||||||
|
COUNTRY_NAME VARCHAR2(100)
|
||||||
|
)
|
||||||
|
/
|
||||||
|
|
||||||
|
create table STG_ROOM
|
||||||
|
(
|
||||||
|
SOURCE_ROOM_ID NUMBER(10) not null,
|
||||||
|
HOTEL_CODE VARCHAR2(20) not null,
|
||||||
|
ROOM_NUMBER VARCHAR2(10) not null,
|
||||||
|
FLOOR NUMBER(3) not null,
|
||||||
|
ROOM_TYPE_CODE VARCHAR2(20) not null,
|
||||||
|
ROOM_TYPE_DESCRIPTION VARCHAR2(100) not null,
|
||||||
|
SMOKING_YN NUMBER(1) not null,
|
||||||
|
STANDARD_RATE NUMBER(10, 2) not null,
|
||||||
|
HOTEL_ID NUMBER(10)
|
||||||
|
)
|
||||||
|
/
|
||||||
|
|
||||||
|
create table STG_ROOM_BOOKING
|
||||||
|
(
|
||||||
|
SOURCE_RB_ID NUMBER(10) not null,
|
||||||
|
GUEST_ID NUMBER(10) not null,
|
||||||
|
BOOKING_CREATED_DATE DATE not null,
|
||||||
|
CHECKIN_DATE DATE not null,
|
||||||
|
CHECKOUT_DATE DATE not null,
|
||||||
|
BOOKING_STATUS VARCHAR2(20) not null,
|
||||||
|
BOOKING_COUNT NUMBER(1) default 1 not null,
|
||||||
|
NIGHTS_STAYED NUMBER(4) not null,
|
||||||
|
NIGHTLY_RATE NUMBER(10, 2) not null,
|
||||||
|
TOTAL_AMOUNT NUMBER(12, 2) not null,
|
||||||
|
HOTEL_ID NUMBER(10) not null,
|
||||||
|
ROOM_ID NUMBER(10) not null
|
||||||
|
)
|
||||||
|
/
|
||||||
|
|
||||||
264
sql/schema.sql
264
sql/schema.sql
@@ -1,186 +1,154 @@
|
|||||||
CREATE DATABASE IF NOT EXISTS ewc2025
|
CREATE DATABASE IF NOT EXISTS hotel_reservations
|
||||||
CHARACTER SET utf8mb4
|
CHARACTER SET utf8mb4
|
||||||
COLLATE utf8mb4_unicode_ci;
|
COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
USE ewc2025;
|
USE hotel_reservations;
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────────────────────
|
-- ─────────────────────────────────────────────────────────────────────────────
|
||||||
-- LOOKUP TABLES
|
-- LOOKUP / REFERENCE TABLES
|
||||||
-- ─────────────────────────────────────────────────────────────────────────────
|
-- ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
CREATE TABLE game (
|
CREATE TABLE hotel_chain (
|
||||||
game_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
hotel_chain_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
name VARCHAR(100) NOT NULL,
|
code VARCHAR(10) NOT NULL,
|
||||||
game_type VARCHAR(50) NOT NULL,
|
name VARCHAR(100) NOT NULL,
|
||||||
platform VARCHAR(50) NOT NULL,
|
PRIMARY KEY (hotel_chain_id),
|
||||||
PRIMARY KEY (game_id),
|
UNIQUE KEY uq_chain_code (code)
|
||||||
UNIQUE KEY uq_game_name (name)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE country (
|
CREATE TABLE country (
|
||||||
country_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
country_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
name VARCHAR(100) NOT NULL,
|
code CHAR(2) NOT NULL,
|
||||||
region VARCHAR(50) NOT NULL,
|
name VARCHAR(100) NOT NULL,
|
||||||
gold_medals TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
currency VARCHAR(10) NOT NULL,
|
||||||
silver_medals TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
bronze_medals TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
total_medals TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
total_players SMALLINT UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
top_game VARCHAR(100),
|
|
||||||
PRIMARY KEY (country_id),
|
PRIMARY KEY (country_id),
|
||||||
UNIQUE KEY uq_country_name (name)
|
UNIQUE KEY uq_country_code (code)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE point_system (
|
CREATE TABLE star_rating (
|
||||||
point_system_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
star_rating_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
placement TINYINT UNSIGNED NOT NULL,
|
code TINYINT UNSIGNED NOT NULL,
|
||||||
points SMALLINT UNSIGNED NOT NULL,
|
description VARCHAR(20) NOT NULL,
|
||||||
system_type ENUM('Standard', 'Co-Placement', 'Extended', 'Special') NOT NULL,
|
PRIMARY KEY (star_rating_id),
|
||||||
description VARCHAR(50),
|
UNIQUE KEY uq_star_code (code)
|
||||||
PRIMARY KEY (point_system_id),
|
|
||||||
UNIQUE KEY uq_placement_type (placement, system_type)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE prize_pool_category (
|
CREATE TABLE hotel_characteristic (
|
||||||
prize_category_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
characteristic_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
category VARCHAR(100) NOT NULL,
|
code VARCHAR(20) NOT NULL,
|
||||||
amount_usd INT UNSIGNED NOT NULL,
|
description VARCHAR(100) NOT NULL,
|
||||||
percentage DECIMAL(5,2) NOT NULL,
|
PRIMARY KEY (characteristic_id),
|
||||||
description VARCHAR(200),
|
UNIQUE KEY uq_char_code (code)
|
||||||
num_recipients INT UNSIGNED,
|
);
|
||||||
PRIMARY KEY (prize_category_id),
|
|
||||||
UNIQUE KEY uq_category (category)
|
CREATE TABLE room_type (
|
||||||
|
room_type_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
code VARCHAR(20) NOT NULL,
|
||||||
|
description VARCHAR(100) NOT NULL,
|
||||||
|
standard_rate DECIMAL(10,2) NOT NULL,
|
||||||
|
smoking_yn BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
PRIMARY KEY (room_type_id),
|
||||||
|
UNIQUE KEY uq_room_type_code (code)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE rate_period (
|
||||||
|
rate_period_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
code VARCHAR(20) NOT NULL,
|
||||||
|
description VARCHAR(50) NOT NULL,
|
||||||
|
month_from TINYINT UNSIGNED NOT NULL,
|
||||||
|
month_to TINYINT UNSIGNED NOT NULL,
|
||||||
|
PRIMARY KEY (rate_period_id),
|
||||||
|
UNIQUE KEY uq_rate_period_code (code)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────────────────────
|
-- ─────────────────────────────────────────────────────────────────────────────
|
||||||
-- CORE ENTITIES
|
-- CORE ENTITIES
|
||||||
-- ─────────────────────────────────────────────────────────────────────────────
|
-- ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
CREATE TABLE organization (
|
CREATE TABLE hotel (
|
||||||
organization_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
hotel_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
name VARCHAR(150) NOT NULL,
|
hotel_chain_id INT UNSIGNED,
|
||||||
region VARCHAR(50),
|
country_id INT UNSIGNED NOT NULL,
|
||||||
country_id INT UNSIGNED,
|
star_rating_id INT UNSIGNED NOT NULL,
|
||||||
club_partner_status ENUM('Current', 'New', 'None') NOT NULL DEFAULT 'None',
|
code VARCHAR(20) NOT NULL,
|
||||||
top_8_2024 BOOLEAN,
|
name VARCHAR(150) NOT NULL,
|
||||||
founded_year SMALLINT UNSIGNED,
|
address VARCHAR(200),
|
||||||
hq_location VARCHAR(150),
|
postcode VARCHAR(20),
|
||||||
ceo VARCHAR(150),
|
city VARCHAR(100) NOT NULL,
|
||||||
social_media_followers_m DECIMAL(6,2),
|
url VARCHAR(200),
|
||||||
PRIMARY KEY (organization_id),
|
PRIMARY KEY (hotel_id),
|
||||||
UNIQUE KEY uq_org_name (name),
|
UNIQUE KEY uq_hotel_code (code),
|
||||||
CONSTRAINT fk_org_country FOREIGN KEY (country_id) REFERENCES country (country_id)
|
CONSTRAINT fk_hotel_chain FOREIGN KEY (hotel_chain_id) REFERENCES hotel_chain (hotel_chain_id),
|
||||||
|
CONSTRAINT fk_hotel_country FOREIGN KEY (country_id) REFERENCES country (country_id),
|
||||||
|
CONSTRAINT fk_hotel_star FOREIGN KEY (star_rating_id) REFERENCES star_rating (star_rating_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE tournament (
|
CREATE TABLE hotel_room (
|
||||||
tournament_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
room_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
game_id INT UNSIGNED NOT NULL,
|
hotel_id INT UNSIGNED NOT NULL,
|
||||||
event_name VARCHAR(200) NOT NULL,
|
room_type_id INT UNSIGNED NOT NULL,
|
||||||
start_date DATE NOT NULL,
|
room_number VARCHAR(10) NOT NULL,
|
||||||
end_date DATE NOT NULL,
|
floor TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
||||||
prize_pool_usd INT UNSIGNED NOT NULL,
|
PRIMARY KEY (room_id),
|
||||||
num_participants TINYINT UNSIGNED NOT NULL,
|
UNIQUE KEY uq_hotel_room (hotel_id, room_number),
|
||||||
winner VARCHAR(200),
|
CONSTRAINT fk_room_hotel FOREIGN KEY (hotel_id) REFERENCES hotel (hotel_id),
|
||||||
runner_up VARCHAR(200),
|
CONSTRAINT fk_room_type FOREIGN KEY (room_type_id) REFERENCES room_type (room_type_id)
|
||||||
club_championship_points BOOLEAN NOT NULL DEFAULT FALSE,
|
|
||||||
gender ENUM('Open', 'Men', 'Women') NOT NULL DEFAULT 'Open',
|
|
||||||
PRIMARY KEY (tournament_id),
|
|
||||||
CONSTRAINT fk_tournament_game FOREIGN KEY (game_id) REFERENCES game (game_id)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE schedule (
|
CREATE TABLE guest (
|
||||||
schedule_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
guest_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
tournament_id INT UNSIGNED NOT NULL,
|
country_id INT UNSIGNED,
|
||||||
week_number TINYINT UNSIGNED NOT NULL,
|
name VARCHAR(150) NOT NULL,
|
||||||
venue VARCHAR(200) NOT NULL,
|
email VARCHAR(150),
|
||||||
time_zone VARCHAR(10) NOT NULL,
|
address VARCHAR(200),
|
||||||
duration_days TINYINT UNSIGNED NOT NULL,
|
city VARCHAR(100),
|
||||||
PRIMARY KEY (schedule_id),
|
PRIMARY KEY (guest_id),
|
||||||
UNIQUE KEY uq_schedule_tournament (tournament_id),
|
CONSTRAINT fk_guest_country FOREIGN KEY (country_id) REFERENCES country (country_id)
|
||||||
CONSTRAINT fk_schedule_tournament FOREIGN KEY (tournament_id) REFERENCES tournament (tournament_id)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE player (
|
CREATE TABLE booking (
|
||||||
player_id VARCHAR(20) NOT NULL,
|
booking_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
player_name VARCHAR(100) NOT NULL,
|
guest_id INT UNSIGNED NOT NULL,
|
||||||
country_id INT UNSIGNED,
|
hotel_id INT UNSIGNED NOT NULL,
|
||||||
region VARCHAR(50),
|
date_from DATE NOT NULL,
|
||||||
organization_id INT UNSIGNED,
|
date_to DATE NOT NULL,
|
||||||
game_id INT UNSIGNED,
|
status ENUM('confirmed', 'cancelled', 'completed', 'no_show') NOT NULL DEFAULT 'confirmed',
|
||||||
role VARCHAR(50),
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
age TINYINT UNSIGNED,
|
PRIMARY KEY (booking_id),
|
||||||
experience_years TINYINT UNSIGNED,
|
CONSTRAINT fk_booking_guest FOREIGN KEY (guest_id) REFERENCES guest (guest_id),
|
||||||
previous_team VARCHAR(150),
|
CONSTRAINT fk_booking_hotel FOREIGN KEY (hotel_id) REFERENCES hotel (hotel_id)
|
||||||
tournament_place TINYINT UNSIGNED,
|
|
||||||
prize_earned_usd INT UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
social_media_followers_k INT UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (player_id),
|
|
||||||
CONSTRAINT fk_player_country FOREIGN KEY (country_id) REFERENCES country (country_id),
|
|
||||||
CONSTRAINT fk_player_org FOREIGN KEY (organization_id) REFERENCES organization (organization_id),
|
|
||||||
CONSTRAINT fk_player_game FOREIGN KEY (game_id) REFERENCES game (game_id)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE medalist (
|
CREATE TABLE room_booking (
|
||||||
medalist_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
room_booking_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
tournament_id INT UNSIGNED NOT NULL,
|
booking_id INT UNSIGNED NOT NULL,
|
||||||
medal ENUM('Gold', 'Silver', 'Bronze') NOT NULL,
|
room_id INT UNSIGNED NOT NULL,
|
||||||
organization_id INT UNSIGNED,
|
date_from DATE NOT NULL,
|
||||||
player_name VARCHAR(100) NOT NULL,
|
date_to DATE NOT NULL,
|
||||||
country_id INT UNSIGNED,
|
nightly_rate DECIMAL(10,2) NOT NULL,
|
||||||
role VARCHAR(50),
|
total_amount DECIMAL(10,2) NOT NULL,
|
||||||
PRIMARY KEY (medalist_id),
|
PRIMARY KEY (room_booking_id),
|
||||||
CONSTRAINT fk_medalist_tournament FOREIGN KEY (tournament_id) REFERENCES tournament (tournament_id),
|
CONSTRAINT fk_rb_booking FOREIGN KEY (booking_id) REFERENCES booking (booking_id),
|
||||||
CONSTRAINT fk_medalist_org FOREIGN KEY (organization_id) REFERENCES organization (organization_id),
|
CONSTRAINT fk_rb_room FOREIGN KEY (room_id) REFERENCES hotel_room (room_id)
|
||||||
CONSTRAINT fk_medalist_country FOREIGN KEY (country_id) REFERENCES country (country_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- team_1 / team_2 / winner are VARCHAR because individual-game matches
|
|
||||||
-- (Chess, StarCraft II, fighting games) use player names instead of org names
|
|
||||||
CREATE TABLE match_result (
|
|
||||||
match_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
tournament_id INT UNSIGNED NOT NULL,
|
|
||||||
match_type VARCHAR(50) NOT NULL,
|
|
||||||
team_1 VARCHAR(200) NOT NULL,
|
|
||||||
team_2 VARCHAR(200) NOT NULL,
|
|
||||||
winner VARCHAR(200),
|
|
||||||
score VARCHAR(20),
|
|
||||||
map VARCHAR(100),
|
|
||||||
duration_minutes SMALLINT UNSIGNED,
|
|
||||||
mvp VARCHAR(100),
|
|
||||||
PRIMARY KEY (match_id),
|
|
||||||
CONSTRAINT fk_match_tournament FOREIGN KEY (tournament_id) REFERENCES tournament (tournament_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE club_championship_standing (
|
|
||||||
standing_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
organization_id INT UNSIGNED NOT NULL,
|
|
||||||
rank TINYINT UNSIGNED NOT NULL,
|
|
||||||
total_points SMALLINT UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
prize_money_usd INT UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
tournament_wins TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
top_8_finishes TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
|
||||||
eligible_to_win BOOLEAN NOT NULL DEFAULT FALSE,
|
|
||||||
PRIMARY KEY (standing_id),
|
|
||||||
UNIQUE KEY uq_standing_org (organization_id),
|
|
||||||
CONSTRAINT fk_standing_org FOREIGN KEY (organization_id) REFERENCES organization (organization_id)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
-- ─────────────────────────────────────────────────────────────────────────────
|
-- ─────────────────────────────────────────────────────────────────────────────
|
||||||
-- JUNCTION TABLES
|
-- JUNCTION TABLES
|
||||||
-- ─────────────────────────────────────────────────────────────────────────────
|
-- ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
CREATE TABLE organization_game_competing (
|
CREATE TABLE hotel_hotel_characteristic (
|
||||||
organization_id INT UNSIGNED NOT NULL,
|
hotel_id INT UNSIGNED NOT NULL,
|
||||||
game_id INT UNSIGNED NOT NULL,
|
characteristic_id INT UNSIGNED NOT NULL,
|
||||||
PRIMARY KEY (organization_id, game_id),
|
PRIMARY KEY (hotel_id, characteristic_id),
|
||||||
CONSTRAINT fk_ogc_org FOREIGN KEY (organization_id) REFERENCES organization (organization_id),
|
CONSTRAINT fk_hhc_hotel FOREIGN KEY (hotel_id) REFERENCES hotel (hotel_id),
|
||||||
CONSTRAINT fk_ogc_game FOREIGN KEY (game_id) REFERENCES game (game_id)
|
CONSTRAINT fk_hhc_char FOREIGN KEY (characteristic_id) REFERENCES hotel_characteristic (characteristic_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE organization_game_won (
|
CREATE TABLE period_room_rate (
|
||||||
organization_id INT UNSIGNED NOT NULL,
|
room_type_id INT UNSIGNED NOT NULL,
|
||||||
game_id INT UNSIGNED NOT NULL,
|
rate_period_id INT UNSIGNED NOT NULL,
|
||||||
PRIMARY KEY (organization_id, game_id),
|
rate DECIMAL(10,2) NOT NULL,
|
||||||
CONSTRAINT fk_ogw_org FOREIGN KEY (organization_id) REFERENCES organization (organization_id),
|
PRIMARY KEY (room_type_id, rate_period_id),
|
||||||
CONSTRAINT fk_ogw_game FOREIGN KEY (game_id) REFERENCES game (game_id)
|
CONSTRAINT fk_prr_type FOREIGN KEY (room_type_id) REFERENCES room_type (room_type_id),
|
||||||
|
CONSTRAINT fk_prr_period FOREIGN KEY (rate_period_id) REFERENCES rate_period (rate_period_id)
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user