rhythia-api 173.0.0 → 175.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/addCollectionMap.ts +70 -0
- package/api/chartPublicStats.ts +32 -0
- package/api/createBeatmap.ts +3 -0
- package/api/createCollection.ts +46 -0
- package/api/getCollection.ts +112 -0
- package/api/getCollections.ts +72 -0
- package/api/getPublicStats.ts +13 -0
- package/api/getRawStarRating.ts +11 -0
- package/index.ts +113 -0
- package/package.json +1 -1
- package/types/database.ts +89 -0
- package/utils/star-calc/index.ts +3 -16
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import z from "zod";
|
|
3
|
+
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
4
|
+
import { supabase } from "../utils/supabase";
|
|
5
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
6
|
+
import { User } from "@supabase/supabase-js";
|
|
7
|
+
|
|
8
|
+
export const Schema = {
|
|
9
|
+
input: z.strictObject({
|
|
10
|
+
session: z.string(),
|
|
11
|
+
collection: z.number(),
|
|
12
|
+
beatmapPage: z.number(),
|
|
13
|
+
}),
|
|
14
|
+
output: z.object({
|
|
15
|
+
error: z.string().optional(),
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export async function POST(request: Request) {
|
|
20
|
+
return protectedApi({
|
|
21
|
+
request,
|
|
22
|
+
schema: Schema,
|
|
23
|
+
authorization: validUser,
|
|
24
|
+
activity: handler,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
29
|
+
const user = (await getUserBySession(data.session)) as User;
|
|
30
|
+
let { data: queryUserData, error: userError } = await supabase
|
|
31
|
+
.from("profiles")
|
|
32
|
+
.select("*")
|
|
33
|
+
.eq("uid", user.id)
|
|
34
|
+
.single();
|
|
35
|
+
|
|
36
|
+
if (!queryUserData) {
|
|
37
|
+
return NextResponse.json({ error: "Can't find user" });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let { data: queryCollectionData, error: collectionError } = await supabase
|
|
41
|
+
.from("beatmapCollections")
|
|
42
|
+
.select("*")
|
|
43
|
+
.eq("id", data.collection)
|
|
44
|
+
.single();
|
|
45
|
+
|
|
46
|
+
let { data: queryBeatmapData, error: beatmapData } = await supabase
|
|
47
|
+
.from("beatmapPages")
|
|
48
|
+
.select("*")
|
|
49
|
+
.eq("id", data.beatmapPage)
|
|
50
|
+
.single();
|
|
51
|
+
|
|
52
|
+
if (!queryCollectionData) {
|
|
53
|
+
return NextResponse.json({ error: "Can't find collection" });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!queryBeatmapData) {
|
|
57
|
+
return NextResponse.json({ error: "Can't find beatmap page" });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (queryCollectionData.owner !== queryUserData.id) {
|
|
61
|
+
return NextResponse.json({ error: "You can't update foreign collections" });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
await supabase.from("collectionRelations").insert({
|
|
65
|
+
collection: data.collection,
|
|
66
|
+
beatmapPage: data.beatmapPage,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return NextResponse.json({});
|
|
70
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import z from "zod";
|
|
3
|
+
import { protectedApi } from "../utils/requestUtils";
|
|
4
|
+
import { supabase } from "../utils/supabase";
|
|
5
|
+
|
|
6
|
+
export const Schema = {
|
|
7
|
+
input: z.strictObject({}),
|
|
8
|
+
output: z.object({}),
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export async function POST(request: Request) {
|
|
12
|
+
return protectedApi({
|
|
13
|
+
request,
|
|
14
|
+
schema: Schema,
|
|
15
|
+
authorization: () => {},
|
|
16
|
+
activity: handler,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
21
|
+
// 30 minutes activity
|
|
22
|
+
const countOnline = await supabase
|
|
23
|
+
.from("profileActivities")
|
|
24
|
+
.select("*", { count: "exact", head: true })
|
|
25
|
+
.gt("last_activity", Date.now() - 1800000);
|
|
26
|
+
|
|
27
|
+
await supabase.from("chartedValues").insert({
|
|
28
|
+
type: "online_players",
|
|
29
|
+
value: countOnline.count,
|
|
30
|
+
});
|
|
31
|
+
return NextResponse.json({});
|
|
32
|
+
}
|
package/api/createBeatmap.ts
CHANGED
|
@@ -86,6 +86,9 @@ export async function handler({
|
|
|
86
86
|
.single();
|
|
87
87
|
|
|
88
88
|
if (beatmapPage) {
|
|
89
|
+
if (beatmapPage?.status !== "UNRANKED")
|
|
90
|
+
return NextResponse.json({ error: "Only unranked maps can be updated" });
|
|
91
|
+
|
|
89
92
|
if (!updateFlag) {
|
|
90
93
|
return NextResponse.json({ error: "Already Exists" });
|
|
91
94
|
} else if (beatmapPage.owner !== userData.id) {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import z from "zod";
|
|
3
|
+
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
4
|
+
import { supabase } from "../utils/supabase";
|
|
5
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
6
|
+
import { User } from "@supabase/supabase-js";
|
|
7
|
+
|
|
8
|
+
export const Schema = {
|
|
9
|
+
input: z.strictObject({
|
|
10
|
+
session: z.string(),
|
|
11
|
+
title: z.string(),
|
|
12
|
+
}),
|
|
13
|
+
output: z.object({
|
|
14
|
+
error: z.string().optional(),
|
|
15
|
+
}),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export async function POST(request: Request) {
|
|
19
|
+
return protectedApi({
|
|
20
|
+
request,
|
|
21
|
+
schema: Schema,
|
|
22
|
+
authorization: validUser,
|
|
23
|
+
activity: handler,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
28
|
+
const user = (await getUserBySession(data.session)) as User;
|
|
29
|
+
let { data: queryUserData, error: userError } = await supabase
|
|
30
|
+
.from("profiles")
|
|
31
|
+
.select("*")
|
|
32
|
+
.eq("uid", user.id)
|
|
33
|
+
.single();
|
|
34
|
+
|
|
35
|
+
if (!queryUserData) {
|
|
36
|
+
return NextResponse.json({ error: "Can't find user" });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
await supabase.from("beatmapCollections").insert({
|
|
40
|
+
title: data.title,
|
|
41
|
+
description: "",
|
|
42
|
+
owner: queryUserData.id,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return NextResponse.json({});
|
|
46
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import z from "zod";
|
|
3
|
+
import { protectedApi } from "../utils/requestUtils";
|
|
4
|
+
import { supabase } from "../utils/supabase";
|
|
5
|
+
|
|
6
|
+
export const Schema = {
|
|
7
|
+
input: z.strictObject({
|
|
8
|
+
session: z.string(),
|
|
9
|
+
collection: z.number(),
|
|
10
|
+
}),
|
|
11
|
+
output: z.object({
|
|
12
|
+
collection: z.object({
|
|
13
|
+
title: z.string(),
|
|
14
|
+
description: z.string(),
|
|
15
|
+
beatmaps: z.array(
|
|
16
|
+
z.object({
|
|
17
|
+
id: z.number(),
|
|
18
|
+
playcount: z.number().nullable().optional(),
|
|
19
|
+
created_at: z.string().nullable().optional(),
|
|
20
|
+
difficulty: z.number().nullable().optional(),
|
|
21
|
+
length: z.number().nullable().optional(),
|
|
22
|
+
title: z.string().nullable().optional(),
|
|
23
|
+
ranked: z.boolean().nullable().optional(),
|
|
24
|
+
beatmapFile: z.string().nullable().optional(),
|
|
25
|
+
image: z.string().nullable().optional(),
|
|
26
|
+
starRating: z.number().nullable().optional(),
|
|
27
|
+
owner: z.number().nullable().optional(),
|
|
28
|
+
ownerUsername: z.string().nullable().optional(),
|
|
29
|
+
status: z.string().nullable().optional(),
|
|
30
|
+
tags: z.string().nullable().optional(),
|
|
31
|
+
})
|
|
32
|
+
),
|
|
33
|
+
}),
|
|
34
|
+
error: z.string().optional(),
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export async function POST(request: Request) {
|
|
39
|
+
return protectedApi({
|
|
40
|
+
request,
|
|
41
|
+
schema: Schema,
|
|
42
|
+
authorization: () => {},
|
|
43
|
+
activity: handler,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
48
|
+
let { data: queryCollectionData, error: collectionError } = await supabase
|
|
49
|
+
.from("beatmapCollections")
|
|
50
|
+
.select("*")
|
|
51
|
+
.eq("id", data.collection)
|
|
52
|
+
.single();
|
|
53
|
+
|
|
54
|
+
if (!queryCollectionData) {
|
|
55
|
+
return NextResponse.json({ error: "Can't find collection" });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let { data: queryBeatmaps, error: beatmapsError } = await supabase
|
|
59
|
+
.from("collectionRelations")
|
|
60
|
+
.select(
|
|
61
|
+
`
|
|
62
|
+
*,
|
|
63
|
+
beatmapPages!inner(
|
|
64
|
+
owner,
|
|
65
|
+
created_at,
|
|
66
|
+
id,
|
|
67
|
+
status,
|
|
68
|
+
tags,
|
|
69
|
+
beatmaps!inner(
|
|
70
|
+
playcount,
|
|
71
|
+
ranked,
|
|
72
|
+
beatmapFile,
|
|
73
|
+
image,
|
|
74
|
+
starRating,
|
|
75
|
+
difficulty,
|
|
76
|
+
length,
|
|
77
|
+
title
|
|
78
|
+
),
|
|
79
|
+
profiles!inner(
|
|
80
|
+
username
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
`
|
|
84
|
+
)
|
|
85
|
+
.eq("collection", data.collection);
|
|
86
|
+
|
|
87
|
+
const formattedBeatmaps =
|
|
88
|
+
queryBeatmaps?.map((relation) => ({
|
|
89
|
+
id: relation.beatmapPages.id,
|
|
90
|
+
playcount: relation.beatmapPages.beatmaps.playcount,
|
|
91
|
+
created_at: relation.beatmapPages.created_at,
|
|
92
|
+
difficulty: relation.beatmapPages.beatmaps.difficulty,
|
|
93
|
+
length: relation.beatmapPages.beatmaps.length,
|
|
94
|
+
title: relation.beatmapPages.beatmaps.title,
|
|
95
|
+
ranked: relation.beatmapPages.beatmaps.ranked,
|
|
96
|
+
beatmapFile: relation.beatmapPages.beatmaps.beatmapFile,
|
|
97
|
+
image: relation.beatmapPages.beatmaps.image,
|
|
98
|
+
starRating: relation.beatmapPages.beatmaps.starRating,
|
|
99
|
+
owner: relation.beatmapPages.owner,
|
|
100
|
+
ownerUsername: relation.beatmapPages.profiles.username,
|
|
101
|
+
status: relation.beatmapPages.status,
|
|
102
|
+
tags: relation.beatmapPages.tags,
|
|
103
|
+
})) || [];
|
|
104
|
+
|
|
105
|
+
return NextResponse.json({
|
|
106
|
+
collection: {
|
|
107
|
+
title: queryCollectionData.title,
|
|
108
|
+
description: queryCollectionData.description,
|
|
109
|
+
beatmaps: formattedBeatmaps,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import z from "zod";
|
|
3
|
+
import { protectedApi } from "../utils/requestUtils";
|
|
4
|
+
import { supabase } from "../utils/supabase";
|
|
5
|
+
|
|
6
|
+
export const Schema = {
|
|
7
|
+
input: z.strictObject({
|
|
8
|
+
session: z.string(),
|
|
9
|
+
}),
|
|
10
|
+
output: z.object({
|
|
11
|
+
collections: z.array(
|
|
12
|
+
z.object({
|
|
13
|
+
id: z.number(),
|
|
14
|
+
title: z.string(),
|
|
15
|
+
description: z.string(),
|
|
16
|
+
beatmapCount: z.number(),
|
|
17
|
+
createdAt: z.string().nullable().optional(),
|
|
18
|
+
updatedAt: z.string().nullable().optional(),
|
|
19
|
+
})
|
|
20
|
+
),
|
|
21
|
+
error: z.string().optional(),
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export async function POST(request: Request) {
|
|
26
|
+
return protectedApi({
|
|
27
|
+
request,
|
|
28
|
+
schema: Schema,
|
|
29
|
+
authorization: () => {},
|
|
30
|
+
activity: handler,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
35
|
+
// First get all collections
|
|
36
|
+
let { data: collections, error: collectionsError } = await supabase
|
|
37
|
+
.from("beatmapCollections")
|
|
38
|
+
.select(
|
|
39
|
+
`
|
|
40
|
+
*,
|
|
41
|
+
collectionRelations!left(count)
|
|
42
|
+
`
|
|
43
|
+
)
|
|
44
|
+
.returns<
|
|
45
|
+
Array<{
|
|
46
|
+
id: number;
|
|
47
|
+
title: string;
|
|
48
|
+
description: string;
|
|
49
|
+
created_at: string | null;
|
|
50
|
+
updated_at: string | null;
|
|
51
|
+
collectionRelations: Array<{ count: number }>;
|
|
52
|
+
}>
|
|
53
|
+
>();
|
|
54
|
+
|
|
55
|
+
if (collectionsError) {
|
|
56
|
+
return NextResponse.json({ error: "Error fetching collections" });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const formattedCollections =
|
|
60
|
+
collections?.map((collection) => ({
|
|
61
|
+
id: collection.id,
|
|
62
|
+
title: collection.title,
|
|
63
|
+
description: collection.description,
|
|
64
|
+
beatmapCount: collection.collectionRelations?.[0]?.count ?? 0,
|
|
65
|
+
createdAt: collection.created_at,
|
|
66
|
+
updatedAt: collection.updated_at,
|
|
67
|
+
})) || [];
|
|
68
|
+
|
|
69
|
+
return NextResponse.json({
|
|
70
|
+
collections: formattedCollections,
|
|
71
|
+
});
|
|
72
|
+
}
|
package/api/getPublicStats.ts
CHANGED
|
@@ -10,6 +10,12 @@ export const Schema = {
|
|
|
10
10
|
beatmaps: z.number(),
|
|
11
11
|
scores: z.number(),
|
|
12
12
|
onlineUsers: z.number(),
|
|
13
|
+
countChart: z.array(
|
|
14
|
+
z.object({
|
|
15
|
+
type: z.string(),
|
|
16
|
+
value: z.number(),
|
|
17
|
+
})
|
|
18
|
+
),
|
|
13
19
|
lastBeatmaps: z.array(
|
|
14
20
|
z.object({
|
|
15
21
|
id: z.number().nullable().optional(),
|
|
@@ -127,11 +133,18 @@ export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
|
127
133
|
.select("*", { count: "exact", head: true })
|
|
128
134
|
.gt("last_activity", Date.now() - 1800000);
|
|
129
135
|
|
|
136
|
+
const countChart = await supabase
|
|
137
|
+
.from("chartedValues")
|
|
138
|
+
.select("*")
|
|
139
|
+
.eq("type", "online_players")
|
|
140
|
+
.gt("created_at", new Date(Date.now() - 86400000).toISOString());
|
|
141
|
+
|
|
130
142
|
return NextResponse.json({
|
|
131
143
|
beatmaps: countBeatmapsQuery.count,
|
|
132
144
|
profiles: countProfilesQuery.count,
|
|
133
145
|
scores: countScoresQuery.count,
|
|
134
146
|
onlineUsers: countOnline.count,
|
|
147
|
+
countChart: countChart.data,
|
|
135
148
|
lastBeatmaps: beatmapPage?.map((e) => ({
|
|
136
149
|
playcount: e.beatmaps?.playcount,
|
|
137
150
|
created_at: e.created_at,
|
package/api/getRawStarRating.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { protectedApi } from "../utils/requestUtils";
|
|
4
4
|
import { rateMapNotes } from "../utils/star-calc";
|
|
5
|
+
import { calculatePerformancePoints } from "./submitScore";
|
|
5
6
|
|
|
6
7
|
export const Schema = {
|
|
7
8
|
input: z.strictObject({
|
|
@@ -41,6 +42,16 @@ export async function handler(
|
|
|
41
42
|
return NextResponse.json({
|
|
42
43
|
beatmap: {
|
|
43
44
|
starRating,
|
|
45
|
+
rp: {
|
|
46
|
+
"S---": calculatePerformancePoints((starRating * 1) / 1.35, 1),
|
|
47
|
+
"S--": calculatePerformancePoints((starRating * 1) / 1.25, 1),
|
|
48
|
+
"S-": calculatePerformancePoints((starRating * 1) / 1.15, 1),
|
|
49
|
+
S: calculatePerformancePoints(starRating * 1, 1),
|
|
50
|
+
"S+": calculatePerformancePoints(starRating * 1.15, 1),
|
|
51
|
+
"S++": calculatePerformancePoints(starRating * 1.25, 1),
|
|
52
|
+
"S+++": calculatePerformancePoints(starRating * 1.35, 1),
|
|
53
|
+
"S++++": calculatePerformancePoints(starRating * 1.45, 1),
|
|
54
|
+
},
|
|
44
55
|
},
|
|
45
56
|
});
|
|
46
57
|
}
|
package/index.ts
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
import { handleApi } from "./handleApi"
|
|
2
2
|
|
|
3
|
+
// ./api/addCollectionMap.ts API
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
export const Schema = {
|
|
7
|
+
input: z.strictObject({
|
|
8
|
+
session: z.string(),
|
|
9
|
+
collection: z.number(),
|
|
10
|
+
beatmapPage: z.number(),
|
|
11
|
+
}),
|
|
12
|
+
output: z.object({
|
|
13
|
+
error: z.string().optional(),
|
|
14
|
+
}),
|
|
15
|
+
};*/
|
|
16
|
+
import { Schema as AddCollectionMap } from "./api/addCollectionMap"
|
|
17
|
+
export { Schema as SchemaAddCollectionMap } from "./api/addCollectionMap"
|
|
18
|
+
export const addCollectionMap = handleApi({url:"/api/addCollectionMap",...AddCollectionMap})
|
|
19
|
+
|
|
3
20
|
// ./api/approveMap.ts API
|
|
4
21
|
|
|
5
22
|
/*
|
|
@@ -16,6 +33,17 @@ import { Schema as ApproveMap } from "./api/approveMap"
|
|
|
16
33
|
export { Schema as SchemaApproveMap } from "./api/approveMap"
|
|
17
34
|
export const approveMap = handleApi({url:"/api/approveMap",...ApproveMap})
|
|
18
35
|
|
|
36
|
+
// ./api/chartPublicStats.ts API
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
export const Schema = {
|
|
40
|
+
input: z.strictObject({}),
|
|
41
|
+
output: z.object({}),
|
|
42
|
+
};*/
|
|
43
|
+
import { Schema as ChartPublicStats } from "./api/chartPublicStats"
|
|
44
|
+
export { Schema as SchemaChartPublicStats } from "./api/chartPublicStats"
|
|
45
|
+
export const chartPublicStats = handleApi({url:"/api/chartPublicStats",...ChartPublicStats})
|
|
46
|
+
|
|
19
47
|
// ./api/createBeatmap.ts API
|
|
20
48
|
|
|
21
49
|
/*
|
|
@@ -67,6 +95,22 @@ import { Schema as CreateClan } from "./api/createClan"
|
|
|
67
95
|
export { Schema as SchemaCreateClan } from "./api/createClan"
|
|
68
96
|
export const createClan = handleApi({url:"/api/createClan",...CreateClan})
|
|
69
97
|
|
|
98
|
+
// ./api/createCollection.ts API
|
|
99
|
+
|
|
100
|
+
/*
|
|
101
|
+
export const Schema = {
|
|
102
|
+
input: z.strictObject({
|
|
103
|
+
session: z.string(),
|
|
104
|
+
title: z.string(),
|
|
105
|
+
}),
|
|
106
|
+
output: z.object({
|
|
107
|
+
error: z.string().optional(),
|
|
108
|
+
}),
|
|
109
|
+
};*/
|
|
110
|
+
import { Schema as CreateCollection } from "./api/createCollection"
|
|
111
|
+
export { Schema as SchemaCreateCollection } from "./api/createCollection"
|
|
112
|
+
export const createCollection = handleApi({url:"/api/createCollection",...CreateCollection})
|
|
113
|
+
|
|
70
114
|
// ./api/deleteBeatmapPage.ts API
|
|
71
115
|
|
|
72
116
|
/*
|
|
@@ -403,6 +447,69 @@ import { Schema as GetClan } from "./api/getClan"
|
|
|
403
447
|
export { Schema as SchemaGetClan } from "./api/getClan"
|
|
404
448
|
export const getClan = handleApi({url:"/api/getClan",...GetClan})
|
|
405
449
|
|
|
450
|
+
// ./api/getCollection.ts API
|
|
451
|
+
|
|
452
|
+
/*
|
|
453
|
+
export const Schema = {
|
|
454
|
+
input: z.strictObject({
|
|
455
|
+
session: z.string(),
|
|
456
|
+
collection: z.number(),
|
|
457
|
+
}),
|
|
458
|
+
output: z.object({
|
|
459
|
+
collection: z.object({
|
|
460
|
+
title: z.string(),
|
|
461
|
+
description: z.string(),
|
|
462
|
+
beatmaps: z.array(
|
|
463
|
+
z.object({
|
|
464
|
+
id: z.number(),
|
|
465
|
+
playcount: z.number().nullable().optional(),
|
|
466
|
+
created_at: z.string().nullable().optional(),
|
|
467
|
+
difficulty: z.number().nullable().optional(),
|
|
468
|
+
length: z.number().nullable().optional(),
|
|
469
|
+
title: z.string().nullable().optional(),
|
|
470
|
+
ranked: z.boolean().nullable().optional(),
|
|
471
|
+
beatmapFile: z.string().nullable().optional(),
|
|
472
|
+
image: z.string().nullable().optional(),
|
|
473
|
+
starRating: z.number().nullable().optional(),
|
|
474
|
+
owner: z.number().nullable().optional(),
|
|
475
|
+
ownerUsername: z.string().nullable().optional(),
|
|
476
|
+
status: z.string().nullable().optional(),
|
|
477
|
+
tags: z.string().nullable().optional(),
|
|
478
|
+
})
|
|
479
|
+
),
|
|
480
|
+
}),
|
|
481
|
+
error: z.string().optional(),
|
|
482
|
+
}),
|
|
483
|
+
};*/
|
|
484
|
+
import { Schema as GetCollection } from "./api/getCollection"
|
|
485
|
+
export { Schema as SchemaGetCollection } from "./api/getCollection"
|
|
486
|
+
export const getCollection = handleApi({url:"/api/getCollection",...GetCollection})
|
|
487
|
+
|
|
488
|
+
// ./api/getCollections.ts API
|
|
489
|
+
|
|
490
|
+
/*
|
|
491
|
+
export const Schema = {
|
|
492
|
+
input: z.strictObject({
|
|
493
|
+
session: z.string(),
|
|
494
|
+
}),
|
|
495
|
+
output: z.object({
|
|
496
|
+
collections: z.array(
|
|
497
|
+
z.object({
|
|
498
|
+
id: z.number(),
|
|
499
|
+
title: z.string(),
|
|
500
|
+
description: z.string(),
|
|
501
|
+
beatmapCount: z.number(),
|
|
502
|
+
createdAt: z.string().nullable().optional(),
|
|
503
|
+
updatedAt: z.string().nullable().optional(),
|
|
504
|
+
})
|
|
505
|
+
),
|
|
506
|
+
error: z.string().optional(),
|
|
507
|
+
}),
|
|
508
|
+
};*/
|
|
509
|
+
import { Schema as GetCollections } from "./api/getCollections"
|
|
510
|
+
export { Schema as SchemaGetCollections } from "./api/getCollections"
|
|
511
|
+
export const getCollections = handleApi({url:"/api/getCollections",...GetCollections})
|
|
512
|
+
|
|
406
513
|
// ./api/getLeaderboard.ts API
|
|
407
514
|
|
|
408
515
|
/*
|
|
@@ -540,6 +647,12 @@ export const Schema = {
|
|
|
540
647
|
beatmaps: z.number(),
|
|
541
648
|
scores: z.number(),
|
|
542
649
|
onlineUsers: z.number(),
|
|
650
|
+
countChart: z.array(
|
|
651
|
+
z.object({
|
|
652
|
+
type: z.string(),
|
|
653
|
+
value: z.number(),
|
|
654
|
+
})
|
|
655
|
+
),
|
|
543
656
|
lastBeatmaps: z.array(
|
|
544
657
|
z.object({
|
|
545
658
|
id: z.number().nullable().optional(),
|
package/package.json
CHANGED
package/types/database.ts
CHANGED
|
@@ -9,6 +9,38 @@ export type Json =
|
|
|
9
9
|
export type Database = {
|
|
10
10
|
public: {
|
|
11
11
|
Tables: {
|
|
12
|
+
beatmapCollections: {
|
|
13
|
+
Row: {
|
|
14
|
+
created_at: string
|
|
15
|
+
description: string
|
|
16
|
+
id: number
|
|
17
|
+
owner: number
|
|
18
|
+
title: string
|
|
19
|
+
}
|
|
20
|
+
Insert: {
|
|
21
|
+
created_at?: string
|
|
22
|
+
description: string
|
|
23
|
+
id?: number
|
|
24
|
+
owner: number
|
|
25
|
+
title: string
|
|
26
|
+
}
|
|
27
|
+
Update: {
|
|
28
|
+
created_at?: string
|
|
29
|
+
description?: string
|
|
30
|
+
id?: number
|
|
31
|
+
owner?: number
|
|
32
|
+
title?: string
|
|
33
|
+
}
|
|
34
|
+
Relationships: [
|
|
35
|
+
{
|
|
36
|
+
foreignKeyName: "beatmapCollections_owner_fkey"
|
|
37
|
+
columns: ["owner"]
|
|
38
|
+
isOneToOne: false
|
|
39
|
+
referencedRelation: "profiles"
|
|
40
|
+
referencedColumns: ["id"]
|
|
41
|
+
},
|
|
42
|
+
]
|
|
43
|
+
}
|
|
12
44
|
beatmapPageComments: {
|
|
13
45
|
Row: {
|
|
14
46
|
beatmapPage: number
|
|
@@ -153,6 +185,27 @@ export type Database = {
|
|
|
153
185
|
}
|
|
154
186
|
Relationships: []
|
|
155
187
|
}
|
|
188
|
+
chartedValues: {
|
|
189
|
+
Row: {
|
|
190
|
+
created_at: string
|
|
191
|
+
id: number
|
|
192
|
+
type: string | null
|
|
193
|
+
value: number | null
|
|
194
|
+
}
|
|
195
|
+
Insert: {
|
|
196
|
+
created_at?: string
|
|
197
|
+
id?: number
|
|
198
|
+
type?: string | null
|
|
199
|
+
value?: number | null
|
|
200
|
+
}
|
|
201
|
+
Update: {
|
|
202
|
+
created_at?: string
|
|
203
|
+
id?: number
|
|
204
|
+
type?: string | null
|
|
205
|
+
value?: number | null
|
|
206
|
+
}
|
|
207
|
+
Relationships: []
|
|
208
|
+
}
|
|
156
209
|
clans: {
|
|
157
210
|
Row: {
|
|
158
211
|
acronym: string | null
|
|
@@ -194,6 +247,42 @@ export type Database = {
|
|
|
194
247
|
},
|
|
195
248
|
]
|
|
196
249
|
}
|
|
250
|
+
collectionRelations: {
|
|
251
|
+
Row: {
|
|
252
|
+
beatmapPage: number | null
|
|
253
|
+
collection: number
|
|
254
|
+
created_at: string
|
|
255
|
+
id: number
|
|
256
|
+
}
|
|
257
|
+
Insert: {
|
|
258
|
+
beatmapPage?: number | null
|
|
259
|
+
collection: number
|
|
260
|
+
created_at?: string
|
|
261
|
+
id?: number
|
|
262
|
+
}
|
|
263
|
+
Update: {
|
|
264
|
+
beatmapPage?: number | null
|
|
265
|
+
collection?: number
|
|
266
|
+
created_at?: string
|
|
267
|
+
id?: number
|
|
268
|
+
}
|
|
269
|
+
Relationships: [
|
|
270
|
+
{
|
|
271
|
+
foreignKeyName: "collectionRelations_beatmapPage_fkey"
|
|
272
|
+
columns: ["beatmapPage"]
|
|
273
|
+
isOneToOne: false
|
|
274
|
+
referencedRelation: "beatmapPages"
|
|
275
|
+
referencedColumns: ["id"]
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
foreignKeyName: "collectionRelations_collection_fkey"
|
|
279
|
+
columns: ["collection"]
|
|
280
|
+
isOneToOne: false
|
|
281
|
+
referencedRelation: "beatmapCollections"
|
|
282
|
+
referencedColumns: ["id"]
|
|
283
|
+
},
|
|
284
|
+
]
|
|
285
|
+
}
|
|
197
286
|
discordWebhooks: {
|
|
198
287
|
Row: {
|
|
199
288
|
id: number
|
package/utils/star-calc/index.ts
CHANGED
|
@@ -4,19 +4,6 @@ import { sampleMap } from "./osuUtils";
|
|
|
4
4
|
import { SSPMParsedMap } from "./sspmParser";
|
|
5
5
|
import { SSPMMap, V1SSPMParser } from "./sspmv1Parser";
|
|
6
6
|
|
|
7
|
-
function easeInExpoDeq(x: number) {
|
|
8
|
-
return x === 0 ? 0 : Math.pow(2, 35 * x - 35);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function calculatePerformancePoints(
|
|
12
|
-
starRating: number,
|
|
13
|
-
accuracy: number
|
|
14
|
-
) {
|
|
15
|
-
return Math.round(
|
|
16
|
-
Math.pow((starRating * easeInExpoDeq(accuracy) * 100) / 2, 2) / 1000
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
7
|
export function rateMap(map: SSPMParsedMap) {
|
|
21
8
|
let notes = map.markers
|
|
22
9
|
.filter((marker) => marker.type === 0)
|
|
@@ -31,9 +18,9 @@ export function rateMap(map: SSPMParsedMap) {
|
|
|
31
18
|
|
|
32
19
|
export function rateMapNotes(map: [number, number, number][]) {
|
|
33
20
|
let notes = map.map((marker) => ({
|
|
34
|
-
time: marker[
|
|
35
|
-
x: marker[
|
|
36
|
-
y: marker[
|
|
21
|
+
time: marker[2],
|
|
22
|
+
x: marker[0],
|
|
23
|
+
y: marker[1],
|
|
37
24
|
}));
|
|
38
25
|
|
|
39
26
|
return rate(notes);
|