mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-16 16:09:09 -05:00
186 lines
5.3 KiB
JavaScript
186 lines
5.3 KiB
JavaScript
const { UserInputError, gql } = require('apollo-server-express')
|
|
const Placement = require('../models/placement')
|
|
const Player = require('../models/player')
|
|
|
|
const typeDef = gql`
|
|
extend type Query {
|
|
topPlayers (weapon: String!): topPlayer!
|
|
playerInfo(uid: String twitter: String): PlayerWithPlacements!
|
|
searchForPlayers(name: String! exact: Boolean): [Placement]!
|
|
searchForPlacements(name: String, weapon: String, mode: Int, unique_id: String, month: Int, year: Int, page: Int): PlacementCollection!
|
|
}
|
|
type Placement {
|
|
id: ID!
|
|
name: String!
|
|
weapon: String!
|
|
rank: Int!
|
|
mode: Int!
|
|
x_power: Float!
|
|
unique_id: String!
|
|
month: Int!
|
|
year: Int!
|
|
player: Player!
|
|
}
|
|
type topPlayer {
|
|
placements: [Placement!]!
|
|
modeCount: [Int!]!
|
|
}
|
|
type PlayerWithPlacements {
|
|
player: Player!
|
|
placements: [Placement!]!
|
|
}
|
|
type PlacementCollection {
|
|
placements: [Placement]!
|
|
pageCount: Int!
|
|
}
|
|
`
|
|
const resolvers = {
|
|
Query: {
|
|
topPlayers: async (root, args) => {
|
|
const placements = await Placement
|
|
.find({ weapon: args.weapon })
|
|
.sort({ "x_power": "desc" })
|
|
.select({ weapon: 0})
|
|
.catch(e => {
|
|
throw new UserInputError(e.message, {
|
|
invalidArgs: args,
|
|
})
|
|
})
|
|
|
|
const m = placements.reduce((acc, cur) => {
|
|
if (cur.mode === 1) {
|
|
acc.sz++
|
|
} else if (cur.mode === 2) {
|
|
acc.tc++
|
|
} else if (cur.mode === 3) {
|
|
acc.rm++
|
|
} else {
|
|
acc.cb++
|
|
}
|
|
|
|
return acc
|
|
}, {sz: 0, tc: 0, rm: 0, cb: 0})
|
|
|
|
return {placements: placements.slice(0, 101), modeCount: [m.sz+m.tc+m.rm+m.cb, m.sz, m.tc, m.rm, m.cb]}
|
|
},
|
|
playerInfo: async (root, args) => {
|
|
let searchCriteria = {}
|
|
if (args.uid) searchCriteria = { "unique_id": args.uid }
|
|
else if (args.twitter) searchCriteria = { "twitter": args.twitter.toLowerCase()}
|
|
else throw new UserInputError('no id or twitter provided', {
|
|
invalidArgs: args,
|
|
})
|
|
const player = await Player
|
|
.findOne(searchCriteria)
|
|
.catch(e => {
|
|
throw new UserInputError(e.message, {
|
|
invalidArgs: args,
|
|
})
|
|
})
|
|
|
|
if (!player) {
|
|
throw new UserInputError('player not found', {
|
|
invalidArgs: args,
|
|
})
|
|
}
|
|
const placements = await Placement
|
|
.find({ unique_id: player.unique_id })
|
|
.sort({ "year": "asc", "month": "asc" })
|
|
.catch(e => {
|
|
throw new UserInputError(e.message, {
|
|
invalidArgs: args,
|
|
})
|
|
})
|
|
|
|
return { player, placements }
|
|
},
|
|
searchForPlayers: async (root, args) => {
|
|
let placements = []
|
|
if (args.exact) {
|
|
placements = await Placement
|
|
.find({ name: args.name })
|
|
.sort({ "x_power": "desc" })
|
|
.limit(100)
|
|
.select({ name: 1, weapon: 1, x_power: 1, unique_id: 1})
|
|
.catch(e => {
|
|
throw new UserInputError(e.message, {
|
|
invalidArgs: args,
|
|
})
|
|
})
|
|
} else {
|
|
placements = await Placement
|
|
.find({ name: { "$regex": args.name, "$options": "i" }})
|
|
.sort({ "x_power": "desc" })
|
|
.limit(100)
|
|
.select({ name: 1, weapon: 1, x_power: 1, unique_id: 1})
|
|
.catch(e => {
|
|
throw new UserInputError(e.message, {
|
|
invalidArgs: args,
|
|
})
|
|
})
|
|
}
|
|
|
|
let uids = []
|
|
|
|
return placements.filter(p => {
|
|
if (uids.length === 21) {
|
|
return false
|
|
}
|
|
const bool = uids.includes(p.unique_id)
|
|
if (bool) {
|
|
return false
|
|
}
|
|
uids.push(p.unique_id)
|
|
return true
|
|
})
|
|
},
|
|
searchForPlacements: async (root, args) => {
|
|
const perPage = 25
|
|
const currentPage = args.page ? args.page - 1 : 0
|
|
const searchCriteria = {}
|
|
// TODO: If this turns out slow maybe denormalize the database to have case insensitive name field
|
|
if (args.name) searchCriteria.name = { $regex : new RegExp(args.name, "i") }
|
|
if (args.weapon) searchCriteria.weapon = args.weapon
|
|
if (args.mode) searchCriteria.mode = args.mode
|
|
if (args.unique_id) searchCriteria.unique_id = args.unique_id
|
|
if (args.month && args.year) {
|
|
searchCriteria.month = args.month
|
|
searchCriteria.year = args.year
|
|
}
|
|
const placementCount = await Placement
|
|
.countDocuments(searchCriteria)
|
|
.catch(e => {
|
|
throw new UserInputError(e.message, {
|
|
invalidArgs: args,
|
|
})
|
|
})
|
|
|
|
const pageCount = Math.ceil(placementCount / perPage)
|
|
// if 0 documents we don't care if the page is wrong
|
|
if (placementCount !== 0) {
|
|
if (args.page > pageCount) throw new UserInputError('too big page number given', {
|
|
invalidArgs: args,
|
|
})
|
|
}
|
|
|
|
const placements = await Placement
|
|
.find(searchCriteria)
|
|
.skip(perPage * currentPage)
|
|
.limit(perPage)
|
|
.sort({ "x_power": "desc" })
|
|
.populate('player')
|
|
.catch(e => {
|
|
throw new UserInputError(e.message, {
|
|
invalidArgs: args,
|
|
})
|
|
})
|
|
|
|
return { pageCount, placements}
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
Placement: typeDef,
|
|
placementResolvers: resolvers
|
|
} |