sendou.ink/graphql-schemas/placement.js
2020-01-23 01:43:41 +02:00

198 lines
5.2 KiB
JavaScript

const { UserInputError, gql } = require("apollo-server-express")
const Placement = require("../mongoose-models/placement")
const Player = require("../mongoose-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) {
return null
}
const placements = await Placement.find({ unique_id: player.unique_id })
.sort({ year: "desc", month: "desc" })
.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 = {}
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) searchCriteria.month = args.month
if (args.year) 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,
}