working save data

This commit is contained in:
GEEKiDoS
2024-04-09 16:14:04 +08:00
parent 1fa7d578fe
commit 83e63acc94
7 changed files with 315 additions and 191 deletions
+44 -63
View File
@@ -1,72 +1,53 @@
import { Binary } from "mongodb"; import { Binary, ObjectId } from "mongodb";
export interface PlayerInfo {
_id: string;
rivals: string[];
pointCount: number;
customize: {
2: string;
3: string;
4: string;
5: string;
6: string;
7: string;
8: string;
11: string;
10: string;
},
otherCustomize: {
1: string;
2: string;
3: string;
4: string;
5: string;
}
}
export interface PlayerPlayData { export interface PlayerPlayData {
_id: string; _id: string;
// konami binary xml
pdata: Binary; pdata: Binary;
checksum: string; // sha256 to ^
check_sum: string;
} }
export interface PlayerMusicData { export interface PlayerMusicData {
player: string; player: string;
musicId: string; music_id: number;
clearFlag: { play_style: number;
spb: number;
spn: number; // 1 = B, 5 = L, etc
sph: number; score: number[];
spa: number; clear_flag: number[];
spl: number; miss_count: number[];
dpb: number; play_num: number[];
dpn: number; clear_num: number[];
dph: number;
dpa: number;
dpl: number;
};
score: {
spb: number;
spn: number;
sph: number;
spa: number;
spl: number;
dpb: number;
dpn: number;
dph: number;
dpa: number;
dpl: number;
};
missCount: {
spb: number;
spn: number;
sph: number;
spa: number;
spl: number;
dpb: number;
dpn: number;
dph: number;
dpa: number;
dpl: number;
};
} }
export interface PlayerPlayLog {
_id: ObjectId,
player: string;
clock: number,
music_id: number,
note_id: number,
score: number,
pgreat_count: number,
great_count: number,
miss_count: number,
clear_flag: number,
stage: number,
groove_gauge: number,
mode_id: number,
mode_sub_id: number,
fail_detail: number,
ghost_check_sum: string,
update_my_best_score: boolean,
is_limit_score: boolean,
rival_infinitas_id: string,
is_compe: boolean,
compe_id: number,
compe_music_index: number
valid_best_option: boolean,
arrange_0: number,
arrange_1: number,
assist: number,
flip: number,
ghost: Buffer,
};
+3 -2
View File
@@ -109,11 +109,12 @@ async function main(): Promise<void> {
} }
logger.info( logger.info(
'%s.%s [%s]: request = %s', '%s %s.%s [%s]: request = %o',
ctx.url,
ctx.service.name, ctx.service.name,
ctx.service.method, ctx.service.method,
ctx.token, ctx.token,
JSON.stringify(ctx.body), ctx.body,
); );
let method = ctx.service.method; let method = ctx.service.method;
+20 -7
View File
@@ -6,10 +6,15 @@ import { XMLParser } from 'fast-xml-parser';
const parser = new XMLParser({ const parser = new XMLParser({
ignoreAttributes: false, ignoreAttributes: false,
parseAttributeValue: true, parseAttributeValue: false,
attributeNamePrefix: '$', attributeNamePrefix: '$',
removeNSPrefix: true, removeNSPrefix: true,
allowBooleanAttributes: true, numberParseOptions: {
hex: false,
leadingZeros: false,
eNotation: false,
skipLike: /.*/,
},
}); });
function parseValue(node: { $__type: string; $__count?: unknown }): any { function parseValue(node: { $__type: string; $__count?: unknown }): any {
@@ -25,15 +30,21 @@ function parseValue(node: { $__type: string; $__count?: unknown }): any {
'u32', 'u32',
's64', 's64',
'u64', 'u64',
'float',
'double',
].includes(node.$__type) ].includes(node.$__type)
) { ) {
if (isArray) { if (isArray) {
return node['#text'].split(' ').map((v) => new Number(v)); return node['#text'].split(' ').map((v) => parseInt(v));
} }
return new Number(node['#text']); return parseInt(node['#text']);
}
if (['float', 'double'].includes(node.$__type)) {
if (isArray) {
return node['#text'].split(' ').map((v) => parseFloat(v));
}
return parseFloat(node['#text']);
} }
if (['b', 'bool'].includes(node.$__type)) { if (['b', 'bool'].includes(node.$__type)) {
@@ -106,7 +117,9 @@ export async function eacnet(ctx: Context, next: Next): Promise<any> {
'base64' 'base64'
); );
const decoded = LZ77.decompress(buffer); const decoded = LZ77.decompress(buffer);
const xmlResult = kxmlToObject(parser.parse(to_xml(decoded).data)); const xml = to_xml(decoded).data;
const parsedXml = parser.parse(xml);
const xmlResult = kxmlToObject(parsedXml);
const game = Object.keys(xmlResult)[0]; const game = Object.keys(xmlResult)[0];
+82 -80
View File
@@ -88,10 +88,8 @@
3013, 3013,
3018, 3018,
4000, 4000,
4001,
4003, 4003,
4004, 4004,
4005,
4006, 4006,
4007, 4007,
4008, 4008,
@@ -114,7 +112,6 @@
5009, 5009,
5011, 5011,
5012, 5012,
5014,
5015, 5015,
5016, 5016,
5017, 5017,
@@ -164,7 +161,6 @@
7026, 7026,
7032, 7032,
7036, 7036,
7038,
7039, 7039,
8001, 8001,
8003, 8003,
@@ -180,7 +176,6 @@
8020, 8020,
8022, 8022,
8023, 8023,
8024,
8025, 8025,
8026, 8026,
8028, 8028,
@@ -214,14 +209,12 @@
9030, 9030,
9033, 9033,
9037, 9037,
9038,
9042, 9042,
9043, 9043,
9044, 9044,
9045, 9045,
9046, 9046,
9048, 9048,
9051,
9052, 9052,
9054, 9054,
9057, 9057,
@@ -265,7 +258,6 @@
11009, 11009,
11010, 11010,
11011, 11011,
11012,
11013, 11013,
11014, 11014,
11015, 11015,
@@ -273,7 +265,6 @@
11026, 11026,
11027, 11027,
11028, 11028,
11032,
11035, 11035,
11036, 11036,
11037, 11037,
@@ -285,7 +276,6 @@
11052, 11052,
12000, 12000,
12001, 12001,
12002,
12003, 12003,
12004, 12004,
12005, 12005,
@@ -293,13 +283,11 @@
12007, 12007,
12008, 12008,
12009, 12009,
12010,
12011, 12011,
12012, 12012,
12013, 12013,
12014, 12014,
12015, 12015,
12016,
12018, 12018,
12019, 12019,
12020, 12020,
@@ -321,7 +309,6 @@
12050, 12050,
12052, 12052,
12053, 12053,
12054,
13000, 13000,
13001, 13001,
13002, 13002,
@@ -330,7 +317,6 @@
13006, 13006,
13008, 13008,
13009, 13009,
13010,
13011, 13011,
13012, 13012,
13013, 13013,
@@ -351,7 +337,6 @@
13035, 13035,
13036, 13036,
13037, 13037,
13038,
13039, 13039,
13040, 13040,
13041, 13041,
@@ -368,12 +353,10 @@
14000, 14000,
14001, 14001,
14003, 14003,
14004,
14005, 14005,
14006, 14006,
14007, 14007,
14008, 14008,
14009,
14011, 14011,
14012, 14012,
14014, 14014,
@@ -384,7 +367,6 @@
14019, 14019,
14020, 14020,
14021, 14021,
14022,
14023, 14023,
14024, 14024,
14025, 14025,
@@ -398,32 +380,23 @@
14034, 14034,
14038, 14038,
14045, 14045,
14046,
14047, 14047,
14048, 14048,
14049, 14049,
14050, 14050,
14051, 14051,
14052, 14052,
14053,
14055, 14055,
14056, 14056,
15000,
15001, 15001,
15002, 15002,
15003, 15003,
15004,
15005,
15006, 15006,
15007,
15008,
15009, 15009,
15010, 15010,
15011, 15011,
15012, 15012,
15013, 15013,
15014,
15015,
15016, 15016,
15017, 15017,
15018, 15018,
@@ -431,10 +404,7 @@
15020, 15020,
15021, 15021,
15022, 15022,
15023,
15024, 15024,
15025,
15026,
15028, 15028,
15031, 15031,
15032, 15032,
@@ -445,21 +415,16 @@
15039, 15039,
15040, 15040,
15044, 15044,
15045,
15047, 15047,
15048, 15048,
15049, 15049,
15050, 15050,
15051, 15051,
15052, 15052,
15054,
15056, 15056,
15057, 15057,
15058, 15058,
15059, 15059,
15061,
16000,
16001,
16003, 16003,
16004, 16004,
16005, 16005,
@@ -467,24 +432,18 @@
16008, 16008,
16009, 16009,
16010, 16010,
16011,
16012, 16012,
16013, 16013,
16014, 16014,
16015,
16016, 16016,
16017, 16017,
16018,
16019, 16019,
16020, 16020,
16021, 16021,
16022,
16023, 16023,
16024, 16024,
16025,
16026, 16026,
16029, 16029,
16031,
16032, 16032,
16035, 16035,
16036, 16036,
@@ -492,12 +451,8 @@
16039, 16039,
16040, 16040,
16041, 16041,
16042,
16043, 16043,
16044, 16044,
16045,
16047,
16050,
16051, 16051,
16052, 16052,
16053, 16053,
@@ -529,7 +484,6 @@
17025, 17025,
17026, 17026,
17027, 17027,
17028,
17030, 17030,
17031, 17031,
17032, 17032,
@@ -552,7 +506,6 @@
17056, 17056,
17058, 17058,
17059, 17059,
17060,
17062, 17062,
17064, 17064,
17065, 17065,
@@ -566,7 +519,6 @@
18008, 18008,
18009, 18009,
18010, 18010,
18011,
18012, 18012,
18013, 18013,
18014, 18014,
@@ -579,7 +531,6 @@
18022, 18022,
18023, 18023,
18024, 18024,
18025,
18026, 18026,
18027, 18027,
18028, 18028,
@@ -671,7 +622,6 @@
19060, 19060,
19061, 19061,
19062, 19062,
19063,
19064, 19064,
19065, 19065,
19067, 19067,
@@ -681,7 +631,6 @@
19071, 19071,
19072, 19072,
19073, 19073,
19074,
19075, 19075,
20000, 20000,
20001, 20001,
@@ -702,12 +651,10 @@
20016, 20016,
20017, 20017,
20018, 20018,
20019,
20020, 20020,
20021, 20021,
20022, 20022,
20023, 20023,
20024,
20025, 20025,
20027, 20027,
20028, 20028,
@@ -721,7 +668,6 @@
20036, 20036,
20037, 20037,
20038, 20038,
20039,
20040, 20040,
20041, 20041,
20042, 20042,
@@ -747,7 +693,6 @@
20065, 20065,
20066, 20066,
20067, 20067,
20068,
20069, 20069,
20070, 20070,
20071, 20071,
@@ -772,7 +717,6 @@
20097, 20097,
20098, 20098,
20099, 20099,
20100,
20101, 20101,
20102, 20102,
21001, 21001,
@@ -786,7 +730,6 @@
21009, 21009,
21010, 21010,
21011, 21011,
21012,
21014, 21014,
21015, 21015,
21016, 21016,
@@ -801,7 +744,6 @@
21026, 21026,
21027, 21027,
21028, 21028,
21029,
21030, 21030,
21032, 21032,
21033, 21033,
@@ -815,17 +757,13 @@
21045, 21045,
21046, 21046,
21047, 21047,
21048,
21049, 21049,
21050,
21051, 21051,
21052,
21053, 21053,
21054, 21054,
21056, 21056,
21057, 21057,
21058, 21058,
21059,
21060, 21060,
21061, 21061,
21062, 21062,
@@ -835,10 +773,8 @@
21066, 21066,
21067, 21067,
21068, 21068,
21069,
21070, 21070,
21071, 21071,
21073,
21074, 21074,
21075, 21075,
21076, 21076,
@@ -853,21 +789,17 @@
21086, 21086,
21087, 21087,
21088, 21088,
21089,
21090, 21090,
22001, 22001,
22002, 22002,
22003, 22003,
22004, 22004,
22005, 22005,
22006,
22007, 22007,
22008,
22009, 22009,
22010, 22010,
22011, 22011,
22012, 22012,
22013,
22014, 22014,
22015, 22015,
22016, 22016,
@@ -876,13 +808,10 @@
22019, 22019,
22020, 22020,
22023, 22023,
22024,
22025, 22025,
22026, 22026,
22027,
22028, 22028,
22029, 22029,
22031,
22032, 22032,
22033, 22033,
22034, 22034,
@@ -928,7 +857,6 @@
22082, 22082,
22087, 22087,
22088, 22088,
22089,
22090, 22090,
22091, 22091,
22092, 22092,
@@ -968,7 +896,6 @@
23028, 23028,
23029, 23029,
23030, 23030,
23031,
23032, 23032,
23034, 23034,
23035, 23035,
@@ -989,7 +916,6 @@
23051, 23051,
23052, 23052,
23053, 23053,
23054,
23055, 23055,
23056, 23056,
23057, 23057,
@@ -1003,7 +929,6 @@
23067, 23067,
23068, 23068,
23069, 23069,
23070,
23074, 23074,
23075, 23075,
23076, 23076,
@@ -1020,7 +945,6 @@
23092, 23092,
23093, 23093,
23094, 23094,
23095,
24000, 24000,
24001, 24001,
24002, 24002,
@@ -1032,7 +956,6 @@
24008, 24008,
24009, 24009,
24010, 24010,
24011,
24012, 24012,
24013, 24013,
24014, 24014,
@@ -1061,7 +984,6 @@
24038, 24038,
24039, 24039,
24040, 24040,
24041,
24042, 24042,
24043, 24043,
24044, 24044,
@@ -1069,7 +991,6 @@
24046, 24046,
24047, 24047,
24048, 24048,
24050,
24051, 24051,
24053, 24053,
24054, 24054,
@@ -1364,7 +1285,6 @@
27112, 27112,
27113, 27113,
27114, 27114,
27116,
27117, 27117,
28002, 28002,
28005, 28005,
@@ -1537,5 +1457,87 @@
80049, 80049,
80050, 80050,
80051 80051
],
"lmusics": [
4001,
4005,
5014,
7038,
8024,
9038,
9051,
11012,
11032,
12002,
12010,
12016,
12054,
13010,
13038,
14004,
14009,
14022,
14046,
14053,
15000,
15004,
15005,
15007,
15008,
15014,
15015,
15023,
15025,
15026,
15045,
15054,
15061,
16000,
16001,
16011,
16015,
16018,
16022,
16025,
16031,
16042,
16045,
16047,
16050,
17028,
17060,
18011,
18025,
19063,
19074,
20019,
20024,
20039,
20068,
20100,
21012,
21029,
21048,
21050,
21052,
21059,
21069,
21073,
21089,
22006,
22008,
22013,
22024,
22027,
22031,
22089,
23031,
23054,
23070,
23095,
24011,
24041,
24050,
27116
] ]
} }
+15 -7
View File
@@ -16,7 +16,7 @@ function Combine(...modules: ({ new(): any })[]) {
modules.forEach(v => { modules.forEach(v => {
const descriptors = Object.getOwnPropertyDescriptors(v.prototype); const descriptors = Object.getOwnPropertyDescriptors(v.prototype);
for(const name in descriptors) { for (const name in descriptors) {
if (name === 'constructor') if (name === 'constructor')
continue; continue;
@@ -40,9 +40,17 @@ export default class extends Combine(Service, User, Game) {
} }
export const ITEM_LIST = data.items; export const ITEM_LIST = data.items;
export const MUSIC_LIST = data.musics.map(id => ({ export const MUSIC_LIST = [
music_id: v.s32(id), ...data.musics.map(id => ({
kind: v.s32(1), music_id: v.s32(id),
note_bit: v.s32(0), kind: v.s32(1),
music_pack_item_id: v.str('') note_bit: v.s32(0),
})); music_pack_item_id: v.str('')
})),
...data.lmusics.map(id => ({
music_id: v.s32(id),
kind: v.s32(2),
note_bit: v.s32(1),
music_pack_item_id: v.str('')
})),
];
+142 -32
View File
@@ -3,7 +3,8 @@ import { eacnet } from "../../decorators/eacnet.js";
import { Context } from "../../types.js"; import { Context } from "../../types.js";
import { v } from "../../utils/kxml-value.js"; import { v } from "../../utils/kxml-value.js";
import { ITEM_LIST, MUSIC_LIST } from "./index.js"; import { ITEM_LIST, MUSIC_LIST } from "./index.js";
import { PlayerMusicData, PlayerPlayData } from "../../database/index.js"; import { PlayerMusicData, PlayerPlayData, PlayerPlayLog } from "../../database/index.js";
import { fromToken } from "../../utils/laochan-id.js";
export class User { export class User {
db: Db; db: Db;
@@ -12,10 +13,14 @@ export class User {
return this.db.collection<PlayerPlayData>('player_play_data'); return this.db.collection<PlayerPlayData>('player_play_data');
} }
get playMusicCol() { get musicDataCol() {
return this.db.collection<PlayerMusicData>('player_music_data'); return this.db.collection<PlayerMusicData>('player_music_data');
} }
get playLogCol() {
return this.db.collection<PlayerPlayLog>('player_play_log');
}
@eacnet('p2d') @eacnet('p2d')
async getCustomizeSetting() { async getCustomizeSetting() {
return { return {
@@ -58,7 +63,11 @@ export class User {
status: v.s32(0), status: v.s32(0),
error: v.s32(0), error: v.s32(0),
result: { result: {
point_count: v.s32(114514), point_count: v.s32(1),
point: [{
point_id: v.str('P0100000'),
point_num: v.u32(114514),
}]
} }
} }
} }
@@ -85,16 +94,79 @@ export class User {
} }
} }
@eacnet('p2d')
async reportMusicResult(ctx: Context) {
const result = ctx.body as PlayerPlayLog;
result.player = ctx.token;
let updateTask = Promise.resolve();
const play_style = Math.floor(result.note_id / 5);
const diff = result.note_id % 5;
updateTask = (async () => {
const musicData = (await this.musicDataCol.findOne({
player: result.player,
music_id: result.music_id,
play_style: play_style
})) ?? {
player: result.player,
music_id: result.music_id,
play_style: play_style,
score: [0, 0, 0, 0, 0],
clear_flag: [0, 0, 0, 0, 0],
miss_count: [0, 0, 0, 0, 0],
play_num: [0, 0, 0, 0, 0],
clear_num: [0, 0, 0, 0, 0],
};
if (result.clear_flag > musicData.clear_flag[diff])
musicData.clear_flag[diff] = result.clear_flag;
if (result.miss_count < musicData.miss_count[diff])
musicData.miss_count[diff] = result.miss_count;
if (result.score > musicData.score[diff])
musicData.score[diff] = result.score;
if (result.clear_flag >= 2)
musicData.clear_num[diff]++;
musicData.play_num[diff]++;
await this.musicDataCol.updateOne({
player: result.player,
music_id: result.music_id,
play_style: play_style
}, {
$set: musicData
}, {
upsert: true
});
})();
await Promise.all([
this.playLogCol.insertOne(result),
updateTask,
])
return {
status: v.s32(0),
error: v.s32(0),
};
}
@eacnet('p2d') @eacnet('p2d')
async savePlayData(ctx: Context) { async savePlayData(ctx: Context) {
const uid = ctx.token; const uid = ctx.token;
const { pdata, checksum } = ctx.body as { pdata: Buffer, checksum: string }; const { pdata, check_sum } = ctx.body as { pdata: Buffer, check_sum: string };
await this.playDataCol await this.playDataCol
.updateOne({ _id: uid }, { .updateOne({ _id: uid }, {
$set: { $set: {
pdata: new Binary(pdata), pdata: new Binary(pdata),
checksum: checksum, check_sum,
} }
}); });
@@ -122,6 +194,9 @@ export class User {
status: v.s32(0), status: v.s32(0),
error: v.s32(0), error: v.s32(0),
result: { result: {
size: v.s32(result.pdata.length()),
rest_size: v.s32(0),
check_sum: v.str(result.check_sum),
pdata: v.bin(result.pdata.buffer), pdata: v.bin(result.pdata.buffer),
} }
} }
@@ -130,12 +205,10 @@ export class User {
@eacnet('p2d') @eacnet('p2d')
async registPlayer(ctx: Context) { async registPlayer(ctx: Context) {
const uid = ctx.token; const uid = ctx.token;
const { pdata, checksum } = ctx.body as { pdata: Buffer, checksum: string }; const { pdata, check_sum } = ctx.body as { pdata: Buffer, check_sum: string };
await this.playDataCol await this.playDataCol
.insertOne({ _id: uid, pdata: new Binary(pdata), checksum }); .insertOne({ _id: uid, pdata: new Binary(pdata), check_sum });
// this.userDataSaveTemp.set(uid, { pdata, checksum });
return { return {
status: v.s32(0), status: v.s32(0),
@@ -143,6 +216,53 @@ export class User {
} }
} }
@eacnet('p2d')
async checkPlayData(ctx: Context) {
const { check_sum } = ctx.body as { check_sum: string };
const data = await this.playDataCol.findOne({ _id: ctx.token }, {
projection: {
check_sum: 1,
}
});
const id = fromToken(ctx.token);
if (!data) {
return {
status: v.s32(0),
error: v.s32(0),
result: {
infinitas_id: v.str(id),
valid: v.bool(false),
is_exist: v.bool(false),
}
};
}
if (data.check_sum !== check_sum) {
return {
status: v.s32(0),
error: v.s32(0),
result: {
infinitas_id: v.str(id),
valid: v.bool(false),
is_exist: v.bool(true),
}
};
}
return {
status: v.s32(0),
error: v.s32(0),
result: {
infinitas_id: v.str(id),
valid: v.bool(true),
is_exist: v.bool(true),
}
};
}
@eacnet('p2d') @eacnet('p2d')
async getRivalInfo() { async getRivalInfo() {
return { return {
@@ -163,7 +283,7 @@ export class User {
error: v.s32(0), error: v.s32(0),
result: { result: {
status: v.s32(0), status: v.s32(0),
check_sum: v.str('f57959c468c9c59c47a4cead973f59fbec72eaa53a790c5b792222148e69c19d'), check_sum: v.str('adb004981ab29df534ef1d8b5e6216b447042f798010c2c1f233eebc058e1b67'),
music_list: { music_list: {
music_num: v.s32(MUSIC_LIST.length), music_num: v.s32(MUSIC_LIST.length),
music: MUSIC_LIST, music: MUSIC_LIST,
@@ -185,38 +305,28 @@ export class User {
async getMusicData(ctx: Context) { async getMusicData(ctx: Context) {
const { play_style } = ctx.body as { play_style: number }; const { play_style } = ctx.body as { play_style: number };
const musicDatas = await this.musicDataCol.find({
player: ctx.token,
play_style,
}).toArray();
return { return {
status: v.s32(0), status: v.s32(0),
error: v.s32(0), error: v.s32(0),
play_style: v.s32(play_style), play_style: v.s32(play_style),
result: { result: {
music: MUSIC_LIST.map(music => ({ music: musicDatas.map(data => ({
music_id: music.music_id, music_id: v.s32(data.music_id),
score: v.s32([9999, 9999, 9999, 9999]), score: v.s32(data.score),
clear_flag: v.s32([7, 7, 7, 7]), clear_flag: v.s32(data.clear_flag),
miss_count: v.s32([0, 0, 0, 0]), miss_count: v.s32(data.miss_count),
play_num: v.s32([1, 1, 1 ,1]), play_num: v.s32(data.play_num),
clear_num: v.s32([1, 1, 1 ,1]), clear_num: v.s32(data.clear_num),
})) }))
}, },
} }
} }
@eacnet('p2d')
async checkPlayData(ctx: Context) {
const count = await this.playDataCol.countDocuments({ _id: ctx.token });
return {
status: v.s32(0),
error: v.s32(0),
result: {
infinitas_id: v.str(ctx.token),
valid: v.bool(count),
is_exist: v.bool(count),
}
};
}
@eacnet('p2d') @eacnet('p2d')
async getItemList() { async getItemList() {
return { return {
+9
View File
@@ -0,0 +1,9 @@
import { createHash } from 'crypto';
export function fromToken(token: string) {
const key = createHash('md5')
.update(token, 'utf-8')
.digest('hex');
return ('LCHAN' + key).slice(0, 13);
}