-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.js
169 lines (136 loc) · 5.99 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//setup
require("dotenv").config()
const express = require("express")
const { get } = require("axios")
const data = require("./data.json")
const path = require("path")
const wge = require("wge")
const utils = require("./utils")
const helmet = require("helmet");
const version = require("./package.json").version
const app = express()
const port = process.env.PORT || 80
//plugins
app.use(helmet()) //secure
app.use(express.json()) //parse json
app.use(express.urlencoded({ extended: true }))
//main page, send render
app.get("/", (req, res) => res.send(wge.render(path.join(__dirname, "public/index.html"), { version })))
app.post("/slayer", async(req, res) => {
//get basic info
minecraftID = await (await get(`https://api.minetools.eu/uuid/${req.body.username}`)).data.id
if (minecraftID == null) return res.send(["get uuid error"])
let profiles = await (await get(`https://api.hypixel.net/skyblock/profiles?key=${process.env.APIKEY}&uuid=${minecraftID}`)).data.profiles
if (profiles == null) return res.send(["get profiles error"])
let profile = await (await get(`https://api.hypixel.net/skyblock/profile?key=${process.env.APIKEY}&profile=${utils.getLatestProfile(profiles, minecraftID)[0].profile_id}`)).data.profile
if (profile == null) return res.send(["get profile error"])
let name = req.body.username
let user = profile.members[minecraftID]
//declare stats
let stats = {
// weekend: true,
// combatXpBuff: 1,
slayerXpBuff: 1,
mf: 1,
price: 1,
zombie: [],
spider: [],
wolf: [],
enderman: []
}
//declare slayer
let slayer = {
type: req.body.type, //zombie, spider, wolf, enderman
//if tier is 5 and type is zombie --> return 5, else --> return 4, else --> return normal
tier: req.body.tier == 5 ? (req.body.type == "zombie" ? 5 : 4) : req.body.tier,
amount: req.body.amount
}
//slayer loop
Object.keys(user.slayer_bosses).forEach(boss => {
let slayer = user.slayer_bosses[boss]
//calc global xp buff
// for (let i = 0; i <= 2; i++) {
// if (slayer.hasOwnProperty(`boss_kills_tier_${i}`)) stats.combatXpBuff += 0.01 //t1 - t3
// }
// if (slayer.hasOwnProperty(`boss_kills_tier_3`)) stats.combatXpBuff += 0.02 //t4
//calc level
if (!slayer.hasOwnProperty("xp")) return
let need = data[boss]
//get level and progress to next
for (let x in need) {
if (slayer.xp < need[x]) { //if xp is lower than cumulative, we found the level
stats[boss] = [+x, slayer.xp]
break
}
}
})
/* form info */
//weekend bonus
// if (weekend) stats.combatXpBuff += 0.2
//buffs
stats.mf += (+req.body.mf / 100)
//aatrox
if (req.body.xp) stats.slayerXpBuff += 0.25
if (req.body.drops) stats.mf += 0.2
if (req.body.price) stats.price /= 2
/* player info */
//slayer level bonus
if (stats.zombie[0] >= 7 && stats.spider[0] >= 7 && stats.wolf[0] >= 7 && stats.enderman[0] >= 7) stats.price -= 0.04
//send simulated data
res.send(calcDrops(slayer.type, slayer.tier, stats.mf, slayer.amount, stats[slayer.type][0]))
})
//calculate the stack size to be dropped
const calcStack = (type, tier, item) => {
const drops = require(`./drops/${type}/t${tier}.json`) //loot table
let drop = drops[item]
//if range doesnt exist, its specific
return !drop[1][0] ? drop[1] : drop[1].random()
}
//drop into map
const drop = (type, tier, item, map) => {
map.set(item.camel(), (map.has(item.camel()) ? map.get(item.camel()) + calcStack(type, tier, item) : calcStack(type, tier, item)))
}
//main calculation logic
const calcDrops = (type, tier, mf, amount, level) => {
let tickets = []
const drops = require(`./drops/${type}/t${tier}.json`) //loot table
const levels = require(`./drops/${type}/levels.json`)
//if it doesnt meet level requirement then remove it from drops
Object.keys(levels).forEach(item => { if (level < levels[item]) delete drops[item] })
let totalDrops = new Map()
for (let i = 0; i < amount; i++) {
let ticket = Math.random() * 100 //rng number
let pool = [] //drop pool
//go over each drop and see if it is bigger than ticket with mf
Object.keys(drops).forEach(drop => {
let dropName = drop
let dropMeta = drops[drop]
//ticket drop
if (ticket < dropMeta[0] * mf) {
pool.push([dropName, dropMeta[0]])
}
})
let temp = pool.slice(0).flat().filter(value => !isNaN(value)) //clone, flatten and filter out the non-numbers
pool = pool.filter(drop => drop[1] == Math.min(...temp)) //choose only the lowest chance drops
pool = utils.shuffle(pool) //random shuffle between those drops, because
tickets.push(ticket)
drop(type, tier, pool[0][0], totalDrops)
}
return [`${data[type.toUpperCase()]} T${tier} - ${amount} runs - ${mf * 100}% MF`, JSON.stringify(Object.fromEntries(totalDrops)), Math.min(...tickets)]
}
//serve static files, put last because it interferes with wge
app.use(express.static("public"))
//create server
app.listen(port, () => console.log(`Listening at http://localhost:${port}`))
//simple capitalize word
String.prototype.capitalize = function() {
return this.toLowerCase().replace(/_/g, " ").replace(/(^|\s)([a-z])/g, function(m, p1, p2) { return p1 + p2.toUpperCase() })
}
//transform camel into separate capitalized words -> "revenantFlesh".camel() returns "Revenant Flesh"
String.prototype.camel = function() {
return this.replace(/[A-Z-_\&](?=[a-z0-9]+)|[A-Z-_\&]+(?![a-z0-9])/g, ' $&').trim().capitalize()
}
//pick a random number from an array of 2 numbers as an inclusive range -> [ 20, 40 ].random() returns an integer between 20 and 40 (inclusive)
Array.prototype.random = function() {
return Math.floor(Math.random() * (Math.floor(this[1]) - Math.ceil(this[0]) + 1)) + Math.ceil(this[0])
}