Skip to content

Commit 8b2a5e4

Browse files
committed
Add command to remove unranked mod clan scores
1 parent 2c9c7e7 commit 8b2a5e4

File tree

3 files changed

+324
-0
lines changed

3 files changed

+324
-0
lines changed

cmd/console/cmd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ func init() {
5555
RootCmd.AddCommand(commands.FixStatsCmd)
5656
RootCmd.AddCommand(commands.UpdateStripePriceId)
5757
RootCmd.AddCommand(commands.ClanRecalculateCommand)
58+
RootCmd.AddCommand(commands.RemoveUnrankedClanScores)
5859

5960
// Migrations
6061
RootCmd.AddCommand(migrations.MigrationPlaylistMapsetCmd)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package commands
2+
3+
import (
4+
"github.com/Quaver/api2/db"
5+
"github.com/Quaver/api2/enums"
6+
"github.com/sirupsen/logrus"
7+
"github.com/spf13/cobra"
8+
)
9+
10+
var RemoveUnrankedClanScores = &cobra.Command{
11+
Use: "clan:remove:unranked",
12+
Short: "Removes unranked clan scores",
13+
Run: func(cmd *cobra.Command, args []string) {
14+
scores := make([]*db.Score, 0)
15+
16+
result := db.SQL.
17+
Where("clan_id IS NOT NULL and mods > 0").
18+
Find(&scores)
19+
20+
if result.Error != nil {
21+
logrus.Error(result.Error)
22+
return
23+
}
24+
25+
for _, score := range scores {
26+
if enums.IsModComboRanked(enums.Mods(score.Modifiers)) {
27+
continue
28+
}
29+
30+
err := db.SQL.Model(&db.Score{}).
31+
Update("clan_id", nil).
32+
Where("id = ?", score.Id).Error
33+
34+
if err != nil {
35+
logrus.Error(err)
36+
return
37+
}
38+
39+
logrus.Info("Removed clan score: ", score.Id)
40+
}
41+
},
42+
}

enums/mods.go

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
package enums
2+
3+
import (
4+
"strings"
5+
)
6+
7+
type Mods int64
8+
9+
const (
10+
ModNoSliderVelocities Mods = 1 << iota
11+
ModSpeed05X
12+
ModSpeed06X
13+
ModSpeed07X
14+
ModSpeed08X
15+
ModSpeed09X
16+
ModSpeed11X
17+
ModSpeed12X
18+
ModSpeed13X
19+
ModSpeed14X
20+
ModSpeed15X
21+
ModSpeed16X
22+
ModSpeed17X
23+
ModSpeed18X
24+
ModSpeed19X
25+
ModSpeed20X
26+
ModStrict
27+
ModChill
28+
ModNoPause
29+
ModAutoplay
30+
ModPaused
31+
ModNoFail
32+
ModNoLongNotes
33+
ModRandomize
34+
ModSpeed055X
35+
ModSpeed065X
36+
ModSpeed075X
37+
ModSpeed085X
38+
ModSpeed095X
39+
ModInverse
40+
ModFullLN
41+
ModMirror
42+
ModCoop
43+
ModSpeed105X
44+
ModSpeed115X
45+
ModSpeed125X
46+
ModSpeed135X
47+
ModSpeed145X
48+
ModSpeed155X
49+
ModSpeed165X
50+
ModSpeed175X
51+
ModSpeed185X
52+
ModSpeed195X
53+
ModHealthAdjust
54+
ModNoMiss
55+
ModEnumMaxValue // This is only in place for looping purposes (i < ModEnumMaxValue - 1; i++)
56+
)
57+
58+
var RankedMods = []Mods{
59+
ModSpeed05X,
60+
ModSpeed055X,
61+
ModSpeed06X,
62+
ModSpeed065X,
63+
ModSpeed07X,
64+
ModSpeed075X,
65+
ModSpeed08X,
66+
ModSpeed085X,
67+
ModSpeed09X,
68+
ModSpeed095X,
69+
ModSpeed105X,
70+
ModSpeed11X,
71+
ModSpeed115X,
72+
ModSpeed12X,
73+
ModSpeed125X,
74+
ModSpeed13X,
75+
ModSpeed135X,
76+
ModSpeed14X,
77+
ModSpeed145X,
78+
ModSpeed15X,
79+
ModSpeed155X,
80+
ModSpeed16X,
81+
ModSpeed165X,
82+
ModSpeed17X,
83+
ModSpeed175X,
84+
ModSpeed18X,
85+
ModSpeed185X,
86+
ModSpeed19X,
87+
ModSpeed195X,
88+
ModSpeed20X,
89+
ModMirror,
90+
ModNoMiss,
91+
}
92+
93+
var ModStrings = map[Mods]string{
94+
ModNoSliderVelocities: "NSV",
95+
ModSpeed05X: "0.5x",
96+
ModSpeed06X: "0.6x",
97+
ModSpeed07X: "0.7x",
98+
ModSpeed08X: "0.8x",
99+
ModSpeed09X: "0.9x",
100+
ModSpeed11X: "1.1x",
101+
ModSpeed12X: "1.2x",
102+
ModSpeed13X: "1.3x",
103+
ModSpeed14X: "1.4x",
104+
ModSpeed15X: "1.5x",
105+
ModSpeed16X: "1.6x",
106+
ModSpeed17X: "1.7x",
107+
ModSpeed18X: "1.8x",
108+
ModSpeed19X: "1.9x",
109+
ModSpeed20X: "2.0x",
110+
ModStrict: "Strict",
111+
ModChill: "Chill",
112+
ModNoPause: "No Pause",
113+
ModAutoplay: "Autoplay",
114+
ModPaused: "Paused",
115+
ModNoFail: "No Fail",
116+
ModNoLongNotes: "No Long Notes",
117+
ModRandomize: "Randomize",
118+
ModSpeed055X: "0.55x",
119+
ModSpeed065X: "0.65x",
120+
ModSpeed075X: "0.75x",
121+
ModSpeed085X: "0.85x",
122+
ModSpeed095X: "0.95x",
123+
ModInverse: "Inverse",
124+
ModFullLN: "Full Long Notes",
125+
ModMirror: "Mirror",
126+
ModCoop: "Co-op",
127+
ModSpeed105X: "1.05x",
128+
ModSpeed115X: "1.15x",
129+
ModSpeed125X: "1.25x",
130+
ModSpeed135X: "1.35x",
131+
ModSpeed145X: "1.45x",
132+
ModSpeed155X: "1.55x",
133+
ModSpeed165X: "1.65x",
134+
ModSpeed175X: "1.75x",
135+
ModSpeed185X: "1.85x",
136+
ModSpeed195X: "1.95x",
137+
ModHealthAdjust: "Health Adjustments",
138+
ModNoMiss: "NM",
139+
ModEnumMaxValue: "INVALID!",
140+
}
141+
142+
// IsModActivated Returns if a given mod is activated in a mod combo
143+
func IsModActivated(modCombo Mods, mod Mods) bool {
144+
return modCombo&mod != 0
145+
}
146+
147+
// IsModComboRanked Returns if a combination of mods is ranked
148+
func IsModComboRanked(modCombo Mods) bool {
149+
if modCombo == 0 {
150+
return true
151+
}
152+
153+
for i := 0; (1 << i) < ModEnumMaxValue-1; i++ {
154+
mod := Mods(1 << i)
155+
156+
if !IsModActivated(modCombo, mod) {
157+
continue
158+
}
159+
160+
if !isModRanked(mod) {
161+
return false
162+
}
163+
}
164+
165+
return true
166+
}
167+
168+
// IsUnrankedModComboAllowed Returns if a combination of mods is allowed in score submission
169+
func IsUnrankedModComboAllowed(modCombo Mods) bool {
170+
if modCombo == 0 {
171+
return true
172+
}
173+
174+
for i := 0; (1 << i) < ModEnumMaxValue-1; i++ {
175+
mod := Mods(1 << i)
176+
177+
if !IsModActivated(modCombo, mod) {
178+
continue
179+
}
180+
181+
if !isUnrankedModAllowed(mod) && !isModRanked(mod) {
182+
return false
183+
}
184+
}
185+
186+
return true
187+
}
188+
189+
// GetModsString Gets a stringified version of a mod combination
190+
func GetModsString(modCombo Mods) string {
191+
if modCombo == 0 {
192+
return "None"
193+
}
194+
195+
mods := []string{}
196+
197+
for i := 0; (1 << i) < ModEnumMaxValue-1; i++ {
198+
mod := Mods(1 << i)
199+
200+
if !IsModActivated(modCombo, mod) {
201+
continue
202+
}
203+
204+
mods = append(mods, ModStrings[mod])
205+
}
206+
207+
return strings.Join(mods[:], ", ")
208+
}
209+
210+
// HasIncompatibleModifiers Checks if the combination of modifiers is incompatible
211+
func HasIncompatibleModifiers(modCombo Mods) bool {
212+
for i := 0; (1 << i) < ModEnumMaxValue-1; i++ {
213+
mod := Mods(1 << i)
214+
215+
if !IsModActivated(modCombo, mod) {
216+
continue
217+
}
218+
219+
// Go through each modifier
220+
for j := 0; (1 << j) < ModEnumMaxValue-1; j++ {
221+
modToCheck := Mods(1 << j)
222+
223+
if !IsModActivated(modCombo, modToCheck) || mod == modToCheck {
224+
continue
225+
}
226+
227+
// Both modifiers are speed mods
228+
if isSpeedModifier(mod) && isSpeedModifier(modToCheck) {
229+
return true
230+
}
231+
232+
// Both modifiers change long notes in some way
233+
if isLongNoteModifier(mod) && isLongNoteModifier(modToCheck) {
234+
return true
235+
}
236+
}
237+
}
238+
239+
return false
240+
}
241+
242+
// isModRanked Returns if a particular mod is ranked
243+
func isModRanked(mod Mods) bool {
244+
if mod == 0 {
245+
return true
246+
}
247+
248+
for _, rankedMod := range RankedMods {
249+
if rankedMod == mod {
250+
return true
251+
}
252+
}
253+
254+
return false
255+
}
256+
257+
// isUnrankedModAllowed Returns if a particular mod is allowed to be submitted.
258+
func isUnrankedModAllowed(mod Mods) bool {
259+
if mod == 0 {
260+
return true
261+
}
262+
263+
switch mod {
264+
case ModNoLongNotes, ModFullLN, ModInverse, ModNoSliderVelocities:
265+
return true
266+
}
267+
268+
return false
269+
}
270+
271+
// Returns if the modifier is a speed modifier
272+
func isSpeedModifier(mod Mods) bool {
273+
return (mod >= ModSpeed05X && mod <= ModSpeed20X) ||
274+
(mod >= ModSpeed055X && mod <= ModSpeed095X) ||
275+
(mod >= ModSpeed105X && mod <= ModSpeed195X)
276+
}
277+
278+
// Returns if a modifier changes the long notes within the map
279+
func isLongNoteModifier(mod Mods) bool {
280+
return mod == ModFullLN || mod == ModInverse || mod == ModNoLongNotes
281+
}

0 commit comments

Comments
 (0)