readded calendar and xleaderboard
108
models/player.js
@@ -1,78 +1,106 @@
|
||||
const mongoose = require('mongoose')
|
||||
const mongoose = require("mongoose")
|
||||
|
||||
const playerSchema = new mongoose.Schema({
|
||||
name: {type: String, required: true },
|
||||
name: { type: String, required: true },
|
||||
unique_id: { type: String, unique: true, required: true },
|
||||
alias: String,
|
||||
twitter: String,
|
||||
weapons: [String],
|
||||
topTotal: {
|
||||
type: [{
|
||||
type: [
|
||||
{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Placement'
|
||||
}
|
||||
], validate: [arrayLimit, '{PATH} exceeds the limit of 4']},
|
||||
ref: "Placement"
|
||||
}
|
||||
],
|
||||
validate: [arrayLimit, "{PATH} exceeds the limit of 4"]
|
||||
},
|
||||
topTotalScore: Number,
|
||||
topShooter: {
|
||||
type: [{
|
||||
type: [
|
||||
{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Placement'
|
||||
}
|
||||
], validate: [arrayLimit, '{PATH} exceeds the limit of 4']},
|
||||
ref: "Placement"
|
||||
}
|
||||
],
|
||||
validate: [arrayLimit, "{PATH} exceeds the limit of 4"]
|
||||
},
|
||||
topShooterScore: Number,
|
||||
topBlaster: {
|
||||
type: [{
|
||||
type: [
|
||||
{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Placement'
|
||||
}
|
||||
], validate: [arrayLimit, '{PATH} exceeds the limit of 4']},
|
||||
ref: "Placement"
|
||||
}
|
||||
],
|
||||
validate: [arrayLimit, "{PATH} exceeds the limit of 4"]
|
||||
},
|
||||
topBlasterScore: Number,
|
||||
topRoller: {
|
||||
type: [{
|
||||
type: [
|
||||
{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Placement'
|
||||
}
|
||||
], validate: [arrayLimit, '{PATH} exceeds the limit of 4']},
|
||||
ref: "Placement"
|
||||
}
|
||||
],
|
||||
validate: [arrayLimit, "{PATH} exceeds the limit of 4"]
|
||||
},
|
||||
topRollerScore: Number,
|
||||
topCharger: {
|
||||
type: [{
|
||||
type: [
|
||||
{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Placement'
|
||||
}
|
||||
], validate: [arrayLimit, '{PATH} exceeds the limit of 4']},
|
||||
ref: "Placement"
|
||||
}
|
||||
],
|
||||
validate: [arrayLimit, "{PATH} exceeds the limit of 4"]
|
||||
},
|
||||
topChargerScore: Number,
|
||||
topSlosher: {
|
||||
type: [{
|
||||
type: [
|
||||
{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Placement'
|
||||
}
|
||||
], validate: [arrayLimit, '{PATH} exceeds the limit of 4']},
|
||||
ref: "Placement"
|
||||
}
|
||||
],
|
||||
validate: [arrayLimit, "{PATH} exceeds the limit of 4"]
|
||||
},
|
||||
topSlosherScore: Number,
|
||||
topSplatling: {
|
||||
type: [{
|
||||
type: [
|
||||
{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Placement'
|
||||
}
|
||||
], validate: [arrayLimit, '{PATH} exceeds the limit of 4']},
|
||||
ref: "Placement"
|
||||
}
|
||||
],
|
||||
validate: [arrayLimit, "{PATH} exceeds the limit of 4"]
|
||||
},
|
||||
topSplatlingScore: Number,
|
||||
topDualies: {
|
||||
type: [{
|
||||
type: [
|
||||
{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Placement'
|
||||
}
|
||||
], validate: [arrayLimit, '{PATH} exceeds the limit of 4']},
|
||||
ref: "Placement"
|
||||
}
|
||||
],
|
||||
validate: [arrayLimit, "{PATH} exceeds the limit of 4"]
|
||||
},
|
||||
topDualiesScore: Number,
|
||||
topBrella: {
|
||||
type: [{
|
||||
type: [
|
||||
{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Placement'
|
||||
}
|
||||
], validate: [arrayLimit, '{PATH} exceeds the limit of 4']},
|
||||
topBrellaScore: Number
|
||||
ref: "Placement"
|
||||
}
|
||||
],
|
||||
validate: [arrayLimit, "{PATH} exceeds the limit of 4"]
|
||||
},
|
||||
topBrellaScore: Number,
|
||||
weaponsCount: Number
|
||||
})
|
||||
|
||||
function arrayLimit(val) {
|
||||
return val.length <= 4
|
||||
}
|
||||
|
||||
module.exports = mongoose.model('Player', playerSchema)
|
||||
module.exports = mongoose.model("Player", playerSchema)
|
||||
|
||||
5
react-ui/package-lock.json
generated
@@ -7958,6 +7958,11 @@
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"jstz": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jstz/-/jstz-2.1.1.tgz",
|
||||
"integrity": "sha512-8hfl5RD6P7rEeIbzStBz3h4f+BQHfq/ABtoU6gXKQv5OcZhnmrIpG7e1pYaZ8hS9e0mp+bxUj08fnDUbKctYyA=="
|
||||
},
|
||||
"jsx-ast-utils": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.1.tgz",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"@apollo/react-hooks": "^3.1.1",
|
||||
"apollo-boost": "^0.4.4",
|
||||
"graphql": "^14.5.8",
|
||||
"jstz": "^2.1.1",
|
||||
"react": "^16.10.1",
|
||||
"react-color": "^2.17.3",
|
||||
"react-dom": "^16.10.1",
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
BIN
react-ui/src/assets/xleaderboardIcons/all.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
react-ui/src/assets/xleaderboardIcons/blasters.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
react-ui/src/assets/xleaderboardIcons/brellas.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
react-ui/src/assets/xleaderboardIcons/chargers.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
react-ui/src/assets/xleaderboardIcons/dualies.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
react-ui/src/assets/xleaderboardIcons/flex.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
react-ui/src/assets/xleaderboardIcons/rollers.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
react-ui/src/assets/xleaderboardIcons/shooters.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
react-ui/src/assets/xleaderboardIcons/sloshers.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
react-ui/src/assets/xleaderboardIcons/splatlings.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
77
react-ui/src/components/calendar/Calendar.js
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
import React, { useState, useEffect, useRef } from "react"
|
||||
import { Button, Segment } from "semantic-ui-react"
|
||||
import jstz from "jstz"
|
||||
|
||||
import useWindowDimensions from "../../utils/useWindowDimensions"
|
||||
|
||||
const PageCalendar = () => {
|
||||
const [showCode, setShowCode] = useState(false)
|
||||
const { containerWidth } = useWindowDimensions()
|
||||
const calenderDiv = useRef(null)
|
||||
|
||||
const iFrameHTML = `<iframe title="calendar" src="https://calendar.google.com/calendar/embed?height=600&wkst=2&bgcolor=%23ffffff&src=NDNnYnJlamkxbnQyZTY1dWJuZzdvYWkxZGtAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ&color=%23E67C73&showTitle=0&showNav=1&showDate=1&showPrint=0&showCalendars=0&ctz=${jstz
|
||||
.determine()
|
||||
.name()}" style=border-width: 0 width=${containerWidth} height="1000" frameBorder="0" scrolling="no"></iframe>`
|
||||
|
||||
//This is a weird solution but I couldn't get it working just setting the iframe src from a variable
|
||||
useEffect(() => {
|
||||
document.title = "Competitive Calendar - sendou.ink"
|
||||
calenderDiv.current.innerHTML = iFrameHTML
|
||||
}, [iFrameHTML])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<Button onClick={() => setShowCode(!showCode)}>Show emoji code</Button>
|
||||
{showCode && (
|
||||
<Segment raised compact>
|
||||
<h4>
|
||||
<span role="img" aria-label="money bag emoji">
|
||||
💰
|
||||
</span>{" "}
|
||||
- Has prizes
|
||||
<br />
|
||||
<span role="img" aria-label="masks emoji">
|
||||
🎭
|
||||
</span>{" "}
|
||||
- Unconventional ruleset
|
||||
<br />
|
||||
<span role="img" aria-label="lock emoji">
|
||||
🔒
|
||||
</span>{" "}
|
||||
- Limited registration
|
||||
<br />
|
||||
<span role="img" aria-label="handshake emoji">
|
||||
🤝
|
||||
</span>{" "}
|
||||
- Local event
|
||||
<br />
|
||||
<span role="img" aria-label="dice emoji">
|
||||
🎲
|
||||
</span>{" "}
|
||||
- Solo registration available
|
||||
<br />
|
||||
<span role="img" aria-label="eyes emoji">
|
||||
👀
|
||||
</span>{" "}
|
||||
- No open registration
|
||||
</h4>
|
||||
</Segment>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ paddingTop: "15px" }} ref={calenderDiv}></div>
|
||||
If an event is missing you can contact{" "}
|
||||
<a href="https://twitter.com/Kbot_273">Kbot</a> about it.
|
||||
<br />
|
||||
You can add the calendar to your personal Google Calendar by pressing the
|
||||
plus button above. If you are using other kind of calendar program you can
|
||||
try{" "}
|
||||
<a href="https://calendar.google.com/calendar/ical/43gbreji1nt2e65ubng7oai1dk%40group.calendar.google.com/public/basic.ics">
|
||||
this link
|
||||
</a>{" "}
|
||||
instead.
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PageCalendar
|
||||
16
react-ui/src/components/root/MainMenu.js
vendored
@@ -19,36 +19,36 @@ const MainMenu = () => {
|
||||
|
||||
<Dropdown item text="Tools">
|
||||
<Dropdown.Menu style={dropdownStyle}>
|
||||
<Dropdown.Item as={NavLink} exact to="/maps">
|
||||
<Dropdown.Item as={NavLink} to="/maps">
|
||||
Maplist Generator
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item as={NavLink} exact to="/rotation">
|
||||
<Dropdown.Item as={NavLink} to="/rotation">
|
||||
Rotation
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item as={NavLink} exact to="/plans">
|
||||
<Dropdown.Item as={NavLink} to="/plans">
|
||||
Map Planner
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item as={NavLink} exact to="/calendar">
|
||||
<Dropdown.Item as={NavLink} to="/calendar">
|
||||
Calendar
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<Dropdown item text="Collections">
|
||||
<Dropdown.Menu style={dropdownStyle}>
|
||||
<Dropdown.Item as={NavLink} exact to="/builds">
|
||||
<Dropdown.Item as={NavLink} to="/builds">
|
||||
Builds
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<Dropdown item text="X Rank">
|
||||
<Dropdown.Menu style={dropdownStyle}>
|
||||
<Dropdown.Item as={NavLink} exact to="/xleaderboard">
|
||||
<Dropdown.Item as={NavLink} to="/xleaderboard">
|
||||
Leaderboards
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item as={NavLink} exact to="/xsearch">
|
||||
<Dropdown.Item as={NavLink} to="/xsearch">
|
||||
Top 500 Browser
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item as={NavLink} exact to="/trends">
|
||||
<Dropdown.Item as={NavLink} to="/trends">
|
||||
Trends
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
|
||||
8
react-ui/src/components/root/Routes.js
vendored
@@ -5,6 +5,8 @@ import Loading from "../common/Loading"
|
||||
const MapListGenerator = lazy(() => import("../maps/MapListGenerator"))
|
||||
const Rotations = lazy(() => import("../rotation/Rotations"))
|
||||
const MapPlanner = lazy(() => import("../plans/MapPlanner"))
|
||||
const Calendar = lazy(() => import("../calendar/Calendar"))
|
||||
const XLeaderboard = lazy(() => import("../xleaderboard/XLeaderboard"))
|
||||
|
||||
const Routes = () => {
|
||||
return (
|
||||
@@ -19,6 +21,12 @@ const Routes = () => {
|
||||
<Route path="/plans">
|
||||
<MapPlanner />
|
||||
</Route>
|
||||
<Route path="/calendar">
|
||||
<Calendar />
|
||||
</Route>
|
||||
<Route path="/xleaderboard">
|
||||
<XLeaderboard />
|
||||
</Route>
|
||||
</Switch>
|
||||
</Suspense>
|
||||
)
|
||||
|
||||
72
react-ui/src/components/xleaderboard/FlexLeaderboard.js
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
import React, { useEffect } from "react"
|
||||
import { Table, Icon, Popup, Segment } from "semantic-ui-react"
|
||||
import { useQuery } from "@apollo/react-hooks"
|
||||
import { Link } from "react-router-dom"
|
||||
|
||||
import { topFlex } from "../../graphql/queries/topFlex"
|
||||
import Error from "../common/Error"
|
||||
import Loading from "../common/Loading"
|
||||
|
||||
const FlexLeaderboard = () => {
|
||||
useEffect(() => {
|
||||
document.title = "Flex Leaderboard - sendou.ink"
|
||||
}, [])
|
||||
const result = useQuery(topFlex)
|
||||
|
||||
if (result.loading) {
|
||||
return (
|
||||
<div style={{ paddingTop: "2em" }}>
|
||||
<Loading />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (result.error) {
|
||||
return <Error />
|
||||
}
|
||||
const leaderboard = result.data["topFlex"]
|
||||
|
||||
return (
|
||||
<Table basic="very">
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell></Table.HeaderCell>
|
||||
<Table.HeaderCell>Name</Table.HeaderCell>
|
||||
<Table.HeaderCell>
|
||||
Power
|
||||
<Popup
|
||||
trigger={<Icon name="question circle" />}
|
||||
content="Flex Power is the amount of unique weapons the player has reached top 500 with. Different kits count as unique weapons but reskins (e.g. Tentatek & Octoshot) don't."
|
||||
position="bottom center"
|
||||
/>
|
||||
</Table.HeaderCell>
|
||||
<Table.HeaderCell>Total Power</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
|
||||
<Table.Body>
|
||||
{leaderboard.map((player, index) => (
|
||||
<Table.Row key={player.id}>
|
||||
<Table.Cell>{index + 1}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Link
|
||||
to={`/xsearch/p/${player.unique_id}`}
|
||||
style={{ color: "black" }}
|
||||
>
|
||||
<u>{player.alias ? player.alias : player.name}</u>
|
||||
</Link>
|
||||
{player.twitter ? (
|
||||
<a href={`https://twitter.com/${player.twitter}`}>
|
||||
<Icon style={{ paddingLeft: "5px" }} name="twitter" />
|
||||
</a>
|
||||
) : null}
|
||||
</Table.Cell>
|
||||
<Table.Cell>{player.weaponsCount}</Table.Cell>
|
||||
<Table.Cell>{player.topTotalScore}</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)
|
||||
}
|
||||
|
||||
export default FlexLeaderboard
|
||||
33
react-ui/src/components/xleaderboard/FourWeapons.js
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import React from "react"
|
||||
import { Popup } from "semantic-ui-react"
|
||||
import weaponDict from "../../utils/english_internal.json"
|
||||
import { modes, months } from "../../utils/lists"
|
||||
|
||||
const FourWeapons = ({ weapons }) => {
|
||||
return (
|
||||
<>
|
||||
{weapons.map(w => {
|
||||
const mode = modes[w.mode]
|
||||
const month = months[w.month]
|
||||
return (
|
||||
<Popup
|
||||
key={`${mode}${month}${w.year}`}
|
||||
trigger={
|
||||
<img
|
||||
style={{ height: "60px", width: "60px" }}
|
||||
src={`https://raw.githubusercontent.com/Leanny/leanny.github.io/master/splat2/weapons/Wst_${
|
||||
weaponDict[w["weapon"]]
|
||||
}.png`}
|
||||
alt={w.name}
|
||||
/>
|
||||
}
|
||||
header={w.name}
|
||||
content={`${w.x_power} (${w.rank} ${mode} - ${month} ${w.year})`}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default FourWeapons
|
||||
77
react-ui/src/components/xleaderboard/WeaponLeaderboard.js
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
import React, { useEffect } from "react"
|
||||
import { Table, Icon, Popup } from "semantic-ui-react"
|
||||
import { useQuery } from "@apollo/react-hooks"
|
||||
import { Link } from "react-router-dom"
|
||||
|
||||
import FourWeapons from "./FourWeapons"
|
||||
import Loading from "../common/Loading"
|
||||
import Error from "../common/Error"
|
||||
|
||||
const WeaponLeaderboard = ({ query, queryName, scoreField, weaponsField }) => {
|
||||
useEffect(() => {
|
||||
document.title = `${weaponsField.substring(3)} Leaderboard - sendou.ink`
|
||||
}, [weaponsField])
|
||||
|
||||
const result = useQuery(query)
|
||||
|
||||
if (result.loading) {
|
||||
return (
|
||||
<div style={{ paddingTop: "2em" }}>
|
||||
<Loading />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (result.error) {
|
||||
return <Error />
|
||||
}
|
||||
|
||||
const leaderboard = result.data[queryName]
|
||||
return (
|
||||
<div style={{ margin: "1.5em" }}>
|
||||
<Table basic="very">
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell />
|
||||
<Table.HeaderCell>Name</Table.HeaderCell>
|
||||
<Table.HeaderCell>
|
||||
Power
|
||||
<Popup
|
||||
trigger={<Icon name="question circle" />}
|
||||
content="Leaderboard explanation"
|
||||
position="bottom center"
|
||||
/>
|
||||
</Table.HeaderCell>
|
||||
<Table.HeaderCell>Weapons</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
|
||||
<Table.Body>
|
||||
{leaderboard.map((player, index) => (
|
||||
<Table.Row key={player.id}>
|
||||
<Table.Cell>{index + 1}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Link
|
||||
to={`/xsearch/p/${player.unique_id}`}
|
||||
style={{ color: "black" }}
|
||||
>
|
||||
<u>{player.alias ? player.alias : player.name}</u>
|
||||
</Link>
|
||||
{player.twitter ? (
|
||||
<a href={`https://twitter.com/${player.twitter}`}>
|
||||
<Icon style={{ paddingLeft: "5px" }} name="twitter" />
|
||||
</a>
|
||||
) : null}
|
||||
</Table.Cell>
|
||||
<Table.Cell>{player[scoreField]}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<FourWeapons weapons={player[weaponsField]} />
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default WeaponLeaderboard
|
||||
14
react-ui/src/components/xleaderboard/XLeaderboard.js
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from "react"
|
||||
import XLeaderBoardMenu from "./XLeaderboardMenu"
|
||||
import XLeaderboardRoutes from "./XLeaderboardRoutes"
|
||||
|
||||
const XLeaderboard = () => {
|
||||
return (
|
||||
<>
|
||||
<XLeaderBoardMenu />
|
||||
<XLeaderboardRoutes />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default XLeaderboard
|
||||
215
react-ui/src/components/xleaderboard/XLeaderboardMenu.js
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
import React from "react"
|
||||
import { Menu, Responsive } from "semantic-ui-react"
|
||||
import { NavLink } from "react-router-dom"
|
||||
|
||||
import allIcon from "../../assets/xleaderboardIcons/all.png"
|
||||
import flexIcon from "../../assets/xleaderboardIcons/flex.png"
|
||||
import blasterIcon from "../../assets/xleaderboardIcons/blasters.png"
|
||||
import brellaIcon from "../../assets/xleaderboardIcons/brellas.png"
|
||||
import chargerIcon from "../../assets/xleaderboardIcons/chargers.png"
|
||||
import dualieIcon from "../../assets/xleaderboardIcons/dualies.png"
|
||||
import rollerIcon from "../../assets/xleaderboardIcons/rollers.png"
|
||||
import shooterIcon from "../../assets/xleaderboardIcons/shooters.png"
|
||||
import slosherIcon from "../../assets/xleaderboardIcons/sloshers.png"
|
||||
import splatlingIcon from "../../assets/xleaderboardIcons/splatlings.png"
|
||||
|
||||
const XLeaderBoardMenu = () => {
|
||||
const wpnIcon = {
|
||||
paddingBottom: "5px"
|
||||
}
|
||||
return (
|
||||
<div className="ui centered grid">
|
||||
<div className="center aligned column">
|
||||
<Responsive minWidth={800}>
|
||||
<Menu compact icon="labeled">
|
||||
<Menu.Item name="all" as={NavLink} exact to="/xleaderboard">
|
||||
<img style={wpnIcon} src={allIcon} alt="All Icon" />
|
||||
All
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item name="flex" as={NavLink} exact to="/xleaderboard/flex">
|
||||
<img style={wpnIcon} src={flexIcon} alt="Flex icon" />
|
||||
Flex
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="shooters"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/shooters"
|
||||
>
|
||||
<img style={wpnIcon} src={shooterIcon} alt="Shooter Icon" />
|
||||
Shooters
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="blasters"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/blasters"
|
||||
>
|
||||
<img style={wpnIcon} src={blasterIcon} alt="Blaster Icon" />
|
||||
Blasters
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="rollers"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/rollers"
|
||||
>
|
||||
<img style={wpnIcon} src={rollerIcon} alt="Roller Icon" />
|
||||
Rollers
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="chargers"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/chargers"
|
||||
>
|
||||
<img style={wpnIcon} src={chargerIcon} alt="Charger Icon" />
|
||||
Chargers
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="splatlings"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/splatlings"
|
||||
>
|
||||
<img style={wpnIcon} src={splatlingIcon} alt="Splatling Icon" />
|
||||
Splatlings
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="sloshers"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/sloshers"
|
||||
>
|
||||
<img style={wpnIcon} src={slosherIcon} alt="Slosher Icon" />
|
||||
Sloshers
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="dualies"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/dualies"
|
||||
>
|
||||
<img style={wpnIcon} src={dualieIcon} alt="Dualie Icon" />
|
||||
Dualies
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="brella"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/brellas"
|
||||
>
|
||||
<img style={wpnIcon} src={brellaIcon} alt="Brella Icon" />
|
||||
Brellas
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</Responsive>
|
||||
<Responsive maxWidth={799}>
|
||||
<Menu compact icon="labeled">
|
||||
<Menu.Item name="all" as={NavLink} exact to="/xleaderboard">
|
||||
<img style={wpnIcon} src={allIcon} alt="All Icon" />
|
||||
All
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu.Item name="flex" as={NavLink} exact to="/xleaderboard/flex">
|
||||
<img style={wpnIcon} src={flexIcon} alt="Flex icon" />
|
||||
Flex
|
||||
</Menu.Item>
|
||||
<Menu compact icon="labeled">
|
||||
<Menu.Item
|
||||
name="shooters"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/shooters"
|
||||
>
|
||||
<img style={wpnIcon} src={shooterIcon} alt="Shooter Icon" />
|
||||
Shooters
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="blasters"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/blasters"
|
||||
>
|
||||
<img style={wpnIcon} src={blasterIcon} alt="Blaster Icon" />
|
||||
Blasters
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="rollers"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/rollers"
|
||||
>
|
||||
<img style={wpnIcon} src={rollerIcon} alt="Roller Icon" />
|
||||
Rollers
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="chargers"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/chargers"
|
||||
>
|
||||
<img style={wpnIcon} src={chargerIcon} alt="Charger Icon" />
|
||||
Chargers
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
<Menu compact icon="labeled">
|
||||
<Menu.Item
|
||||
name="splatlings"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/splatlings"
|
||||
>
|
||||
<img style={wpnIcon} src={splatlingIcon} alt="Splatling Icon" />
|
||||
Splatlings
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="sloshers"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/sloshers"
|
||||
>
|
||||
<img style={wpnIcon} src={slosherIcon} alt="Slosher Icon" />
|
||||
Sloshers
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="dualies"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/dualies"
|
||||
>
|
||||
<img style={wpnIcon} src={dualieIcon} alt="Dualie Icon" />
|
||||
Dualies
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
name="brella"
|
||||
as={NavLink}
|
||||
exact
|
||||
to="/xleaderboard/brellas"
|
||||
>
|
||||
<img style={wpnIcon} src={brellaIcon} alt="Brella Icon" />
|
||||
Brellas
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</Responsive>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default XLeaderBoardMenu
|
||||
135
react-ui/src/components/xleaderboard/XLeaderboardRoutes.js
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
import React from "react"
|
||||
import { Route } from "react-router-dom"
|
||||
import WeaponLeaderboard from "./WeaponLeaderboard"
|
||||
import { topTotalPlayers } from "../../graphql/queries/topPlayers"
|
||||
import { topShooterPlayers } from "../../graphql/queries/topShooters"
|
||||
import { topBlasterPlayers } from "../../graphql/queries/topBlasters"
|
||||
import { topBrellaPlayers } from "../../graphql/queries/topBrellas"
|
||||
import { topChargerPlayers } from "../../graphql/queries/topChargers"
|
||||
import { topDualiesPlayers } from "../../graphql/queries/topDualies"
|
||||
import { topRollerPlayers } from "../../graphql/queries/topRollers"
|
||||
import { topSlosherPlayers } from "../../graphql/queries/topSloshers"
|
||||
import { topSplatlingPlayers } from "../../graphql/queries/topSplatlings"
|
||||
import FlexLeaderboard from "./FlexLeaderboard"
|
||||
|
||||
const XLeaderboardRoutes = () => {
|
||||
return (
|
||||
<>
|
||||
<Route
|
||||
exact
|
||||
path="/xleaderboard"
|
||||
render={() => (
|
||||
<WeaponLeaderboard
|
||||
query={topTotalPlayers}
|
||||
queryName="topTotalPlayers"
|
||||
scoreField="topTotalScore"
|
||||
weaponsField="topTotal"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/xleaderboard/flex"
|
||||
render={() => <FlexLeaderboard />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/xleaderboard/shooters"
|
||||
render={() => (
|
||||
<WeaponLeaderboard
|
||||
query={topShooterPlayers}
|
||||
queryName="topShooterPlayers"
|
||||
scoreField="topShooterScore"
|
||||
weaponsField="topShooter"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/xleaderboard/blasters"
|
||||
render={() => (
|
||||
<WeaponLeaderboard
|
||||
query={topBlasterPlayers}
|
||||
queryName="topBlasterPlayers"
|
||||
scoreField="topBlasterScore"
|
||||
weaponsField="topBlaster"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/xleaderboard/rollers"
|
||||
render={() => (
|
||||
<WeaponLeaderboard
|
||||
query={topRollerPlayers}
|
||||
queryName="topRollerPlayers"
|
||||
scoreField="topRollerScore"
|
||||
weaponsField="topRoller"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/xleaderboard/chargers"
|
||||
render={() => (
|
||||
<WeaponLeaderboard
|
||||
query={topChargerPlayers}
|
||||
queryName="topChargerPlayers"
|
||||
scoreField="topChargerScore"
|
||||
weaponsField="topCharger"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/xleaderboard/splatlings"
|
||||
render={() => (
|
||||
<WeaponLeaderboard
|
||||
query={topSplatlingPlayers}
|
||||
queryName="topSplatlingPlayers"
|
||||
scoreField="topSplatlingScore"
|
||||
weaponsField="topSplatling"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/xleaderboard/sloshers"
|
||||
render={() => (
|
||||
<WeaponLeaderboard
|
||||
query={topSlosherPlayers}
|
||||
queryName="topSlosherPlayers"
|
||||
scoreField="topSlosherScore"
|
||||
weaponsField="topSlosher"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/xleaderboard/dualies"
|
||||
render={() => (
|
||||
<WeaponLeaderboard
|
||||
query={topDualiesPlayers}
|
||||
queryName="topDualiesPlayers"
|
||||
scoreField="topDualiesScore"
|
||||
weaponsField="topDualies"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/xleaderboard/brellas"
|
||||
render={() => (
|
||||
<WeaponLeaderboard
|
||||
query={topBrellaPlayers}
|
||||
queryName="topBrellaPlayers"
|
||||
scoreField="topBrellaScore"
|
||||
weaponsField="topBrella"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default XLeaderboardRoutes
|
||||
12
react-ui/src/graphql/queries/links.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const links = gql`
|
||||
{
|
||||
links {
|
||||
title
|
||||
url
|
||||
description
|
||||
type
|
||||
}
|
||||
}
|
||||
`
|
||||
34
react-ui/src/graphql/queries/playerInfo.js
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const playerInfo = gql`
|
||||
query playerInfo($uid: String, $twitter: String) {
|
||||
playerInfo(uid: $uid, twitter: $twitter) {
|
||||
player {
|
||||
name
|
||||
weapons
|
||||
alias
|
||||
twitter
|
||||
discord_id
|
||||
topTotalScore
|
||||
topShooterScore
|
||||
topBlasterScore
|
||||
topRollerScore
|
||||
topChargerScore
|
||||
topSlosherScore
|
||||
topSplatlingScore
|
||||
topDualiesScore
|
||||
topBrellaScore
|
||||
}
|
||||
placements {
|
||||
id
|
||||
name
|
||||
weapon
|
||||
rank
|
||||
mode
|
||||
x_power
|
||||
month
|
||||
year
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
16
react-ui/src/graphql/queries/seachForTrend.js
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const searchForTrend = gql`
|
||||
query searchForTrend($weapon: String!) {
|
||||
searchForTrend(weapon: $weapon) {
|
||||
weapon
|
||||
counts {
|
||||
year
|
||||
SZ
|
||||
TC
|
||||
RM
|
||||
CB
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
16
react-ui/src/graphql/queries/searchForBuilds.js
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const searchForBuilds = gql`
|
||||
query searchForBuilds($discord_id: String!) {
|
||||
searchForBuilds(discord_id: $discord_id) {
|
||||
id
|
||||
weapon
|
||||
title
|
||||
headgear
|
||||
clothing
|
||||
shoes
|
||||
updatedAt
|
||||
top
|
||||
}
|
||||
}
|
||||
`
|
||||
23
react-ui/src/graphql/queries/searchForBuildsByWeapon.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const searchForBuildsByWeapon = gql`
|
||||
query searchForBuildsByWeapon($weapon: String!, $page: Int) {
|
||||
searchForBuildsByWeapon(weapon: $weapon, page: $page) {
|
||||
builds {
|
||||
id
|
||||
discord_id
|
||||
top
|
||||
headgear
|
||||
clothing
|
||||
shoes
|
||||
title
|
||||
updatedAt
|
||||
discord_user {
|
||||
username
|
||||
discriminator
|
||||
}
|
||||
}
|
||||
pageCount
|
||||
}
|
||||
}
|
||||
`
|
||||
40
react-ui/src/graphql/queries/searchForPlacements.js
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const searchForPlacements = gql`
|
||||
query searchForPlacements(
|
||||
$name: String
|
||||
$weapon: String
|
||||
$mode: Int
|
||||
$unique_id: String
|
||||
$month: Int
|
||||
$year: Int
|
||||
$page: Int
|
||||
) {
|
||||
searchForPlacements(
|
||||
name: $name
|
||||
weapon: $weapon
|
||||
mode: $mode
|
||||
unique_id: $unique_id
|
||||
month: $month
|
||||
year: $year
|
||||
page: $page
|
||||
) {
|
||||
placements {
|
||||
name
|
||||
x_power
|
||||
weapon
|
||||
rank
|
||||
id
|
||||
unique_id
|
||||
month
|
||||
year
|
||||
mode
|
||||
player {
|
||||
twitter
|
||||
}
|
||||
}
|
||||
pageCount
|
||||
}
|
||||
}
|
||||
|
||||
`
|
||||
12
react-ui/src/graphql/queries/searchForPlayers.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const searchForPlayers = gql`
|
||||
query searchForPlayers($name: String!, $exact: Boolean) {
|
||||
searchForPlayers(name: $name, exact: $exact) {
|
||||
name
|
||||
x_power
|
||||
weapon
|
||||
unique_id
|
||||
}
|
||||
}
|
||||
`
|
||||
14
react-ui/src/graphql/queries/searchForUser.js
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const searchForUser = gql`
|
||||
query searchForUser($discord_id: String) {
|
||||
searchForUser(discord_id: $discord_id) {
|
||||
username
|
||||
discriminator
|
||||
discord_id
|
||||
avatar
|
||||
twitch_name
|
||||
twitter_name
|
||||
}
|
||||
}
|
||||
`
|
||||
23
react-ui/src/graphql/queries/topBlasters.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const topBlasterPlayers = gql`
|
||||
{
|
||||
topBlasterPlayers {
|
||||
id
|
||||
unique_id
|
||||
name
|
||||
alias
|
||||
twitter
|
||||
topBlasterScore
|
||||
topBlaster {
|
||||
name
|
||||
weapon
|
||||
mode
|
||||
x_power
|
||||
rank
|
||||
month
|
||||
year
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
23
react-ui/src/graphql/queries/topBrellas.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const topBrellaPlayers = gql`
|
||||
{
|
||||
topBrellaPlayers {
|
||||
id
|
||||
unique_id
|
||||
name
|
||||
alias
|
||||
twitter
|
||||
topBrellaScore
|
||||
topBrella {
|
||||
name
|
||||
weapon
|
||||
mode
|
||||
x_power
|
||||
rank
|
||||
month
|
||||
year
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
23
react-ui/src/graphql/queries/topChargers.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const topChargerPlayers = gql`
|
||||
{
|
||||
topChargerPlayers {
|
||||
id
|
||||
unique_id
|
||||
name
|
||||
alias
|
||||
twitter
|
||||
topChargerScore
|
||||
topCharger {
|
||||
name
|
||||
weapon
|
||||
mode
|
||||
x_power
|
||||
rank
|
||||
month
|
||||
year
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
23
react-ui/src/graphql/queries/topDualies.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const topDualiesPlayers = gql`
|
||||
{
|
||||
topDualiesPlayers {
|
||||
id
|
||||
unique_id
|
||||
name
|
||||
alias
|
||||
twitter
|
||||
topDualiesScore
|
||||
topDualies {
|
||||
name
|
||||
weapon
|
||||
mode
|
||||
x_power
|
||||
rank
|
||||
month
|
||||
year
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
15
react-ui/src/graphql/queries/topFlex.js
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const topFlex = gql`
|
||||
{
|
||||
topFlex {
|
||||
id
|
||||
unique_id
|
||||
name
|
||||
alias
|
||||
twitter
|
||||
weaponsCount
|
||||
topTotalScore
|
||||
}
|
||||
}
|
||||
`
|
||||
23
react-ui/src/graphql/queries/topPlayers.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const topTotalPlayers = gql`
|
||||
{
|
||||
topTotalPlayers {
|
||||
id
|
||||
unique_id
|
||||
name
|
||||
alias
|
||||
twitter
|
||||
topTotalScore
|
||||
topTotal {
|
||||
name
|
||||
weapon
|
||||
mode
|
||||
x_power
|
||||
rank
|
||||
month
|
||||
year
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
19
react-ui/src/graphql/queries/topPlayersOfWeapon.js
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const topPlayersOfWeapon = gql`
|
||||
query topPlayers($weapon: String!) {
|
||||
topPlayers(weapon: $weapon) {
|
||||
modeCount
|
||||
placements {
|
||||
id
|
||||
name
|
||||
rank
|
||||
mode
|
||||
x_power
|
||||
unique_id
|
||||
month
|
||||
year
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
23
react-ui/src/graphql/queries/topRollers.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const topRollerPlayers = gql`
|
||||
{
|
||||
topRollerPlayers {
|
||||
id
|
||||
unique_id
|
||||
name
|
||||
alias
|
||||
twitter
|
||||
topRollerScore
|
||||
topRoller {
|
||||
name
|
||||
weapon
|
||||
mode
|
||||
x_power
|
||||
rank
|
||||
month
|
||||
year
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
23
react-ui/src/graphql/queries/topShooters.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const topShooterPlayers = gql`
|
||||
{
|
||||
topShooterPlayers {
|
||||
id
|
||||
unique_id
|
||||
name
|
||||
alias
|
||||
twitter
|
||||
topShooterScore
|
||||
topShooter {
|
||||
name
|
||||
weapon
|
||||
mode
|
||||
x_power
|
||||
rank
|
||||
month
|
||||
year
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
23
react-ui/src/graphql/queries/topSloshers.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const topSlosherPlayers = gql`
|
||||
{
|
||||
topSlosherPlayers {
|
||||
id
|
||||
unique_id
|
||||
name
|
||||
alias
|
||||
twitter
|
||||
topSlosherScore
|
||||
topSlosher {
|
||||
name
|
||||
weapon
|
||||
mode
|
||||
x_power
|
||||
rank
|
||||
month
|
||||
year
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
23
react-ui/src/graphql/queries/topSplatlings.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const topSplatlingPlayers = gql`
|
||||
{
|
||||
topSplatlingPlayers {
|
||||
id
|
||||
unique_id
|
||||
name
|
||||
alias
|
||||
twitter
|
||||
topSplatlingScore
|
||||
topSplatling {
|
||||
name
|
||||
weapon
|
||||
mode
|
||||
x_power
|
||||
rank
|
||||
month
|
||||
year
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
11
react-ui/src/graphql/queries/userLean.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const userLean = gql`
|
||||
{
|
||||
user {
|
||||
username
|
||||
avatar
|
||||
discord_id
|
||||
}
|
||||
}
|
||||
`
|
||||
7
react-ui/src/index.js
vendored
@@ -8,7 +8,12 @@ import { BrowserRouter as Router } from "react-router-dom"
|
||||
import "semantic-ui-css/semantic.min.css"
|
||||
import "./index.css"
|
||||
|
||||
const client = new ApolloClient({ uri: "https://www.sendou.ink/graphql" })
|
||||
const client = new ApolloClient({
|
||||
uri:
|
||||
process.env.REACT_APP_APOLLO_URI === "local"
|
||||
? "http://localhost:3001/graphql"
|
||||
: "https://www.sendou.ink/graphql"
|
||||
})
|
||||
|
||||
ReactDOM.render(
|
||||
<Router>
|
||||
|
||||
24
react-ui/src/utils/lists.js
vendored
@@ -1,3 +1,27 @@
|
||||
export const modes = [
|
||||
"",
|
||||
"Splat Zones",
|
||||
"Tower Control",
|
||||
"Rainmaker",
|
||||
"Clam Blitz"
|
||||
]
|
||||
|
||||
export const months = [
|
||||
"",
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December"
|
||||
]
|
||||
|
||||
export const weapons = [
|
||||
"Sploosh-o-matic",
|
||||
"Neo Sploosh-o-matic",
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
const { UserInputError, AuthenticationError, gql } = require('apollo-server-express')
|
||||
const Player = require('../models/player')
|
||||
const User = require('../models/user')
|
||||
const {
|
||||
UserInputError,
|
||||
AuthenticationError,
|
||||
gql
|
||||
} = require("apollo-server-express")
|
||||
const Player = require("../models/player")
|
||||
const User = require("../models/user")
|
||||
|
||||
const typeDef = gql`
|
||||
extend type Query {
|
||||
playerCount: Int!
|
||||
topTotalPlayers (amount: Int): [Player!]!
|
||||
topShooterPlayers (amount: Int): [Player!]!
|
||||
topBlasterPlayers (amount: Int): [Player!]!
|
||||
topRollerPlayers (amount: Int): [Player!]!
|
||||
topChargerPlayers (amount: Int): [Player!]!
|
||||
topSlosherPlayers (amount: Int): [Player!]!
|
||||
topSplatlingPlayers (amount: Int): [Player!]!
|
||||
topDualiesPlayers (amount: Int): [Player!]!
|
||||
topBrellaPlayers (amount: Int): [Player!]!
|
||||
topTotalPlayers(amount: Int): [Player!]!
|
||||
topShooterPlayers(amount: Int): [Player!]!
|
||||
topBlasterPlayers(amount: Int): [Player!]!
|
||||
topRollerPlayers(amount: Int): [Player!]!
|
||||
topChargerPlayers(amount: Int): [Player!]!
|
||||
topSlosherPlayers(amount: Int): [Player!]!
|
||||
topSplatlingPlayers(amount: Int): [Player!]!
|
||||
topDualiesPlayers(amount: Int): [Player!]!
|
||||
topBrellaPlayers(amount: Int): [Player!]!
|
||||
topFlex: [Player!]!
|
||||
}
|
||||
extend type Mutation {
|
||||
updateTwitter(
|
||||
unique_id: String!
|
||||
twitter: String!
|
||||
): Boolean
|
||||
updateTwitter(unique_id: String!, twitter: String!): Boolean
|
||||
}
|
||||
type Player {
|
||||
id: ID!
|
||||
@@ -47,30 +49,38 @@ const typeDef = gql`
|
||||
topDualiesScore: Float
|
||||
topBrella: [Placement]
|
||||
topBrellaScore: Float
|
||||
weaponsCount: Int
|
||||
}
|
||||
`
|
||||
const resolvers = {
|
||||
Query: {
|
||||
playerCount: () => Player.collection.countDocuments(),
|
||||
topFlex: async (root, args) => {
|
||||
return Player.find({})
|
||||
.sort({ weaponsCount: "desc", topTotalScore: "desc" })
|
||||
.limit(50)
|
||||
},
|
||||
topTotalPlayers: (root, args) => {
|
||||
if (!args.amount) {
|
||||
args.amount = 50
|
||||
}
|
||||
|
||||
if (args.amount < 1 || args.amount > 50) {
|
||||
throw new UserInputError('amount requested has to be between 1 and 50', {
|
||||
invalidArgs: args,
|
||||
})
|
||||
throw new UserInputError(
|
||||
"amount requested has to be between 1 and 50",
|
||||
{
|
||||
invalidArgs: args
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return Player
|
||||
.find({ topTotalScore: { $ne: null} })
|
||||
.sort({ "topTotalScore": "desc" })
|
||||
|
||||
return Player.find({ topTotalScore: { $ne: null } })
|
||||
.sort({ topTotalScore: "desc" })
|
||||
.limit(args.amount)
|
||||
.populate("topTotal", {"unique_id": 0})
|
||||
.populate("topTotal", { unique_id: 0 })
|
||||
.catch(e => {
|
||||
throw new UserInputError(e.message, {
|
||||
invalidArgs: args,
|
||||
invalidArgs: args
|
||||
})
|
||||
})
|
||||
},
|
||||
@@ -80,16 +90,18 @@ const resolvers = {
|
||||
}
|
||||
|
||||
if (args.amount < 1 || args.amount > 50) {
|
||||
throw new UserInputError('amount requested has to be between 1 and 50', {
|
||||
invalidArgs: args,
|
||||
})
|
||||
throw new UserInputError(
|
||||
"amount requested has to be between 1 and 50",
|
||||
{
|
||||
invalidArgs: args
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return Player
|
||||
.find({ topShooterScore: { $ne: null} })
|
||||
.sort({ "topShooterScore": "desc" })
|
||||
return Player.find({ topShooterScore: { $ne: null } })
|
||||
.sort({ topShooterScore: "desc" })
|
||||
.limit(args.amount)
|
||||
.populate("topShooter", {"unique_id": 0})
|
||||
.populate("topShooter", { unique_id: 0 })
|
||||
},
|
||||
topBlasterPlayers: (root, args) => {
|
||||
if (!args.amount) {
|
||||
@@ -97,16 +109,18 @@ const resolvers = {
|
||||
}
|
||||
|
||||
if (args.amount < 1 || args.amount > 50) {
|
||||
throw new UserInputError('amount requested has to be between 1 and 50', {
|
||||
invalidArgs: args,
|
||||
})
|
||||
throw new UserInputError(
|
||||
"amount requested has to be between 1 and 50",
|
||||
{
|
||||
invalidArgs: args
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return Player
|
||||
.find({ topBlasterScore: { $ne: null} })
|
||||
.sort({ "topBlasterScore": "desc" })
|
||||
return Player.find({ topBlasterScore: { $ne: null } })
|
||||
.sort({ topBlasterScore: "desc" })
|
||||
.limit(args.amount)
|
||||
.populate("topBlaster", {"unique_id": 0})
|
||||
.populate("topBlaster", { unique_id: 0 })
|
||||
},
|
||||
topRollerPlayers: (root, args) => {
|
||||
if (!args.amount) {
|
||||
@@ -114,16 +128,18 @@ const resolvers = {
|
||||
}
|
||||
|
||||
if (args.amount < 1 || args.amount > 50) {
|
||||
throw new UserInputError('amount requested has to be between 1 and 50', {
|
||||
invalidArgs: args,
|
||||
})
|
||||
throw new UserInputError(
|
||||
"amount requested has to be between 1 and 50",
|
||||
{
|
||||
invalidArgs: args
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return Player
|
||||
.find({ topRollerScore: { $ne: null} })
|
||||
.sort({ "topRollerScore": "desc" })
|
||||
return Player.find({ topRollerScore: { $ne: null } })
|
||||
.sort({ topRollerScore: "desc" })
|
||||
.limit(args.amount)
|
||||
.populate("topRoller", {"unique_id": 0})
|
||||
.populate("topRoller", { unique_id: 0 })
|
||||
},
|
||||
topChargerPlayers: (root, args) => {
|
||||
if (!args.amount) {
|
||||
@@ -131,16 +147,18 @@ const resolvers = {
|
||||
}
|
||||
|
||||
if (args.amount < 1 || args.amount > 50) {
|
||||
throw new UserInputError('amount requested has to be between 1 and 50', {
|
||||
invalidArgs: args,
|
||||
})
|
||||
throw new UserInputError(
|
||||
"amount requested has to be between 1 and 50",
|
||||
{
|
||||
invalidArgs: args
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return Player
|
||||
.find({ topChargerScore: { $ne: null} })
|
||||
.sort({ "topChargerScore": "desc" })
|
||||
return Player.find({ topChargerScore: { $ne: null } })
|
||||
.sort({ topChargerScore: "desc" })
|
||||
.limit(args.amount)
|
||||
.populate("topCharger", {"unique_id": 0})
|
||||
.populate("topCharger", { unique_id: 0 })
|
||||
},
|
||||
topSlosherPlayers: (root, args) => {
|
||||
if (!args.amount) {
|
||||
@@ -148,16 +166,18 @@ const resolvers = {
|
||||
}
|
||||
|
||||
if (args.amount < 1 || args.amount > 50) {
|
||||
throw new UserInputError('amount requested has to be between 1 and 50', {
|
||||
invalidArgs: args,
|
||||
})
|
||||
throw new UserInputError(
|
||||
"amount requested has to be between 1 and 50",
|
||||
{
|
||||
invalidArgs: args
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return Player
|
||||
.find({ topSlosherScore: { $ne: null} })
|
||||
.sort({ "topSlosherScore": "desc" })
|
||||
return Player.find({ topSlosherScore: { $ne: null } })
|
||||
.sort({ topSlosherScore: "desc" })
|
||||
.limit(args.amount)
|
||||
.populate("topSlosher", {"unique_id": 0})
|
||||
.populate("topSlosher", { unique_id: 0 })
|
||||
},
|
||||
topSplatlingPlayers: (root, args) => {
|
||||
if (!args.amount) {
|
||||
@@ -165,16 +185,18 @@ const resolvers = {
|
||||
}
|
||||
|
||||
if (args.amount < 1 || args.amount > 50) {
|
||||
throw new UserInputError('amount requested has to be between 1 and 50', {
|
||||
invalidArgs: args,
|
||||
})
|
||||
throw new UserInputError(
|
||||
"amount requested has to be between 1 and 50",
|
||||
{
|
||||
invalidArgs: args
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return Player
|
||||
.find({ topSplatlingScore: { $ne: null} })
|
||||
.sort({ "topSplatlingScore": "desc" })
|
||||
return Player.find({ topSplatlingScore: { $ne: null } })
|
||||
.sort({ topSplatlingScore: "desc" })
|
||||
.limit(args.amount)
|
||||
.populate("topSplatling", {"unique_id": 0})
|
||||
.populate("topSplatling", { unique_id: 0 })
|
||||
},
|
||||
topDualiesPlayers: (root, args) => {
|
||||
if (!args.amount) {
|
||||
@@ -182,16 +204,18 @@ const resolvers = {
|
||||
}
|
||||
|
||||
if (args.amount < 1 || args.amount > 50) {
|
||||
throw new UserInputError('amount requested has to be between 1 and 50', {
|
||||
invalidArgs: args,
|
||||
})
|
||||
throw new UserInputError(
|
||||
"amount requested has to be between 1 and 50",
|
||||
{
|
||||
invalidArgs: args
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return Player
|
||||
.find({ topDualiesScore: { $ne: null} })
|
||||
.sort({ "topDualiesScore": "desc" })
|
||||
return Player.find({ topDualiesScore: { $ne: null } })
|
||||
.sort({ topDualiesScore: "desc" })
|
||||
.limit(args.amount)
|
||||
.populate("topDualies", {"unique_id": 0})
|
||||
.populate("topDualies", { unique_id: 0 })
|
||||
},
|
||||
topBrellaPlayers: (root, args) => {
|
||||
if (!args.amount) {
|
||||
@@ -199,29 +223,34 @@ const resolvers = {
|
||||
}
|
||||
|
||||
if (args.amount < 1 || args.amount > 50) {
|
||||
throw new UserInputError('amount requested has to be between 1 and 50', {
|
||||
invalidArgs: args,
|
||||
})
|
||||
throw new UserInputError(
|
||||
"amount requested has to be between 1 and 50",
|
||||
{
|
||||
invalidArgs: args
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return Player
|
||||
.find({ topBrellaScore: { $ne: null} })
|
||||
.sort({ "topBrellaScore": "desc" })
|
||||
return Player.find({ topBrellaScore: { $ne: null } })
|
||||
.sort({ topBrellaScore: "desc" })
|
||||
.limit(args.amount)
|
||||
.populate("topBrella", {"unique_id": 0})
|
||||
},
|
||||
.populate("topBrella", { unique_id: 0 })
|
||||
}
|
||||
},
|
||||
Mutation: {
|
||||
updateTwitter: async (root, args, ctx) => {
|
||||
if (ctx.user.discord_id !== process.env.ADMIN_ID) throw new AuthenticationError('not admin')
|
||||
if (ctx.user.discord_id !== process.env.ADMIN_ID)
|
||||
throw new AuthenticationError("not admin")
|
||||
|
||||
const player = await Player.findOne({ unique_id: args.unique_id.trim() }).catch(e => {
|
||||
const player = await Player.findOne({
|
||||
unique_id: args.unique_id.trim()
|
||||
}).catch(e => {
|
||||
throw new UserInputError(e.message, {
|
||||
invalidArgs: args,
|
||||
invalidArgs: args
|
||||
})
|
||||
})
|
||||
|
||||
if (!player) throw new UserInputError
|
||||
if (!player) throw new UserInputError()
|
||||
|
||||
player.twitter = args.twitter.trim().toLowerCase()
|
||||
|
||||
@@ -229,26 +258,27 @@ const resolvers = {
|
||||
await player.save()
|
||||
} catch (error) {
|
||||
throw new UserInputError(error.message, {
|
||||
invalidArgs: args,
|
||||
invalidArgs: args
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
return true
|
||||
}
|
||||
},
|
||||
Player: {
|
||||
discord_id: async (root) => {
|
||||
discord_id: async root => {
|
||||
if (!root.twitter) return null
|
||||
const user = await User
|
||||
.findOne({ twitter_name: root.twitter })
|
||||
.catch(e => {
|
||||
throw new UserInputError, {
|
||||
invalidArgs: args,
|
||||
}
|
||||
})
|
||||
const user = await User.findOne({ twitter_name: root.twitter }).catch(
|
||||
e => {
|
||||
throw (new UserInputError(),
|
||||
{
|
||||
invalidArgs: args
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
if (!user) return null
|
||||
|
||||
|
||||
return user.discord_id
|
||||
}
|
||||
}
|
||||
@@ -257,4 +287,4 @@ const resolvers = {
|
||||
module.exports = {
|
||||
Player: typeDef,
|
||||
playerResolvers: resolvers
|
||||
}
|
||||
}
|
||||
|
||||
3
scripts/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"python.formatting.provider": "black"
|
||||
}
|
||||
462
scripts/xrank.py
@@ -5,50 +5,158 @@ import calendar
|
||||
import pymongo
|
||||
from config import uri
|
||||
|
||||
shooters = ["Sploosh-o-matic", "Neo Sploosh-o-matic", "Sploosh-o-matic 7",
|
||||
"Splattershot Jr.", "Custom Splattershot Jr.", "Kensa Splattershot Jr.",
|
||||
"Splash-o-matic", "Neo Splash-o-matic", "Aerospray MG", "Aerospray RG",
|
||||
"Aerospray PG", "Splattershot", "Tentatek Splattershot", "Kensa Splattershot",
|
||||
".52 Gal", ".52 Gal Deco", "Kensa .52 Gal", "N-ZAP '85", "N-ZAP '89",
|
||||
"N-ZAP '83", "Splattershot Pro", "Forge Splattershot Pro", "Kensa Splattershot Pro",
|
||||
".96 Gal", ".96 Gal Deco", "Jet Squelcher", "Custom Jet Squelcher",
|
||||
"L-3 Nozzlenose", "L-3 Nozzlenose D", "Kensa L-3 Nozzlenose",
|
||||
"H-3 Nozzlenose", "H-3 Nozzlenose D", "Cherry H-3 Nozzlenose", "Squeezer",
|
||||
"Foil Squeezer"]
|
||||
shooters = [
|
||||
"Sploosh-o-matic",
|
||||
"Neo Sploosh-o-matic",
|
||||
"Sploosh-o-matic 7",
|
||||
"Splattershot Jr.",
|
||||
"Custom Splattershot Jr.",
|
||||
"Kensa Splattershot Jr.",
|
||||
"Splash-o-matic",
|
||||
"Neo Splash-o-matic",
|
||||
"Aerospray MG",
|
||||
"Aerospray RG",
|
||||
"Aerospray PG",
|
||||
"Splattershot",
|
||||
"Tentatek Splattershot",
|
||||
"Kensa Splattershot",
|
||||
".52 Gal",
|
||||
".52 Gal Deco",
|
||||
"Kensa .52 Gal",
|
||||
"N-ZAP '85",
|
||||
"N-ZAP '89",
|
||||
"N-ZAP '83",
|
||||
"Splattershot Pro",
|
||||
"Forge Splattershot Pro",
|
||||
"Kensa Splattershot Pro",
|
||||
".96 Gal",
|
||||
".96 Gal Deco",
|
||||
"Jet Squelcher",
|
||||
"Custom Jet Squelcher",
|
||||
"L-3 Nozzlenose",
|
||||
"L-3 Nozzlenose D",
|
||||
"Kensa L-3 Nozzlenose",
|
||||
"H-3 Nozzlenose",
|
||||
"H-3 Nozzlenose D",
|
||||
"Cherry H-3 Nozzlenose",
|
||||
"Squeezer",
|
||||
"Foil Squeezer",
|
||||
]
|
||||
|
||||
blasters = ["Luna Blaster", "Luna Blaster Neo", "Kensa Luna Blaster",
|
||||
"Blaster", "Custom Blaster", "Range Blaster", "Custom Range Blaster",
|
||||
"Grim Range Blaster", "Rapid Blaster", "Rapid Blaster Deco", "Kensa Rapid Blaster",
|
||||
"Rapid Blaster Pro", "Rapid Blaster Pro Deco", "Clash Blaster", "Clash Blaster Neo"]
|
||||
blasters = [
|
||||
"Luna Blaster",
|
||||
"Luna Blaster Neo",
|
||||
"Kensa Luna Blaster",
|
||||
"Blaster",
|
||||
"Custom Blaster",
|
||||
"Range Blaster",
|
||||
"Custom Range Blaster",
|
||||
"Grim Range Blaster",
|
||||
"Rapid Blaster",
|
||||
"Rapid Blaster Deco",
|
||||
"Kensa Rapid Blaster",
|
||||
"Rapid Blaster Pro",
|
||||
"Rapid Blaster Pro Deco",
|
||||
"Clash Blaster",
|
||||
"Clash Blaster Neo",
|
||||
]
|
||||
|
||||
rollers = ["Carbon Roller", "Carbon Roller Deco", "Splat Roller", "Krak-On Splat Roller",
|
||||
"Kensa Splat Roller", "Dynamo Roller", "Gold Dynamo Roller", "Kensa Dynamo Roller",
|
||||
"Flingza Roller", "Foil Flingza Roller", "Inkbrush", "Inkbrush Nouveau",
|
||||
"Permanent Inkbrush", "Octobrush", "Octobrush Nouveau", "Kensa Octobrush"]
|
||||
rollers = [
|
||||
"Carbon Roller",
|
||||
"Carbon Roller Deco",
|
||||
"Splat Roller",
|
||||
"Krak-On Splat Roller",
|
||||
"Kensa Splat Roller",
|
||||
"Dynamo Roller",
|
||||
"Gold Dynamo Roller",
|
||||
"Kensa Dynamo Roller",
|
||||
"Flingza Roller",
|
||||
"Foil Flingza Roller",
|
||||
"Inkbrush",
|
||||
"Inkbrush Nouveau",
|
||||
"Permanent Inkbrush",
|
||||
"Octobrush",
|
||||
"Octobrush Nouveau",
|
||||
"Kensa Octobrush",
|
||||
]
|
||||
|
||||
chargers = ["Classic Squiffer", "New Squiffer", "Fresh Squiffer", "Splat Charger",
|
||||
"Firefin Splat Charger", "Kensa Charger", "Splatterscope", "Firefin Splatterscope",
|
||||
"Kensa Splatterscope", "E-liter 4K", "Custom E-liter 4K", "E-liter 4K Scope",
|
||||
"Custom E-liter 4K Scope", "Bamboozler 14 Mk I", "Bamboozler 14 Mk II",
|
||||
"Bamboozler 14 Mk III", "Goo Tuber", "Custom Goo Tuber"]
|
||||
chargers = [
|
||||
"Classic Squiffer",
|
||||
"New Squiffer",
|
||||
"Fresh Squiffer",
|
||||
"Splat Charger",
|
||||
"Firefin Splat Charger",
|
||||
"Kensa Charger",
|
||||
"Splatterscope",
|
||||
"Firefin Splatterscope",
|
||||
"Kensa Splatterscope",
|
||||
"E-liter 4K",
|
||||
"Custom E-liter 4K",
|
||||
"E-liter 4K Scope",
|
||||
"Custom E-liter 4K Scope",
|
||||
"Bamboozler 14 Mk I",
|
||||
"Bamboozler 14 Mk II",
|
||||
"Bamboozler 14 Mk III",
|
||||
"Goo Tuber",
|
||||
"Custom Goo Tuber",
|
||||
]
|
||||
|
||||
sloshers = ["Slosher", "Slosher Deco", "Soda Slosher", "Tri-Slosher",
|
||||
"Tri-Slosher Nouveau", "Sloshing Machine", "Sloshing Machine Neo",
|
||||
"Kensa Sloshing Machine", "Bloblobber", "Bloblobber Deco", "Explosher",
|
||||
"Custom Explosher"]
|
||||
sloshers = [
|
||||
"Slosher",
|
||||
"Slosher Deco",
|
||||
"Soda Slosher",
|
||||
"Tri-Slosher",
|
||||
"Tri-Slosher Nouveau",
|
||||
"Sloshing Machine",
|
||||
"Sloshing Machine Neo",
|
||||
"Kensa Sloshing Machine",
|
||||
"Bloblobber",
|
||||
"Bloblobber Deco",
|
||||
"Explosher",
|
||||
"Custom Explosher",
|
||||
]
|
||||
|
||||
splatlings = ["Mini Splatling", "Zink Mini Splatling", "Kensa Mini Splatling",
|
||||
"Heavy Splatling", "Heavy Splatling Deco", "Heavy Splatling Remix",
|
||||
"Hydra Splatling", "Custom Hydra Splatling", "Ballpoint Splatling",
|
||||
"Ballpoint Splatling Nouveau", "Nautilus 47", "Nautilus 79"]
|
||||
splatlings = [
|
||||
"Mini Splatling",
|
||||
"Zink Mini Splatling",
|
||||
"Kensa Mini Splatling",
|
||||
"Heavy Splatling",
|
||||
"Heavy Splatling Deco",
|
||||
"Heavy Splatling Remix",
|
||||
"Hydra Splatling",
|
||||
"Custom Hydra Splatling",
|
||||
"Ballpoint Splatling",
|
||||
"Ballpoint Splatling Nouveau",
|
||||
"Nautilus 47",
|
||||
"Nautilus 79",
|
||||
]
|
||||
|
||||
dualies = ["Dapple Dualies", "Dapple Dualies Nouveau", "Clear Dapple Dualies",
|
||||
"Splat Dualies", "Enperry Splat Dualies", "Kensa Splat Dualies", "Glooga Dualies",
|
||||
"Glooga Dualies Deco", "Kensa Glooga Dualies", "Dualie Squelchers",
|
||||
"Custom Dualie Squelchers", "Dark Tetra Dualies", "Light Tetra Dualies"]
|
||||
dualies = [
|
||||
"Dapple Dualies",
|
||||
"Dapple Dualies Nouveau",
|
||||
"Clear Dapple Dualies",
|
||||
"Splat Dualies",
|
||||
"Enperry Splat Dualies",
|
||||
"Kensa Splat Dualies",
|
||||
"Glooga Dualies",
|
||||
"Glooga Dualies Deco",
|
||||
"Kensa Glooga Dualies",
|
||||
"Dualie Squelchers",
|
||||
"Custom Dualie Squelchers",
|
||||
"Dark Tetra Dualies",
|
||||
"Light Tetra Dualies",
|
||||
]
|
||||
|
||||
brellas = ["Splat Brella", "Sorella Brella", "Tenta Brella", "Tenta Sorella Brella",
|
||||
"Tenta Camo Brella", "Undercover Brella", "Undercover Sorella Brella", "Kensa Undercover Brella"]
|
||||
brellas = [
|
||||
"Splat Brella",
|
||||
"Sorella Brella",
|
||||
"Tenta Brella",
|
||||
"Tenta Sorella Brella",
|
||||
"Tenta Camo Brella",
|
||||
"Undercover Brella",
|
||||
"Undercover Sorella Brella",
|
||||
"Kensa Undercover Brella",
|
||||
]
|
||||
|
||||
client = pymongo.MongoClient(uri)
|
||||
db = client.production
|
||||
@@ -57,136 +165,162 @@ script_dir = os.path.dirname(__file__)
|
||||
rel_path = "xrank_data/*.json"
|
||||
abs_file_path = os.path.join(script_dir, rel_path)
|
||||
|
||||
year = 2019 # needs to be updated manually when we process data from different years
|
||||
year = 2019 # needs to be updated manually when we process data from different years
|
||||
|
||||
|
||||
def resolve_top_array(key_name, player, result, x_power):
|
||||
if key_name not in player:
|
||||
player[key_name] = [result.inserted_id]
|
||||
else:
|
||||
if len(player[key_name]) <= 3:
|
||||
player[key_name].append(result.inserted_id)
|
||||
if key_name not in player:
|
||||
player[key_name] = [result.inserted_id]
|
||||
else:
|
||||
lowest_power = 10000
|
||||
lowest_power_index = -1
|
||||
sum_of_powers = x_power
|
||||
for index, placement_id in enumerate(player[key_name]):
|
||||
high_placement = db.placements.find_one({ "_id": placement_id })
|
||||
if high_placement is None:
|
||||
raise ValueError(f'Placement id {placement_id} not found in the database.')
|
||||
sum_of_powers += high_placement["x_power"]
|
||||
if high_placement["x_power"] < x_power:
|
||||
if high_placement["x_power"] < lowest_power:
|
||||
lowest_power = high_placement["x_power"]
|
||||
lowest_power_index = index
|
||||
|
||||
if lowest_power_index != -1:
|
||||
player[key_name][lowest_power_index] = result.inserted_id
|
||||
sum_of_powers -= lowest_power
|
||||
power_score = round((sum_of_powers / 4), 1)
|
||||
player[f"{key_name}Score"] = power_score
|
||||
return player
|
||||
|
||||
for filepath in glob.iglob(abs_file_path): # iterate through .json files in the xrank_data folder
|
||||
if filepath.endswith(".json"):
|
||||
path_without_folder = filepath.replace("xrank_data\\", "")
|
||||
file_parts = path_without_folder.split("_")
|
||||
print(path_without_folder)
|
||||
month = list(calendar.month_name).index(file_parts[0].capitalize())
|
||||
|
||||
if "splat" in file_parts[1]:
|
||||
mode = 1
|
||||
elif "tower" in file_parts[1]:
|
||||
mode = 2
|
||||
elif "rainmaker" in file_parts[1]:
|
||||
mode = 3
|
||||
else:
|
||||
mode = 4
|
||||
with open(filepath) as f:
|
||||
data = json.load(f)
|
||||
for placement in data:
|
||||
if placement["cheater"]:
|
||||
continue
|
||||
|
||||
rank = placement["rank"]
|
||||
if rank > 500:
|
||||
break
|
||||
|
||||
name = placement["name"]
|
||||
x_power = placement["x_power"]
|
||||
unique_id = placement["unique_id"]
|
||||
|
||||
weapon = placement["weapon"]["name"].strip()
|
||||
# If weapon is one of the reskins it gets converted to the regular version
|
||||
if weapon == "Hero Shot Replica":
|
||||
weapon = "Splattershot"
|
||||
elif weapon == "Octo Shot Replica":
|
||||
weapon = "Tentatek Splattershot"
|
||||
elif weapon == "Hero Blaster Replica":
|
||||
weapon = "Blaster"
|
||||
elif weapon == "Hero Roller Replica":
|
||||
weapon = "Splat Roller"
|
||||
elif weapon == "Herobrush Replica":
|
||||
weapon = "Octobrush"
|
||||
elif weapon == "Hero Charger Replica":
|
||||
weapon = "Splat Charger"
|
||||
elif weapon == "Hero Slosher Replica":
|
||||
weapon = "Slosher"
|
||||
elif weapon == "Hero Splatling Replica":
|
||||
weapon = "Heavy Splatling"
|
||||
elif weapon == "Hero Dualie Replicas":
|
||||
weapon = "Splat Dualies"
|
||||
elif weapon == "Hero Brella Replica":
|
||||
weapon = "Splat Brella"
|
||||
|
||||
print(f"{month} {year} - {mode} - {name} {unique_id} {rank} {x_power} {weapon}")
|
||||
|
||||
placement_document = {"name": name,
|
||||
"weapon": weapon,
|
||||
"rank": rank,
|
||||
"mode": mode,
|
||||
"x_power": x_power,
|
||||
"unique_id": unique_id,
|
||||
"month": month,
|
||||
"year": year}
|
||||
|
||||
result = db.placements.insert_one(placement_document)
|
||||
|
||||
player = db.players.find_one({ "unique_id": unique_id })
|
||||
|
||||
if player is None:
|
||||
player = {"name": name,
|
||||
"unique_id": unique_id,
|
||||
"weapons": [weapon]}
|
||||
if len(player[key_name]) <= 3:
|
||||
player[key_name].append(result.inserted_id)
|
||||
else:
|
||||
player["name"] = name
|
||||
playerWeapons = player["weapons"]
|
||||
playerWeapons.append(weapon)
|
||||
player["weapons"] = list(dict.fromkeys(playerWeapons))
|
||||
|
||||
player = resolve_top_array("topTotal", player, result, x_power)
|
||||
|
||||
if weapon in shooters:
|
||||
player = resolve_top_array("topShooter", player, result, x_power)
|
||||
elif weapon in blasters:
|
||||
player = resolve_top_array("topBlaster", player, result, x_power)
|
||||
elif weapon in rollers:
|
||||
player = resolve_top_array("topRoller", player, result, x_power)
|
||||
elif weapon in chargers:
|
||||
player = resolve_top_array("topCharger", player, result, x_power)
|
||||
elif weapon in sloshers:
|
||||
player = resolve_top_array("topSlosher", player, result, x_power)
|
||||
elif weapon in splatlings:
|
||||
player = resolve_top_array("topSplatling", player, result, x_power)
|
||||
elif weapon in dualies:
|
||||
player = resolve_top_array("topDualies", player, result, x_power)
|
||||
elif weapon in brellas:
|
||||
player = resolve_top_array("topBrella", player, result, x_power)
|
||||
else:
|
||||
raise ValueError(f'Weapon "{weapon}"doesn\'t belong in any category')
|
||||
lowest_power = 10000
|
||||
lowest_power_index = -1
|
||||
sum_of_powers = x_power
|
||||
for index, placement_id in enumerate(player[key_name]):
|
||||
high_placement = db.placements.find_one({"_id": placement_id})
|
||||
if high_placement is None:
|
||||
raise ValueError(
|
||||
f"Placement id {placement_id} not found in the database."
|
||||
)
|
||||
sum_of_powers += high_placement["x_power"]
|
||||
if high_placement["x_power"] < x_power:
|
||||
if high_placement["x_power"] < lowest_power:
|
||||
lowest_power = high_placement["x_power"]
|
||||
lowest_power_index = index
|
||||
|
||||
if len(player["topTotal"]) == 1: # if player was just added
|
||||
db.players.insert_one(player)
|
||||
else:
|
||||
db.players.find_one_and_replace({"unique_id": unique_id}, player)
|
||||
if lowest_power_index != -1:
|
||||
player[key_name][lowest_power_index] = result.inserted_id
|
||||
sum_of_powers -= lowest_power
|
||||
power_score = round((sum_of_powers / 4), 1)
|
||||
player[f"{key_name}Score"] = power_score
|
||||
return player
|
||||
|
||||
|
||||
|
||||
for filepath in glob.iglob(
|
||||
abs_file_path
|
||||
): # iterate through .json files in the xrank_data folder
|
||||
if filepath.endswith(".json"):
|
||||
path_without_folder = filepath.replace("xrank_data\\", "")
|
||||
file_parts = path_without_folder.split("_")
|
||||
print(path_without_folder)
|
||||
month = list(calendar.month_name).index(file_parts[0].capitalize())
|
||||
|
||||
if "splat" in file_parts[1]:
|
||||
mode = 1
|
||||
elif "tower" in file_parts[1]:
|
||||
mode = 2
|
||||
elif "rainmaker" in file_parts[1]:
|
||||
mode = 3
|
||||
else:
|
||||
mode = 4
|
||||
with open(filepath) as f:
|
||||
data = json.load(f)
|
||||
for placement in data:
|
||||
if placement["cheater"]:
|
||||
continue
|
||||
|
||||
rank = placement["rank"]
|
||||
if rank > 500:
|
||||
break
|
||||
|
||||
name = placement["name"]
|
||||
x_power = placement["x_power"]
|
||||
unique_id = placement["unique_id"]
|
||||
|
||||
weapon = placement["weapon"]["name"].strip()
|
||||
# If weapon is one of the reskins it gets converted to the regular version
|
||||
if weapon == "Hero Shot Replica":
|
||||
weapon = "Splattershot"
|
||||
elif weapon == "Octo Shot Replica":
|
||||
weapon = "Tentatek Splattershot"
|
||||
elif weapon == "Hero Blaster Replica":
|
||||
weapon = "Blaster"
|
||||
elif weapon == "Hero Roller Replica":
|
||||
weapon = "Splat Roller"
|
||||
elif weapon == "Herobrush Replica":
|
||||
weapon = "Octobrush"
|
||||
elif weapon == "Hero Charger Replica":
|
||||
weapon = "Splat Charger"
|
||||
elif weapon == "Hero Slosher Replica":
|
||||
weapon = "Slosher"
|
||||
elif weapon == "Hero Splatling Replica":
|
||||
weapon = "Heavy Splatling"
|
||||
elif weapon == "Hero Dualie Replicas":
|
||||
weapon = "Splat Dualies"
|
||||
elif weapon == "Hero Brella Replica":
|
||||
weapon = "Splat Brella"
|
||||
|
||||
print(
|
||||
f"{month} {year} - {mode} - {name} {unique_id} {rank} {x_power} {weapon}"
|
||||
)
|
||||
|
||||
placement_document = {
|
||||
"name": name,
|
||||
"weapon": weapon,
|
||||
"rank": rank,
|
||||
"mode": mode,
|
||||
"x_power": x_power,
|
||||
"unique_id": unique_id,
|
||||
"month": month,
|
||||
"year": year,
|
||||
}
|
||||
|
||||
result = db.placements.insert_one(placement_document)
|
||||
|
||||
player = db.players.find_one({"unique_id": unique_id})
|
||||
|
||||
if player is None:
|
||||
player = {"name": name, "unique_id": unique_id, "weapons": [weapon]}
|
||||
else:
|
||||
player["name"] = name
|
||||
playerWeapons = player["weapons"]
|
||||
playerWeapons.append(weapon)
|
||||
player["weapons"] = list(dict.fromkeys(playerWeapons))
|
||||
|
||||
player = resolve_top_array("topTotal", player, result, x_power)
|
||||
|
||||
if weapon in shooters:
|
||||
player = resolve_top_array("topShooter", player, result, x_power)
|
||||
elif weapon in blasters:
|
||||
player = resolve_top_array("topBlaster", player, result, x_power)
|
||||
elif weapon in rollers:
|
||||
player = resolve_top_array("topRoller", player, result, x_power)
|
||||
elif weapon in chargers:
|
||||
player = resolve_top_array("topCharger", player, result, x_power)
|
||||
elif weapon in sloshers:
|
||||
player = resolve_top_array("topSlosher", player, result, x_power)
|
||||
elif weapon in splatlings:
|
||||
player = resolve_top_array("topSplatling", player, result, x_power)
|
||||
elif weapon in dualies:
|
||||
player = resolve_top_array("topDualies", player, result, x_power)
|
||||
elif weapon in brellas:
|
||||
player = resolve_top_array("topBrella", player, result, x_power)
|
||||
else:
|
||||
raise ValueError(
|
||||
f'Weapon "{weapon}"doesn\'t belong in any category'
|
||||
)
|
||||
|
||||
if len(player["topTotal"]) == 1: # if player was just added
|
||||
db.players.insert_one(player)
|
||||
else:
|
||||
db.players.find_one_and_replace({"unique_id": unique_id}, player)
|
||||
|
||||
# Updating weaponsCount
|
||||
players = db.players.find({})
|
||||
for document in players:
|
||||
amount_of_weapons = len(document["weapons"])
|
||||
if "weaponsCount" not in document or amount_of_weapons != document["weaponsCount"]:
|
||||
db.players.update_one(
|
||||
{"unique_id": document["unique_id"]},
|
||||
{"$set": {"weaponsCount": amount_of_weapons}},
|
||||
)
|
||||
if "weaponsCount" in document:
|
||||
print(
|
||||
f"{document['name']} updated! {document['weaponsCount']} -> {amount_of_weapons}"
|
||||
)
|
||||
else:
|
||||
print(f"New player: {document['name']} with {amount_of_weapons} weapons!")
|
||||
|
||||
print("All done with updating the weaponsCount attributes.")
|
||||
|
||||