idz: Remove profile ext id

Turns out (while researching team creation) the profile ext id
is just the aime id. After creating a team a profile discovery
request is immediately issued with the "profile id" in the field
that holds the aime id during initial profile load.
This commit is contained in:
Tau 2019-05-26 20:05:01 -04:00
parent 7c96253160
commit c2b0bcabc4
70 changed files with 238 additions and 341 deletions

View File

@ -12,7 +12,6 @@ create table "idz"."profile" (
references "aime"."player"("id") references "aime"."player"("id")
on delete cascade, on delete cascade,
-- TODO shop_id -- TODO shop_id
"ext_id" integer not null,
"name" text not null, "name" text not null,
"lv" smallint not null, "lv" smallint not null,
"exp" integer not null, "exp" integer not null,
@ -21,8 +20,7 @@ create table "idz"."profile" (
"mileage" integer not null, "mileage" integer not null,
"register_time" timestamp not null, "register_time" timestamp not null,
"access_time" timestamp not null, "access_time" timestamp not null,
constraint "profile_player_uq" unique ("player_id"), constraint "profile_player_uq" unique ("player_id")
constraint "profile_ext_id_uq" unique ("ext_id")
); );
create table "idz"."chara" ( create table "idz"."chara" (

View File

@ -1,2 +1,2 @@
create table "meta" ("schemaver" integer not null); create table "meta" ("schemaver" integer not null);
insert into "meta" values (1); insert into "meta" values (2);

View File

@ -0,0 +1,3 @@
alter table "idz"."profile" drop column "ext_id";
update "meta" set "schemaver" = 1;

View File

@ -3,7 +3,7 @@ import { Pool, PoolClient } from "pg";
export type Id<T> = bigint & { __id: T }; export type Id<T> = bigint & { __id: T };
const currentSchemaVer = 0; const currentSchemaVer = 1;
const pool = new Pool(); const pool = new Pool();
const fence = testConnection(); const fence = testConnection();

View File

@ -1,25 +0,0 @@
import * as sql from "sql-bricks";
import { ClientBase } from "pg";
import { ExtId } from "../model/base";
import { Profile } from "../model/profile";
import { Id } from "../../db";
export async function _findProfile(
conn: ClientBase,
extId: ExtId<Profile>
): Promise<Id<Profile>> {
const lookupSql = sql
.select("r.id")
.from("idz.profile r")
.where("r.ext_id", extId)
.toParams();
const { rows } = await conn.query(lookupSql);
if (rows.length > 0) {
return rows[0].id as Id<Profile>;
} else {
throw new Error("Profile not found");
}
}

View File

@ -1,22 +1,21 @@
import { ClientBase } from "pg"; import { ClientBase } from "pg";
import * as sql from "sql-bricks"; import * as sql from "sql-bricks";
import { _findProfile } from "./_util"; import { BackgroundCode } from "../model/base";
import { BackgroundCode, ExtId } from "../model/base";
import { Profile } from "../model/profile"; import { Profile } from "../model/profile";
import { FlagRepository } from "../repo"; import { FlagRepository } from "../repo";
import { generateId } from "../../db"; import { generateId, Id } from "../../db";
export class SqlBackgroundsRepository export class SqlBackgroundsRepository
implements FlagRepository<BackgroundCode> { implements FlagRepository<BackgroundCode> {
constructor(private readonly _conn: ClientBase) {} constructor(private readonly _conn: ClientBase) {}
async loadAll(extId: ExtId<Profile>): Promise<Set<BackgroundCode>> { async loadAll(id: Id<Profile>): Promise<Set<BackgroundCode>> {
const loadSql = sql const loadSql = sql
.select("bg.background_no") .select("bg.background_no")
.from("idz.background_unlock bg") .from("idz.background_unlock bg")
.join("idz.profile p", { "bg.profile_id": "p.id" }) .join("idz.profile p", { "bg.profile_id": "p.id" })
.where("p.ext_id", extId) .where("p.id", id)
.toParams(); .toParams();
const { rows } = await this._conn.query(loadSql); const { rows } = await this._conn.query(loadSql);
@ -30,11 +29,10 @@ export class SqlBackgroundsRepository
} }
async saveAll( async saveAll(
extId: ExtId<Profile>, profileId: Id<Profile>,
flags: Set<BackgroundCode> flags: Set<BackgroundCode>
): Promise<void> { ): Promise<void> {
const profileId = await _findProfile(this._conn, extId); const existing = await this.loadAll(profileId);
const existing = await this.loadAll(extId);
for (const flag of flags) { for (const flag of flags) {
if (existing.has(flag)) { if (existing.has(flag)) {

View File

@ -1,12 +1,10 @@
import { ClientBase } from "pg"; import { ClientBase } from "pg";
import * as sql from "sql-bricks-postgres"; import * as sql from "sql-bricks-postgres";
import { _findProfile } from "./_util";
import { ExtId } from "../model/base";
import { Car, CarSelector } from "../model/car"; import { Car, CarSelector } from "../model/car";
import { Profile } from "../model/profile"; import { Profile } from "../model/profile";
import { CarRepository } from "../repo"; import { CarRepository } from "../repo";
import { generateId } from "../../db"; import { generateId, Id } from "../../db";
function _extractRow(row: any): Car { function _extractRow(row: any): Car {
return { return {
@ -31,12 +29,11 @@ function _extractRow(row: any): Car {
export class SqlCarRepository implements CarRepository { export class SqlCarRepository implements CarRepository {
constructor(private readonly _conn: ClientBase) {} constructor(private readonly _conn: ClientBase) {}
async countCars(extId: ExtId<Profile>): Promise<number> { async countCars(profileId: Id<Profile>): Promise<number> {
const countSql = sql const countSql = sql
.select("count(*) result") .select("count(*) result")
.from("idz.car c") .from("idz.car c")
.join("idz.profile p", { "c.profile_id": "p.id" }) .where("c.profile_id", profileId)
.where("p.ext_id", extId)
.toParams(); .toParams();
const { rows } = await this._conn.query(countSql); const { rows } = await this._conn.query(countSql);
@ -45,12 +42,11 @@ export class SqlCarRepository implements CarRepository {
return parseInt(row.result, 10); return parseInt(row.result, 10);
} }
async loadAllCars(extId: ExtId<Profile>): Promise<Car[]> { async loadAllCars(profileId: Id<Profile>): Promise<Car[]> {
const loadSql = sql const loadSql = sql
.select("c.*") .select("c.*")
.from("idz.car c") .from("idz.car c")
.join("idz.profile p", { "c.profile_id": "p.id" }) .where("c.profile_id", profileId)
.where("p.ext_id", extId)
.toParams(); .toParams();
const { rows } = await this._conn.query(loadSql); const { rows } = await this._conn.query(loadSql);
@ -58,13 +54,12 @@ export class SqlCarRepository implements CarRepository {
return rows.map(_extractRow); return rows.map(_extractRow);
} }
async loadSelectedCar(extId: ExtId<Profile>): Promise<Car> { async loadSelectedCar(profileId: Id<Profile>): Promise<Car> {
const loadSql = sql const loadSql = sql
.select("c.*") .select("c.*")
.from("idz.car c") .from("idz.car c")
.join("idz.car_selection s", { "c.id": "s.car_id" }) .join("idz.car_selection s", { "c.id": "s.car_id" })
.join("idz.profile p", { "s.id": "p.id" }) .where("s.id", profileId)
.where("p.ext_id", extId)
.toParams(); .toParams();
const { rows } = await this._conn.query(loadSql); const { rows } = await this._conn.query(loadSql);
@ -72,11 +67,11 @@ export class SqlCarRepository implements CarRepository {
return _extractRow(rows[0]); return _extractRow(rows[0]);
} }
async saveCar(extId: ExtId<Profile>, car: Car): Promise<void> { async saveCar(profileId: Id<Profile>, car: Car): Promise<void> {
const saveSql = sql const saveSql = sql
.insert("idz.car", { .insert("idz.car", {
id: generateId(), id: generateId(),
profile_id: await _findProfile(this._conn, extId), profile_id: profileId,
selector: car.selector, selector: car.selector,
field_00: car.field_00, field_00: car.field_00,
field_02: car.field_02, field_02: car.field_02,
@ -116,11 +111,9 @@ export class SqlCarRepository implements CarRepository {
} }
async saveSelection( async saveSelection(
extId: ExtId<Profile>, profileId: Id<Profile>,
selector: CarSelector selector: CarSelector
): Promise<void> { ): Promise<void> {
const profileId = await _findProfile(this._conn, extId);
const findSql = sql const findSql = sql
.select("c.id") .select("c.id")
.from("idz.car c") .from("idz.car c")

View File

@ -1,21 +1,19 @@
import { ClientBase } from "pg"; import { ClientBase } from "pg";
import * as sql from "sql-bricks-postgres"; import * as sql from "sql-bricks-postgres";
import { _findProfile } from "./_util";
import { ExtId } from "../model/base";
import { Chara } from "../model/chara"; import { Chara } from "../model/chara";
import { Profile } from "../model/profile"; import { Profile } from "../model/profile";
import { FacetRepository } from "../repo"; import { FacetRepository } from "../repo";
import { Id } from "../../db";
export class SqlCharaRepository implements FacetRepository<Chara> { export class SqlCharaRepository implements FacetRepository<Chara> {
constructor(private readonly _conn: ClientBase) {} constructor(private readonly _conn: ClientBase) {}
async load(extId: ExtId<Profile>): Promise<Chara> { async load(profileId: Id<Profile>): Promise<Chara> {
const loadSql = sql const loadSql = sql
.select("c.*") .select("c.*")
.from("idz.profile p") .from("idz.chara c")
.join("idz.chara c", { "p.id": "c.id" }) .where("c.id", profileId)
.where("p.ext_id", extId)
.toParams(); .toParams();
const { rows } = await this._conn.query(loadSql); const { rows } = await this._conn.query(loadSql);
@ -35,9 +33,7 @@ export class SqlCharaRepository implements FacetRepository<Chara> {
}; };
} }
async save(extId: ExtId<Profile>, chara: Chara): Promise<void> { async save(profileId: Id<Profile>, chara: Chara): Promise<void> {
const profileId = await _findProfile(this._conn, extId);
const saveSql = sql const saveSql = sql
.insert("idz.chara", { .insert("idz.chara", {
id: profileId, id: profileId,

View File

@ -1,21 +1,19 @@
import { ClientBase } from "pg"; import { ClientBase } from "pg";
import * as sql from "sql-bricks-postgres"; import * as sql from "sql-bricks-postgres";
import { _findProfile } from "./_util";
import { CourseNo, ExtId } from "../model/base"; import { CourseNo, ExtId } from "../model/base";
import { Profile } from "../model/profile"; import { Profile } from "../model/profile";
import { CoursePlaysRepository } from "../repo"; import { CoursePlaysRepository } from "../repo";
import { generateId } from "../../db"; import { generateId, Id } from "../../db";
export class SqlCoursePlaysRepository implements CoursePlaysRepository { export class SqlCoursePlaysRepository implements CoursePlaysRepository {
constructor(private readonly _conn: ClientBase) {} constructor(private readonly _conn: ClientBase) {}
async loadAll(extId: ExtId<Profile>): Promise<Map<CourseNo, number>> { async loadAll(profileId: Id<Profile>): Promise<Map<CourseNo, number>> {
const loadSql = sql const loadSql = sql
.select("cp.course_no", "cp.count") .select("cp.course_no", "cp.count")
.from("idz.course_plays cp") .from("idz.course_plays cp")
.join("idz.profile p", { "cp.profile_id": "p.id" }) .where("cp.profile_id", profileId)
.where("p.ext_id", extId)
.toParams(); .toParams();
const { rows } = await this._conn.query(loadSql); const { rows } = await this._conn.query(loadSql);
@ -29,11 +27,9 @@ export class SqlCoursePlaysRepository implements CoursePlaysRepository {
} }
async saveAll( async saveAll(
extId: ExtId<Profile>, profileId: Id<Profile>,
plays: Map<CourseNo, number> plays: Map<CourseNo, number>
): Promise<void> { ): Promise<void> {
const profileId = await _findProfile(this._conn, extId);
for (const [k, v] of plays) { for (const [k, v] of plays) {
const saveSql = sql const saveSql = sql
.insert("idz.course_plays", { .insert("idz.course_plays", {

View File

@ -1,8 +1,6 @@
import { ClientBase } from "pg"; import { ClientBase } from "pg";
import * as sql from "sql-bricks-postgres"; import * as sql from "sql-bricks-postgres";
import { _findProfile } from "./_util";
import { ExtId } from "../model/base";
import { MissionGrid, MissionState } from "../model/mission"; import { MissionGrid, MissionState } from "../model/mission";
import { Profile } from "../model/profile"; import { Profile } from "../model/profile";
import { FacetRepository } from "../repo"; import { FacetRepository } from "../repo";
@ -11,9 +9,7 @@ import { generateId, Id } from "../../db";
export class SqlMissionsRepository implements FacetRepository<MissionState> { export class SqlMissionsRepository implements FacetRepository<MissionState> {
constructor(private readonly _conn: ClientBase) {} constructor(private readonly _conn: ClientBase) {}
private async _load( async load(profileId: Id<Profile>): Promise<MissionState> {
extId: ExtId<Profile>
): Promise<[MissionState, Id<Profile>]> {
const result: MissionState = { const result: MissionState = {
solo: new Array<MissionGrid>(), solo: new Array<MissionGrid>(),
team: new Array<MissionGrid>(), team: new Array<MissionGrid>(),
@ -32,8 +28,6 @@ export class SqlMissionsRepository implements FacetRepository<MissionState> {
result.team.push(teamGrid); result.team.push(teamGrid);
} }
const profileId = await _findProfile(this._conn, extId);
const loadSoloSql = sql const loadSoloSql = sql
.select("sm.*") .select("sm.*")
.from("idz.solo_mission_state sm") .from("idz.solo_mission_state sm")
@ -46,17 +40,11 @@ export class SqlMissionsRepository implements FacetRepository<MissionState> {
result.solo[row.grid_no].cells[row.cell_no] = row.value; result.solo[row.grid_no].cells[row.cell_no] = row.value;
} }
return [result, profileId]; return result;
} }
async load(extId: ExtId<Profile>): Promise<MissionState> { async save(profileId: Id<Profile>, mission: MissionState): Promise<void> {
const [mission] = await this._load(extId); const existing = await this.load(profileId);
return mission;
}
async save(extId: ExtId<Profile>, mission: MissionState): Promise<void> {
const [existing, profileId] = await this._load(extId);
for (let i = 0; i < mission.solo.length; i++) { for (let i = 0; i < mission.solo.length; i++) {
const exGrid = existing.solo[i].cells; const exGrid = existing.solo[i].cells;

View File

@ -1,17 +1,16 @@
import * as sql from "sql-bricks"; import * as sql from "sql-bricks";
import { ClientBase } from "pg"; import { ClientBase } from "pg";
import { _findProfile } from "./_util";
import { ExtId } from "../model/base"; import { ExtId } from "../model/base";
import { Profile } from "../model/profile"; import { Profile } from "../model/profile";
import { Team } from "../model/team"; import { Team } from "../model/team";
import { ProfileSpec, ProfileRepository } from "../repo"; import { ProfileSpec, ProfileRepository } from "../repo";
import { generateExtId, generateId, Id } from "../../db"; import { generateId, Id } from "../../db";
import { AimeId } from "../../model"; import { AimeId } from "../../model";
function _extractRow(row: any): Profile { function _extractProfile(row: any): Profile {
return { return {
id: row.ext_id, aimeId: row.ext_id,
teamId: 2 as ExtId<Team>, // TODO teamId: 2 as ExtId<Team>, // TODO
name: row.name, name: row.name,
lv: row.lv, lv: row.lv,
@ -25,11 +24,19 @@ function _extractRow(row: any): Profile {
export class SqlProfileRepository implements ProfileRepository { export class SqlProfileRepository implements ProfileRepository {
constructor(private readonly _conn: ClientBase) {} constructor(private readonly _conn: ClientBase) {}
private async _tryLoadByAimeId( async find(aimeId: AimeId): Promise<Id<Profile>> {
aimeId: AimeId const profileId = await this.peek(aimeId);
): Promise<Profile | undefined> {
if (profileId === undefined) {
throw new Error(`Profile not found for Aime ID ${aimeId}`);
}
return profileId;
}
async peek(aimeId: AimeId): Promise<Id<Profile> | undefined> {
const lookupSql = sql const lookupSql = sql
.select("p.*") .select("p.id")
.from("idz.profile p") .from("idz.profile p")
.join("aime.player r", { "p.player_id": "r.id" }) .join("aime.player r", { "p.player_id": "r.id" })
.where("r.ext_id", aimeId) .where("r.ext_id", aimeId)
@ -42,35 +49,19 @@ export class SqlProfileRepository implements ProfileRepository {
return undefined; return undefined;
} }
return _extractRow(row); return row.id;
} }
async discoverByAimeId(aimeId: AimeId): Promise<boolean> { async load(id: Id<Profile>): Promise<Profile> {
const result = await this._tryLoadByAimeId(aimeId);
return result !== undefined;
}
async loadByAimeId(aimeId: AimeId): Promise<Profile> {
const result = await this._tryLoadByAimeId(aimeId);
if (result === undefined) {
throw new Error("Profile not found for Aime ID");
}
return result;
}
async load(extId: ExtId<Profile>): Promise<Profile> {
const loadSql = sql const loadSql = sql
.select("p.*") .select("p.*")
.from("idz.profile p") .from("idz.profile p")
.where("ext_id", extId) .where("id", id)
.toParams(); .toParams();
const { rows } = await this._conn.query(loadSql); const { rows } = await this._conn.query(loadSql);
return _extractRow(rows[0]); return _extractProfile(rows[0]);
} }
async save(profile: Profile, timestamp: Date): Promise<void> { async save(profile: Profile, timestamp: Date): Promise<void> {
@ -83,7 +74,7 @@ export class SqlProfileRepository implements ProfileRepository {
mileage: profile.mileage, mileage: profile.mileage,
access_time: timestamp, access_time: timestamp,
}) })
.where("ext_id", profile.id) .where("id", profile.aimeId)
.toParams(); .toParams();
await this._conn.query(saveSql); await this._conn.query(saveSql);
@ -93,7 +84,7 @@ export class SqlProfileRepository implements ProfileRepository {
aimeId: AimeId, aimeId: AimeId,
profile: ProfileSpec, profile: ProfileSpec,
timestamp: Date timestamp: Date
): Promise<ExtId<Profile>> { ): Promise<Id<Profile>> {
const findSql = sql const findSql = sql
.select("r.id") .select("r.id")
.from("aime.player r") .from("aime.player r")
@ -108,14 +99,12 @@ export class SqlProfileRepository implements ProfileRepository {
} }
const id = generateId(); const id = generateId();
const extId = generateExtId() as ExtId<Profile>;
const playerId = row.id; const playerId = row.id;
const createSql = sql const createSql = sql
.insert("idz.profile", { .insert("idz.profile", {
id: id, id: id,
player_id: playerId, player_id: playerId,
ext_id: extId,
name: profile.name, name: profile.name,
lv: profile.lv, lv: profile.lv,
exp: profile.exp, exp: profile.exp,
@ -129,6 +118,6 @@ export class SqlProfileRepository implements ProfileRepository {
await this._conn.query(createSql); await this._conn.query(createSql);
return extId; return id as Id<Profile>;
} }
} }

View File

@ -1,21 +1,19 @@
import { ClientBase } from "pg"; import { ClientBase } from "pg";
import * as sql from "sql-bricks-postgres"; import * as sql from "sql-bricks-postgres";
import { _findProfile } from "./_util";
import { ExtId } from "../model/base";
import { Settings } from "../model/settings"; import { Settings } from "../model/settings";
import { Profile } from "../model/profile"; import { Profile } from "../model/profile";
import { FacetRepository } from "../repo"; import { FacetRepository } from "../repo";
import { Id } from "../../db";
export class SqlSettingsRepository implements FacetRepository<Settings> { export class SqlSettingsRepository implements FacetRepository<Settings> {
constructor(private readonly _conn: ClientBase) {} constructor(private readonly _conn: ClientBase) {}
async load(extId: ExtId<Profile>): Promise<Settings> { async load(profileId: Id<Profile>): Promise<Settings> {
const loadSql = sql const loadSql = sql
.select("s.*") .select("s.*")
.from("idz.profile p") .from("idz.settings s")
.join("idz.settings s", { "p.id": "s.id" }) .where("s.id", profileId)
.where("p.ext_id", extId)
.toParams(); .toParams();
const { rows } = await this._conn.query(loadSql); const { rows } = await this._conn.query(loadSql);
@ -29,9 +27,7 @@ export class SqlSettingsRepository implements FacetRepository<Settings> {
}; };
} }
async save(extId: ExtId<Profile>, settings: Settings): Promise<void> { async save(profileId: Id<Profile>, settings: Settings): Promise<void> {
const profileId = await _findProfile(this._conn, extId);
const saveSql = sql const saveSql = sql
.insert("idz.settings", { .insert("idz.settings", {
id: profileId, id: profileId,

View File

@ -1,8 +1,6 @@
import { ClientBase } from "pg"; import { ClientBase } from "pg";
import * as sql from "sql-bricks-postgres"; import * as sql from "sql-bricks-postgres";
import { _findProfile } from "./_util";
import { ExtId } from "../model/base";
import { Profile } from "../model/profile"; import { Profile } from "../model/profile";
import { Story, StoryRow, StoryCell } from "../model/story"; import { Story, StoryRow, StoryCell } from "../model/story";
import { FacetRepository } from "../repo"; import { FacetRepository } from "../repo";
@ -11,9 +9,7 @@ import { generateId, Id } from "../../db";
export class SqlStoryRepository implements FacetRepository<Story> { export class SqlStoryRepository implements FacetRepository<Story> {
constructor(private readonly _conn: ClientBase) {} constructor(private readonly _conn: ClientBase) {}
private async _load(extId: ExtId<Profile>): Promise<[Story, Id<Profile>]> { async load(profileId: Id<Profile>): Promise<Story> {
const profileId = await _findProfile(this._conn, extId);
const loadSql = sql const loadSql = sql
.select("s.*") .select("s.*")
.from("idz.story_state s") .from("idz.story_state s")
@ -56,17 +52,11 @@ export class SqlStoryRepository implements FacetRepository<Story> {
cell.b = row.b; cell.b = row.b;
} }
return [result, profileId]; return result;
} }
async load(extId: ExtId<Profile>): Promise<Story> { async save(profileId: Id<Profile>, story: Story): Promise<void> {
const [story] = await this._load(extId); const existing = await this.load(profileId);
return story;
}
async save(extId: ExtId<Profile>, story: Story): Promise<void> {
const [existing, profileId] = await this._load(extId);
const headSql = sql const headSql = sql
.insert("idz.story_state", { .insert("idz.story_state", {

View File

@ -1,23 +1,21 @@
import { ClientBase } from "pg"; import { ClientBase } from "pg";
import * as sql from "sql-bricks-postgres"; import * as sql from "sql-bricks-postgres";
import { _findProfile } from "./_util";
import { ExtId } from "../model/base";
import { Profile } from "../model/profile"; import { Profile } from "../model/profile";
import { Tickets } from "../model/tickets"; import { Tickets } from "../model/tickets";
import { FacetRepository } from "../repo"; import { FacetRepository } from "../repo";
import { Id } from "../../db";
// TODO free continue // TODO free continue
export class SqlTicketsRepository implements FacetRepository<Tickets> { export class SqlTicketsRepository implements FacetRepository<Tickets> {
constructor(private readonly _conn: ClientBase) {} constructor(private readonly _conn: ClientBase) {}
async load(extId: ExtId<Profile>): Promise<Tickets> { async load(profileId: Id<Profile>): Promise<Tickets> {
const loadSql = sql const loadSql = sql
.select("fc.*") .select("fc.*")
.from("idz.profile p") .from("idz.free_car fc")
.join("idz.free_car fc", { "p.id": "fc.id" }) .where("fc.id", profileId)
.where("p.ext_id", extId)
.toParams(); .toParams();
const { rows } = await this._conn.query(loadSql); const { rows } = await this._conn.query(loadSql);
@ -30,8 +28,7 @@ export class SqlTicketsRepository implements FacetRepository<Tickets> {
}; };
} }
async save(extId: ExtId<Profile>, tickets: Tickets): Promise<void> { async save(profileId: Id<Profile>, tickets: Tickets): Promise<void> {
const profileId = await _findProfile(this._conn, extId);
const { freeCar } = tickets; const { freeCar } = tickets;
if (!freeCar) { if (!freeCar) {

View File

@ -1,12 +1,11 @@
import { ClientBase } from "pg"; import { ClientBase } from "pg";
import * as sql from "sql-bricks-postgres"; import * as sql from "sql-bricks-postgres";
import { _findProfile } from "./_util"; import { RouteNo } from "../model/base";
import { ExtId, RouteNo } from "../model/base";
import { Profile } from "../model/profile"; import { Profile } from "../model/profile";
import { TimeAttackScore } from "../model/timeAttack"; import { TimeAttackScore } from "../model/timeAttack";
import { TimeAttackRepository, TopTenResult } from "../repo"; import { TimeAttackRepository, TopTenResult } from "../repo";
import { generateId } from "../../db"; import { generateId, Id } from "../../db";
export class SqlTimeAttackRepository implements TimeAttackRepository { export class SqlTimeAttackRepository implements TimeAttackRepository {
constructor(private readonly _conn: ClientBase) {} constructor(private readonly _conn: ClientBase) {}
@ -41,12 +40,11 @@ export class SqlTimeAttackRepository implements TimeAttackRepository {
})); }));
} }
async loadAll(extId: ExtId<Profile>): Promise<TimeAttackScore[]> { async loadAll(profileId: Id<Profile>): Promise<TimeAttackScore[]> {
const loadSql = sql const loadSql = sql
.select("ta.*") .select("ta.*")
.from("idz.ta_best ta") .from("idz.ta_best ta")
.join("idz.profile p", { "ta.profile_id": "p.id" }) .where("ta.profile_id", profileId)
.where("p.ext_id", extId)
.toParams(); .toParams();
const { rows } = await this._conn.query(loadSql); const { rows } = await this._conn.query(loadSql);
@ -62,9 +60,7 @@ export class SqlTimeAttackRepository implements TimeAttackRepository {
})); }));
} }
async save(extId: ExtId<Profile>, score: TimeAttackScore): Promise<void> { async save(profileId: Id<Profile>, score: TimeAttackScore): Promise<void> {
const profileId = await _findProfile(this._conn, extId);
const logSql = sql const logSql = sql
.insert("idz.ta_result", { .insert("idz.ta_result", {
id: generateId(), id: generateId(),

View File

@ -1,21 +1,19 @@
import { ClientBase } from "pg"; import { ClientBase } from "pg";
import * as sql from "sql-bricks"; import * as sql from "sql-bricks";
import { _findProfile } from "./_util";
import { TitleCode, ExtId } from "../model/base"; import { TitleCode, ExtId } from "../model/base";
import { Profile } from "../model/profile"; import { Profile } from "../model/profile";
import { FlagRepository } from "../repo"; import { FlagRepository } from "../repo";
import { generateId } from "../../db"; import { generateId, Id } from "../../db";
export class SqlTitlesRepository implements FlagRepository<TitleCode> { export class SqlTitlesRepository implements FlagRepository<TitleCode> {
constructor(private readonly _conn: ClientBase) {} constructor(private readonly _conn: ClientBase) {}
async loadAll(extId: ExtId<Profile>): Promise<Set<TitleCode>> { async loadAll(profileId: Id<Profile>): Promise<Set<TitleCode>> {
const loadSql = sql const loadSql = sql
.select("t.title_no") .select("t.title_no")
.from("idz.title_unlock t") .from("idz.title_unlock t")
.join("idz.profile p", { "t.profile_id": "p.id" }) .where("t.profile_id", profileId)
.where("p.ext_id", extId)
.toParams(); .toParams();
const { rows } = await this._conn.query(loadSql); const { rows } = await this._conn.query(loadSql);
@ -28,9 +26,8 @@ export class SqlTitlesRepository implements FlagRepository<TitleCode> {
return result; return result;
} }
async saveAll(extId: ExtId<Profile>, flags: Set<TitleCode>): Promise<void> { async saveAll(profileId: Id<Profile>, flags: Set<TitleCode>): Promise<void> {
const profileId = await _findProfile(this._conn, extId); const existing = await this.loadAll(profileId);
const existing = await this.loadAll(extId);
for (const flag of flags) { for (const flag of flags) {
if (existing.has(flag)) { if (existing.has(flag)) {

View File

@ -1,21 +1,20 @@
import { ClientBase } from "pg"; import { ClientBase } from "pg";
import * as sql from "sql-bricks-postgres"; import * as sql from "sql-bricks-postgres";
import { _findProfile } from "./_util";
import { ExtId } from "../model/base"; import { ExtId } from "../model/base";
import { Profile } from "../model/profile"; import { Profile } from "../model/profile";
import { Unlocks } from "../model/unlocks"; import { Unlocks } from "../model/unlocks";
import { FacetRepository } from "../repo"; import { FacetRepository } from "../repo";
import { Id } from "../../db";
export class SqlUnlocksRepository implements FacetRepository<Unlocks> { export class SqlUnlocksRepository implements FacetRepository<Unlocks> {
constructor(private readonly _conn: ClientBase) {} constructor(private readonly _conn: ClientBase) {}
async load(extId: ExtId<Profile>): Promise<Unlocks> { async load(profileId: Id<Profile>): Promise<Unlocks> {
const loadSql = sql const loadSql = sql
.select("u.*") .select("u.*")
.from("idz.profile p") .from("idz.unlocks u")
.join("idz.unlocks u", { "p.id": "u.id" }) .where("u.id", profileId)
.where("p.ext_id", extId)
.toParams(); .toParams();
const { rows } = await this._conn.query(loadSql); const { rows } = await this._conn.query(loadSql);
@ -29,9 +28,7 @@ export class SqlUnlocksRepository implements FacetRepository<Unlocks> {
}; };
} }
async save(extId: ExtId<Profile>, unlocks: Unlocks): Promise<void> { async save(profileId: Id<Profile>, unlocks: Unlocks): Promise<void> {
const profileId = await _findProfile(this._conn, extId);
const saveSql = sql const saveSql = sql
.insert("idz.unlocks", { .insert("idz.unlocks", {
id: profileId, id: profileId,

View File

@ -1,9 +1,8 @@
import iconv = require("iconv-lite"); import iconv = require("iconv-lite");
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { ExtId } from "../model/base";
import { Profile } from "../model/profile";
import { CreateTeamRequest } from "../request/createTeam"; import { CreateTeamRequest } from "../request/createTeam";
import { AimeId } from "../../model";
createTeam.msgCode = 0x0071 as RequestCode; createTeam.msgCode = 0x0071 as RequestCode;
createTeam.msgLen = 0x0050; createTeam.msgLen = 0x0050;
@ -11,7 +10,7 @@ createTeam.msgLen = 0x0050;
export function createTeam(buf: Buffer): CreateTeamRequest { export function createTeam(buf: Buffer): CreateTeamRequest {
return { return {
type: "create_team_req", type: "create_team_req",
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
teamName: iconv.decode( teamName: iconv.decode(
buf.slice(0x0008, buf.indexOf("\0", 0x0008)), buf.slice(0x0008, buf.indexOf("\0", 0x0008)),
"shift_jis" "shift_jis"

View File

@ -1,8 +1,8 @@
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { ExtId } from "../model/base"; import { ExtId } from "../model/base";
import { Profile } from "../model/profile";
import { Team } from "../model/team"; import { Team } from "../model/team";
import { Load2on2Request1, Load2on2Request2 } from "../request/load2on2"; import { Load2on2Request1, Load2on2Request2 } from "../request/load2on2";
import { AimeId } from "../../model";
load2on2_v1.msgCode = 0x00b0 as RequestCode; load2on2_v1.msgCode = 0x00b0 as RequestCode;
load2on2_v1.msgLen = 0x0010; load2on2_v1.msgLen = 0x0010;
@ -12,7 +12,7 @@ export function load2on2_v1(buf: Buffer): Load2on2Request1 {
type: "load_2on2_req", type: "load_2on2_req",
format: 1, format: 1,
field_0002: buf.readUInt16LE(0x0002), field_0002: buf.readUInt16LE(0x0002),
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
teamId: buf.readUInt32LE(0x0008) as ExtId<Team>, teamId: buf.readUInt32LE(0x0008) as ExtId<Team>,
}; };
} }
@ -25,7 +25,7 @@ export function load2on2_v2(buf: Buffer): Load2on2Request2 {
type: "load_2on2_req", type: "load_2on2_req",
format: 2, format: 2,
field_0002: buf.readUInt16LE(0x0002), field_0002: buf.readUInt16LE(0x0002),
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
teamId: buf.readUInt32LE(0x0008) as ExtId<Team>, teamId: buf.readUInt32LE(0x0008) as ExtId<Team>,
}; };
} }

View File

@ -1,7 +1,6 @@
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { ExtId } from "../model/base";
import { Profile } from "../model/profile";
import { LoadEventInfoRequest } from "../request/loadEventInfo"; import { LoadEventInfoRequest } from "../request/loadEventInfo";
import { AimeId } from "../../model";
loadEventInfo.msgCode = 0x00be as RequestCode; loadEventInfo.msgCode = 0x00be as RequestCode;
loadEventInfo.msgLen = 0x0010; loadEventInfo.msgLen = 0x0010;
@ -9,6 +8,6 @@ loadEventInfo.msgLen = 0x0010;
export function loadEventInfo(buf: Buffer): LoadEventInfoRequest { export function loadEventInfo(buf: Buffer): LoadEventInfoRequest {
return { return {
type: "load_event_info_req", type: "load_event_info_req",
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
}; };
} }

View File

@ -1,7 +1,6 @@
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { LoadGachaRequest } from "../request/loadGacha"; import { LoadGachaRequest } from "../request/loadGacha";
import { ExtId } from "../model/base"; import { AimeId } from "../../model";
import { Profile } from "../model/profile";
loadGacha.msgCode = 0x00c1 as RequestCode; loadGacha.msgCode = 0x00c1 as RequestCode;
loadGacha.msgLen = 0x0010; loadGacha.msgLen = 0x0010;
@ -9,6 +8,6 @@ loadGacha.msgLen = 0x0010;
export function loadGacha(buf: Buffer): LoadGachaRequest { export function loadGacha(buf: Buffer): LoadGachaRequest {
return { return {
type: "load_gacha_req", type: "load_gacha_req",
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
}; };
} }

View File

@ -1,7 +1,6 @@
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { ExtId } from "../model/base";
import { Profile } from "../model/profile";
import { LoadGarageRequest } from "../request/loadGarage"; import { LoadGarageRequest } from "../request/loadGarage";
import { AimeId } from "../../model";
loadGarage.msgCode = 0x0090 as RequestCode; loadGarage.msgCode = 0x0090 as RequestCode;
loadGarage.msgLen = 0x0010; loadGarage.msgLen = 0x0010;
@ -9,7 +8,7 @@ loadGarage.msgLen = 0x0010;
export function loadGarage(buf: Buffer): LoadGarageRequest { export function loadGarage(buf: Buffer): LoadGarageRequest {
return { return {
type: "load_garage_req", type: "load_garage_req",
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
fetchOffset: buf.readUInt8(0x0008), fetchOffset: buf.readUInt8(0x0008),
field_000A: buf.readUInt16LE(0x000a), field_000A: buf.readUInt16LE(0x000a),
}; };

View File

@ -1,10 +1,9 @@
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { ExtId } from "../model/base";
import { Profile } from "../model/profile";
import { import {
LoadGeneralRewardRequest1, LoadGeneralRewardRequest1,
LoadGeneralRewardRequest2, LoadGeneralRewardRequest2,
} from "../request/loadGeneralReward"; } from "../request/loadGeneralReward";
import { AimeId } from "../../model";
loadGeneralReward1.msgCode = 0x009c as RequestCode; loadGeneralReward1.msgCode = 0x009c as RequestCode;
loadGeneralReward1.msgLen = 0x0010; loadGeneralReward1.msgLen = 0x0010;
@ -13,7 +12,7 @@ export function loadGeneralReward1(buf: Buffer): LoadGeneralRewardRequest1 {
return { return {
type: "load_general_reward_req", type: "load_general_reward_req",
format: 1, format: 1,
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
}; };
} }
@ -24,6 +23,6 @@ export function loadGeneralReward2(buf: Buffer): LoadGeneralRewardRequest2 {
return { return {
type: "load_general_reward_req", type: "load_general_reward_req",
format: 2, format: 2,
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
}; };
} }

View File

@ -1,7 +1,6 @@
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { ExtId } from "../model/base";
import { Profile } from "../model/profile";
import { LoadStockerRequest } from "../request/loadStocker"; import { LoadStockerRequest } from "../request/loadStocker";
import { AimeId } from "../../model";
loadStocker.msgCode = 0x00a7 as RequestCode; loadStocker.msgCode = 0x00a7 as RequestCode;
loadStocker.msgLen = 0x0010; loadStocker.msgLen = 0x0010;
@ -9,6 +8,6 @@ loadStocker.msgLen = 0x0010;
export function loadStocker(buf: Buffer): LoadStockerRequest { export function loadStocker(buf: Buffer): LoadStockerRequest {
return { return {
type: "load_stocker_req", type: "load_stocker_req",
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
}; };
} }

View File

@ -7,7 +7,7 @@ loadTeam.msgLen = 0x0010;
export function loadTeam(buf: Buffer): LoadTeamRequest { export function loadTeam(buf: Buffer): LoadTeamRequest {
return { return {
type: "load_team_req", type: "load_team_req",
profileId: buf.readUInt32LE(0x0004), aimeId: buf.readUInt32LE(0x0004),
teamId: buf.readUInt32LE(0x0008), teamId: buf.readUInt32LE(0x0008),
}; };
} }

View File

@ -1,11 +1,11 @@
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { ExtId, RouteNo } from "../model/base"; import { ExtId, RouteNo } from "../model/base";
import { Profile } from "../model/profile";
import { Team } from "../model/team"; import { Team } from "../model/team";
import { import {
LoadTopTenRequest, LoadTopTenRequest,
LoadTopTenRequestSelector, LoadTopTenRequestSelector,
} from "../request/loadTopTen"; } from "../request/loadTopTen";
import { AimeId } from "../../model";
loadTopTen1.msgCode = 0x00b5 as RequestCode; loadTopTen1.msgCode = 0x00b5 as RequestCode;
loadTopTen1.msgLen = 0x00e0; loadTopTen1.msgLen = 0x00e0;
@ -30,7 +30,7 @@ export function loadTopTen1(buf: Buffer): LoadTopTenRequest {
field_C4: buf.readUInt8(0x00c4), // Boolean, true if profile ID is set field_C4: buf.readUInt8(0x00c4), // Boolean, true if profile ID is set
field_C5: buf.readUInt8(0x00c5), // Always zero field_C5: buf.readUInt8(0x00c5), // Always zero
field_C6: buf.readUInt16LE(0x00c6), field_C6: buf.readUInt16LE(0x00c6),
profileId: profileId !== 0 ? (profileId as ExtId<Profile>) : undefined, aimeId: profileId !== 0 ? (profileId as AimeId) : undefined,
teamId: teamId !== 0xffffffff ? (teamId as ExtId<Team>) : undefined, teamId: teamId !== 0xffffffff ? (teamId as ExtId<Team>) : undefined,
}; };
} }

View File

@ -1,11 +1,11 @@
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { ExtId, RouteNo } from "../model/base"; import { ExtId, RouteNo } from "../model/base";
import { Profile } from "../model/profile";
import { Team } from "../model/team"; import { Team } from "../model/team";
import { import {
LoadTopTenRequest, LoadTopTenRequest,
LoadTopTenRequestSelector, LoadTopTenRequestSelector,
} from "../request/loadTopTen"; } from "../request/loadTopTen";
import { AimeId } from "../../model";
loadTopTen2.msgCode = 0x012c as RequestCode; loadTopTen2.msgCode = 0x012c as RequestCode;
loadTopTen2.msgLen = 0x0110; loadTopTen2.msgLen = 0x0110;
@ -30,7 +30,7 @@ export function loadTopTen2(buf: Buffer): LoadTopTenRequest {
field_C4: buf.readUInt8(0x00f4), // Boolean, true if profile ID is set field_C4: buf.readUInt8(0x00f4), // Boolean, true if profile ID is set
field_C5: buf.readUInt8(0x00f5), // Always zero field_C5: buf.readUInt8(0x00f5), // Always zero
field_C6: buf.readUInt16LE(0x00f6), field_C6: buf.readUInt16LE(0x00f6),
profileId: profileId !== 0 ? (profileId as ExtId<Profile>) : undefined, aimeId: profileId !== 0 ? (profileId as AimeId) : undefined,
teamId: teamId !== 0xffffffff ? (teamId as ExtId<Team>) : undefined, teamId: teamId !== 0xffffffff ? (teamId as ExtId<Team>) : undefined,
}; };
} }

View File

@ -7,7 +7,7 @@ lockProfile.msgLen = 0x0020;
export function lockProfile(buf: Buffer): LockProfileRequest { export function lockProfile(buf: Buffer): LockProfileRequest {
return { return {
type: "lock_profile_req", type: "lock_profile_req",
profileId: buf.readUInt32LE(0x0004), aimeId: buf.readUInt32LE(0x0004),
pcbId: buf.slice(0x0008, buf.indexOf("\0", 0x0008)).toString("ascii"), pcbId: buf.slice(0x0008, buf.indexOf("\0", 0x0008)).toString("ascii"),
field_0018: buf.readUInt16LE(0x0018), field_0018: buf.readUInt16LE(0x0018),
}; };

View File

@ -1,7 +1,6 @@
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { ExtId } from "../model/base";
import { Profile } from "../model/profile";
import { LockProfileExtendRequest } from "../request/lockProfileExtend"; import { LockProfileExtendRequest } from "../request/lockProfileExtend";
import { AimeId } from "../../model";
lockProfileExtend.msgCode = 0x006d as RequestCode; lockProfileExtend.msgCode = 0x006d as RequestCode;
lockProfileExtend.msgLen = 0x0020; lockProfileExtend.msgLen = 0x0020;
@ -9,7 +8,7 @@ lockProfileExtend.msgLen = 0x0020;
export function lockProfileExtend(buf: Buffer): LockProfileExtendRequest { export function lockProfileExtend(buf: Buffer): LockProfileExtendRequest {
return { return {
type: "lock_profile_extend_req", type: "lock_profile_extend_req",
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
luid: buf.slice(0x0008, buf.indexOf("\0")).toString("ascii"), luid: buf.slice(0x0008, buf.indexOf("\0")).toString("ascii"),
}; };
} }

View File

@ -14,7 +14,7 @@ export function saveGarage(buf: Buffer): SaveGarageRequest {
return { return {
type: "save_garage_req", type: "save_garage_req",
profileId: buf.readUInt32LE(0x0004), aimeId: buf.readUInt32LE(0x0004),
payload: car(buf.slice(0x0008, 0x0068)), payload: car(buf.slice(0x0008, 0x0068)),
field_0068, field_0068,
field_0080: buf.readUInt8(0x0080), field_0080: buf.readUInt8(0x0080),

View File

@ -1,8 +1,7 @@
import { car } from "./_car"; import { car } from "./_car";
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { ExtId } from "../model/base";
import { Profile } from "../model/profile";
import { SaveNewCarRequest } from "../request/saveNewCar"; import { SaveNewCarRequest } from "../request/saveNewCar";
import { AimeId } from "../../model";
saveNewCar.msgCode = 0x0079 as RequestCode; saveNewCar.msgCode = 0x0079 as RequestCode;
saveNewCar.msgLen = 0x0090; saveNewCar.msgLen = 0x0090;
@ -10,7 +9,7 @@ saveNewCar.msgLen = 0x0090;
export function saveNewCar(buf: Buffer): SaveNewCarRequest { export function saveNewCar(buf: Buffer): SaveNewCarRequest {
return { return {
type: "save_new_car_req", type: "save_new_car_req",
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
luid: buf.slice(0x0008, buf.indexOf(0, 0x0008)).toString("ascii"), luid: buf.slice(0x0008, buf.indexOf(0, 0x0008)).toString("ascii"),
car: car(buf.slice(0x0020, 0x0080)), car: car(buf.slice(0x0020, 0x0080)),
field_0080: buf.readUInt32LE(0x0080), field_0080: buf.readUInt32LE(0x0080),

View File

@ -2,9 +2,9 @@ import { car } from "./_car";
import { mission } from "./_mission"; import { mission } from "./_mission";
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { BackgroundCode, CourseNo, ExtId, TitleCode } from "../model/base"; import { BackgroundCode, CourseNo, ExtId, TitleCode } from "../model/base";
import { Profile } from "../model/profile";
import { SaveProfileRequest2 } from "../request/saveProfile"; import { SaveProfileRequest2 } from "../request/saveProfile";
import { bitmap } from "./_bitmap"; import { bitmap } from "./_bitmap";
import { AimeId } from "../../model";
saveProfile2.msgCode = 0x0068 as RequestCode; saveProfile2.msgCode = 0x0068 as RequestCode;
saveProfile2.msgLen = 0x0940; saveProfile2.msgLen = 0x0940;
@ -47,7 +47,7 @@ export function saveProfile2(buf: Buffer): SaveProfileRequest2 {
return { return {
type: "save_profile_req", type: "save_profile_req",
format: 2, format: 2,
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
lv: buf.readUInt16LE(0x0026), lv: buf.readUInt16LE(0x0026),
exp: buf.readUInt32LE(0x0028), exp: buf.readUInt32LE(0x0028),
fame: buf.readUInt32LE(0x0468), fame: buf.readUInt32LE(0x0468),

View File

@ -1,10 +1,10 @@
import { car } from "./_car"; import { car } from "./_car";
import { mission } from "./_mission"; import { mission } from "./_mission";
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { BackgroundCode, CourseNo, ExtId, TitleCode } from "../model/base"; import { BackgroundCode, CourseNo, TitleCode } from "../model/base";
import { Profile } from "../model/profile";
import { SaveProfileRequest2 } from "../request/saveProfile"; import { SaveProfileRequest2 } from "../request/saveProfile";
import { bitmap } from "./_bitmap"; import { bitmap } from "./_bitmap";
import { AimeId } from "../../model";
saveProfile3.msgCode = 0x0138 as RequestCode; saveProfile3.msgCode = 0x0138 as RequestCode;
saveProfile3.msgLen = 0x0a70; saveProfile3.msgLen = 0x0a70;
@ -49,7 +49,7 @@ export function saveProfile3(buf: Buffer): SaveProfileRequest2 {
return { return {
type: "save_profile_req", type: "save_profile_req",
format: 2, format: 2,
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
lv: buf.readUInt16LE(0x0026), lv: buf.readUInt16LE(0x0026),
exp: buf.readUInt32LE(0x0028), exp: buf.readUInt32LE(0x0028),
fame: buf.readUInt32LE(0x04fc), fame: buf.readUInt32LE(0x04fc),

View File

@ -1,7 +1,6 @@
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { ExtId } from "../model/base";
import { Profile } from "../model/profile";
import { SaveSettingsRequest } from "../request/saveSettings"; import { SaveSettingsRequest } from "../request/saveSettings";
import { AimeId } from "../../model";
saveSettings.msgCode = 0x00a5 as RequestCode; saveSettings.msgCode = 0x00a5 as RequestCode;
saveSettings.msgLen = 0x0020; saveSettings.msgLen = 0x0020;
@ -13,7 +12,7 @@ export function saveSettings(buf: Buffer): SaveSettingsRequest {
return { return {
type: "save_settings_req", type: "save_settings_req",
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
dpoint: buf.readUInt32LE(0x0008), dpoint: buf.readUInt32LE(0x0008),
settings: { settings: {
music: buf.readUInt16LE(0x0002), music: buf.readUInt16LE(0x0002),

View File

@ -1,10 +1,9 @@
import { bitmap } from "./_bitmap"; import { bitmap } from "./_bitmap";
import { chara } from "./_chara"; import { chara } from "./_chara";
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { BackgroundCode, ExtId } from "../model/base";
import { CarSelector } from "../model/car"; import { CarSelector } from "../model/car";
import { Profile } from "../model/profile";
import { SaveStockerRequest } from "../request/saveStocker"; import { SaveStockerRequest } from "../request/saveStocker";
import { AimeId } from "../../model";
saveStocker.msgCode = 0x00a6 as RequestCode; saveStocker.msgCode = 0x00a6 as RequestCode;
saveStocker.msgLen = 0x00c0; saveStocker.msgLen = 0x00c0;
@ -12,7 +11,7 @@ saveStocker.msgLen = 0x00c0;
export function saveStocker(buf: Buffer): SaveStockerRequest { export function saveStocker(buf: Buffer): SaveStockerRequest {
return { return {
type: "save_stocker_req", type: "save_stocker_req",
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
backgrounds: bitmap(buf.slice(0x0008, 0x002c)), backgrounds: bitmap(buf.slice(0x0008, 0x002c)),
selectedCar: buf.readUInt16LE(0x009c) as CarSelector, selectedCar: buf.readUInt16LE(0x009c) as CarSelector,

View File

@ -1,13 +1,13 @@
import { RequestCode } from "./_defs"; import { RequestCode } from "./_defs";
import { ExtId, RouteNo } from "../model/base"; import { RouteNo } from "../model/base";
import { CarSelector } from "../model/car"; import { CarSelector } from "../model/car";
import { Profile } from "../model/profile";
import { SaveTimeAttackRequest } from "../request/saveTimeAttack"; import { SaveTimeAttackRequest } from "../request/saveTimeAttack";
import { AimeId } from "../../model";
function saveTimeAttack(buf: Buffer): SaveTimeAttackRequest { function saveTimeAttack(buf: Buffer): SaveTimeAttackRequest {
return { return {
type: "save_time_attack_req", type: "save_time_attack_req",
profileId: buf.readUInt32LE(0x0004) as ExtId<Profile>, aimeId: buf.readUInt32LE(0x0004) as AimeId,
dayNight: buf.readUInt8(0x0054) & 1, dayNight: buf.readUInt8(0x0054) & 1,
payload: { payload: {
routeNo: (buf.readUInt8(0x0054) >> 1) as RouteNo, routeNo: (buf.readUInt8(0x0054) >> 1) as RouteNo,

View File

@ -7,7 +7,7 @@ unlockProfile.msgLen = 0x0020;
export function unlockProfile(buf: Buffer): UnlockProfileRequest { export function unlockProfile(buf: Buffer): UnlockProfileRequest {
return { return {
type: "unlock_profile_req", type: "unlock_profile_req",
profileId: buf.readUInt32LE(0x0004), aimeId: buf.readUInt32LE(0x0004),
pcbId: buf.slice(0x0008, buf.indexOf("\0", 0x0008)).toString("ascii"), pcbId: buf.slice(0x0008, buf.indexOf("\0", 0x0008)).toString("ascii"),
}; };
} }

View File

@ -78,7 +78,7 @@ export function loadProfile2(res: LoadProfileResponse2) {
buf.writeUInt16LE(0, 0x037c); // Team leader buf.writeUInt16LE(0, 0x037c); // Team leader
mission(res.missions.team).copy(buf, 0x038a); mission(res.missions.team).copy(buf, 0x038a);
buf.writeUInt16LE(0xffff, 0x0388); // [1] buf.writeUInt16LE(0xffff, 0x0388); // [1]
buf.writeUInt32LE(res.profileId, 0x03b8); buf.writeUInt32LE(res.aimeId, 0x03b8);
buf.writeUInt32LE(res.mileage, 0x03bc); buf.writeUInt32LE(res.mileage, 0x03bc);
buf.writeUInt16LE(res.settings.music, 0x03c8); buf.writeUInt16LE(res.settings.music, 0x03c8);
buf.writeUInt16LE(res.lv, 0x03cc); buf.writeUInt16LE(res.lv, 0x03cc);

View File

@ -78,7 +78,7 @@ export function loadProfile3(res: LoadProfileResponse3) {
buf.writeUInt16LE(0, 0x0456); // Team leader buf.writeUInt16LE(0, 0x0456); // Team leader
mission(res.missions.team).copy(buf, 0x0460); mission(res.missions.team).copy(buf, 0x0460);
buf.writeUInt16LE(0xffff, 0x0462); // [1] buf.writeUInt16LE(0xffff, 0x0462); // [1]
buf.writeUInt32LE(res.profileId, 0x0494); buf.writeUInt32LE(res.aimeId, 0x0494);
buf.writeUInt32LE(res.mileage, 0x0498); buf.writeUInt32LE(res.mileage, 0x0498);
buf.writeUInt16LE(res.settings.music, 0x04a4); buf.writeUInt16LE(res.settings.music, 0x04a4);
buf.writeUInt16LE(res.lv, 0x04a8); buf.writeUInt16LE(res.lv, 0x04a8);

View File

@ -46,6 +46,6 @@ export async function createProfile(
return { return {
type: "generic_res", type: "generic_res",
status: profileId, // "Generic response" my fucking *ass* status: req.aimeId, // "Generic response" my fucking *ass*
}; };
} }

View File

@ -6,8 +6,10 @@ export async function discoverProfile(
w: Repositories, w: Repositories,
req: DiscoverProfileRequest req: DiscoverProfileRequest
): Promise<DiscoverProfileResponse> { ): Promise<DiscoverProfileResponse> {
const profileId = await w.profile().find(req.aimeId);
return { return {
type: "discover_profile_res", type: "discover_profile_res",
exists: await w.profile().discoverByAimeId(req.aimeId), exists: profileId !== undefined,
}; };
} }

View File

@ -6,8 +6,10 @@ export async function loadGarage(
w: Repositories, w: Repositories,
req: LoadGarageRequest req: LoadGarageRequest
): Promise<LoadGarageResponse> { ): Promise<LoadGarageResponse> {
const profileId = await w.profile().find(req.aimeId);
return { return {
type: "load_garage_res", type: "load_garage_res",
cars: await w.car().loadAllCars(req.profileId), cars: await w.car().loadAllCars(profileId),
}; };
} }

View File

@ -6,27 +6,31 @@ export async function loadProfile(
w: Repositories, w: Repositories,
req: LoadProfileRequest req: LoadProfileRequest
): Promise<LoadProfileResponse> { ): Promise<LoadProfileResponse> {
const { aimeId } = req;
const profileId = await w.profile().find(aimeId);
// Promise.all would be messy here, who cares anyway this isn't supposed to // Promise.all would be messy here, who cares anyway this isn't supposed to
// be a high-performance server. // be a high-performance server.
const profile = await w.profile().loadByAimeId(req.aimeId); const profile = await w.profile().load(profileId);
const settings = await w.settings().load(profile.id); const settings = await w.settings().load(profileId);
const chara = await w.chara().load(profile.id); const chara = await w.chara().load(profileId);
const titles = await w.titles().loadAll(profile.id); const titles = await w.titles().loadAll(profileId);
const coursePlays = await w.coursePlays().loadAll(profile.id); const coursePlays = await w.coursePlays().loadAll(profileId);
const missions = await w.missions().load(profile.id); const missions = await w.missions().load(profileId);
const car = await w.car().loadSelectedCar(profile.id); const car = await w.car().loadSelectedCar(profileId);
const carCount = await w.car().countCars(profile.id); const carCount = await w.car().countCars(profileId);
const story = await w.story().load(profile.id); const story = await w.story().load(profileId);
const timeAttack = await w.timeAttack().loadAll(profile.id); const timeAttack = await w.timeAttack().loadAll(profileId);
const unlocks = await w.unlocks().load(profile.id); const unlocks = await w.unlocks().load(profileId);
const tickets = await w.tickets().load(profile.id); const tickets = await w.tickets().load(profileId);
return { return {
type: "load_profile_res", type: "load_profile_res",
format: req.format as any, // TS fart format: req.format as any, // TS fart
name: profile.name, name: profile.name,
profileId: profile.id, aimeId,
lv: profile.lv, lv: profile.lv,
exp: profile.exp, exp: profile.exp,
fame: profile.fame, fame: profile.fame,

View File

@ -6,7 +6,8 @@ export async function loadStocker(
w: Repositories, w: Repositories,
req: LoadStockerRequest req: LoadStockerRequest
): Promise<LoadStockerResponse> { ): Promise<LoadStockerResponse> {
const backgrounds = await w.backgrounds().loadAll(req.profileId); const profileId = await w.profile().find(req.aimeId);
const backgrounds = await w.backgrounds().loadAll(profileId);
return { return {
type: "load_stocker_res", type: "load_stocker_res",

View File

@ -6,7 +6,9 @@ export async function saveNewCar(
w: Repositories, w: Repositories,
req: SaveNewCarRequest req: SaveNewCarRequest
): Promise<SaveNewCarResponse> { ): Promise<SaveNewCarResponse> {
await w.car().saveCar(req.profileId, req.car); const profileId = await w.profile().find(req.aimeId);
await w.car().saveCar(profileId, req.car);
return { return {
type: "save_new_car_res", type: "save_new_car_res",

View File

@ -7,8 +7,9 @@ export async function saveProfile(
req: SaveProfileRequest req: SaveProfileRequest
): Promise<GenericResponse> { ): Promise<GenericResponse> {
const now = new Date(); const now = new Date();
const profile = await w.profile().load(req.profileId); const profileId = await w.profile().find(req.aimeId);
const chara = await w.chara().load(req.profileId); const profile = await w.profile().load(profileId);
const chara = await w.chara().load(profileId);
await w.profile().save( await w.profile().save(
{ {
@ -22,20 +23,20 @@ export async function saveProfile(
now now
); );
await w.chara().save(req.profileId, { await w.chara().save(profileId, {
...chara, ...chara,
title: req.title, title: req.title,
background: req.background, background: req.background,
}); });
await w.car().saveCar(req.profileId, req.car); await w.car().saveCar(profileId, req.car);
await w.coursePlays().saveAll(req.profileId, req.coursePlays); await w.coursePlays().saveAll(profileId, req.coursePlays);
await w.missions().save(req.profileId, req.missions); await w.missions().save(profileId, req.missions);
await w.story().save(req.profileId, req.story); await w.story().save(profileId, req.story);
await w.titles().saveAll(req.profileId, req.titles); await w.titles().saveAll(profileId, req.titles);
await w.unlocks().save(req.profileId, req.unlocks); await w.unlocks().save(profileId, req.unlocks);
await w.settings().save(req.profileId, req.settings); await w.settings().save(profileId, req.settings);
await w.tickets().save(req.profileId, req.tickets); await w.tickets().save(profileId, req.tickets);
return { return {
type: "generic_res", type: "generic_res",

View File

@ -6,7 +6,9 @@ export async function saveSettings(
w: Repositories, w: Repositories,
req: SaveSettingsRequest req: SaveSettingsRequest
): Promise<GenericResponse> { ): Promise<GenericResponse> {
await w.settings().save(req.profileId, req.settings); const profileId = await w.profile().find(req.aimeId);
await w.settings().save(profileId, req.settings);
return { type: "generic_res" }; return { type: "generic_res" };
} }

View File

@ -6,10 +6,12 @@ export async function saveStocker(
w: Repositories, w: Repositories,
req: SaveStockerRequest req: SaveStockerRequest
): Promise<GenericResponse> { ): Promise<GenericResponse> {
const profileId = await w.profile().find(req.aimeId);
await Promise.all([ await Promise.all([
w.backgrounds().saveAll(req.profileId, req.backgrounds), w.backgrounds().saveAll(profileId, req.backgrounds),
w.chara().save(req.profileId, req.chara), w.chara().save(profileId, req.chara),
w.car().saveSelection(req.profileId, req.selectedCar), w.car().saveSelection(profileId, req.selectedCar),
]); ]);
return { type: "generic_res" }; return { type: "generic_res" };

View File

@ -13,9 +13,10 @@ export async function saveTimeAttack(
// Override client time since we might be doing some maintenance window // Override client time since we might be doing some maintenance window
// avoidance time warping stuff // avoidance time warping stuff
await w const now = new Date();
.timeAttack() const profileId = await w.profile().find(req.aimeId);
.save(req.profileId, { ...req.payload, timestamp: new Date() });
await w.timeAttack().save(profileId, { ...req.payload, timestamp: now });
} }
return { return {

View File

@ -1,8 +1,9 @@
import { ExtId } from "./base"; import { ExtId } from "./base";
import { Team } from "./team"; import { Team } from "./team";
import { AimeId } from "../../model";
export interface Profile { export interface Profile {
id: ExtId<Profile>; aimeId: AimeId;
teamId?: ExtId<Team>; teamId?: ExtId<Team>;
name: string; name: string;
lv: number; lv: number;

View File

@ -2,59 +2,52 @@ import { Subtract } from "utility-types";
import * as Model from "./model"; import * as Model from "./model";
import { AimeId } from "../model"; import { AimeId } from "../model";
import { Id } from "../db";
export type ProfileSpec = Subtract< export type ProfileSpec = Subtract<Model.Profile, { aimeId: AimeId }>;
Model.Profile,
{ id: Model.ExtId<Model.Profile> }
>;
export interface CarRepository { export interface CarRepository {
countCars(profileId: Model.ExtId<Model.Profile>): Promise<number>; countCars(profileId: Id<Model.Profile>): Promise<number>;
loadAllCars(profileId: Model.ExtId<Model.Profile>): Promise<Model.Car[]>; loadAllCars(profileId: Id<Model.Profile>): Promise<Model.Car[]>;
loadSelectedCar(profileId: Model.ExtId<Model.Profile>): Promise<Model.Car>; loadSelectedCar(profileId: Id<Model.Profile>): Promise<Model.Car>;
saveCar( saveCar(profileId: Id<Model.Profile>, car: Model.Car): Promise<void>;
profileId: Model.ExtId<Model.Profile>,
car: Model.Car
): Promise<void>;
saveSelection( saveSelection(
profileId: Model.ExtId<Model.Profile>, profileId: Id<Model.Profile>,
selector: Model.CarSelector selector: Model.CarSelector
): Promise<void>; ): Promise<void>;
} }
export interface CoursePlaysRepository { export interface CoursePlaysRepository {
loadAll( loadAll(profileId: Id<Model.Profile>): Promise<Map<Model.CourseNo, number>>;
profileId: Model.ExtId<Model.Profile>
): Promise<Map<Model.CourseNo, number>>;
saveAll( saveAll(
profileId: Model.ExtId<Model.Profile>, profileId: Id<Model.Profile>,
counts: Map<Model.CourseNo, number> counts: Map<Model.CourseNo, number>
): Promise<void>; ): Promise<void>;
} }
export interface FacetRepository<T> { export interface FacetRepository<T> {
load(profileId: Model.ExtId<Model.Profile>): Promise<T>; load(profileId: Id<Model.Profile>): Promise<T>;
save(profileId: Model.ExtId<Model.Profile>, facet: T): Promise<void>; save(profileId: Id<Model.Profile>, facet: T): Promise<void>;
} }
export interface FlagRepository<T extends number> { export interface FlagRepository<T extends number> {
loadAll(profileId: Model.ExtId<Model.Profile>): Promise<Set<T>>; loadAll(profileId: Id<Model.Profile>): Promise<Set<T>>;
saveAll(profileId: Model.ExtId<Model.Profile>, items: Set<T>): Promise<void>; saveAll(profileId: Id<Model.Profile>, items: Set<T>): Promise<void>;
} }
export interface ProfileRepository { export interface ProfileRepository {
discoverByAimeId(id: AimeId): Promise<boolean>; find(aimeId: AimeId): Promise<Id<Model.Profile>>;
loadByAimeId(id: AimeId): Promise<Model.Profile>; peek(aimeId: AimeId): Promise<Id<Model.Profile> | undefined>;
load(id: Model.ExtId<Model.Profile>): Promise<Model.Profile>; load(id: Id<Model.Profile>): Promise<Model.Profile>;
save(profile: Model.Profile, timestamp: Date): Promise<void>; save(profile: Model.Profile, timestamp: Date): Promise<void>;
@ -62,7 +55,7 @@ export interface ProfileRepository {
aimeId: AimeId, aimeId: AimeId,
profile: ProfileSpec, profile: ProfileSpec,
timestamp: Date timestamp: Date
): Promise<Model.ExtId<Model.Profile>>; ): Promise<Id<Model.Profile>>;
} }
// TODO extend and factorize // TODO extend and factorize
@ -77,12 +70,10 @@ export interface TimeAttackRepository {
minTimestamp: Date minTimestamp: Date
): Promise<TopTenResult[]>; ): Promise<TopTenResult[]>;
loadAll( loadAll(profileId: Id<Model.Profile>): Promise<Model.TimeAttackScore[]>;
profileId: Model.ExtId<Model.Profile>
): Promise<Model.TimeAttackScore[]>;
save( save(
profileId: Model.ExtId<Model.Profile>, profileId: Id<Model.Profile>,
score: Model.TimeAttackScore score: Model.TimeAttackScore
): Promise<void>; ): Promise<void>;
} }

View File

@ -1,9 +1,8 @@
import { ExtId } from "../model/base"; import { AimeId } from "../../model";
import { Profile } from "../model/profile";
export interface CreateTeamRequest { export interface CreateTeamRequest {
type: "create_team_req"; type: "create_team_req";
profileId: ExtId<Profile>; // u32 aimeId: AimeId;
teamName: string; // len 0x20 teamName: string; // len 0x20
field_0028: number; // u16 field_0028: number; // u16
field_002C: number; // u32 (but only holds a u8) field_002C: number; // u32 (but only holds a u8)

View File

@ -1,11 +1,11 @@
import { ExtId } from "../model/base"; import { ExtId } from "../model/base";
import { Profile } from "../model/profile";
import { Team } from "../model/team"; import { Team } from "../model/team";
import { AimeId } from "../../model";
interface Load2on2RequestBase { interface Load2on2RequestBase {
type: "load_2on2_req"; type: "load_2on2_req";
field_0002: number; field_0002: number;
profileId: ExtId<Profile>; aimeId: AimeId;
teamId: ExtId<Team>; teamId: ExtId<Team>;
} }

View File

@ -1,7 +1,6 @@
import { ExtId } from "../model/base"; import { AimeId } from "../../model";
import { Profile } from "../model/profile";
export interface LoadEventInfoRequest { export interface LoadEventInfoRequest {
type: "load_event_info_req"; type: "load_event_info_req";
profileId: ExtId<Profile>; aimeId: AimeId;
} }

View File

@ -1,7 +1,6 @@
import { ExtId } from "../model/base"; import { AimeId } from "../../model";
import { Profile } from "../model/profile";
export interface LoadGachaRequest { export interface LoadGachaRequest {
type: "load_gacha_req"; type: "load_gacha_req";
profileId: ExtId<Profile>; aimeId: AimeId;
} }

View File

@ -1,9 +1,8 @@
import { ExtId } from "../model/base"; import { AimeId } from "../../model";
import { Profile } from "../model/profile";
export interface LoadGarageRequest { export interface LoadGarageRequest {
type: "load_garage_req"; type: "load_garage_req";
profileId: ExtId<Profile>; aimeId: AimeId;
fetchOffset: number; fetchOffset: number;
field_000A: number; field_000A: number;
} }

View File

@ -1,9 +1,8 @@
import { ExtId } from "../model/base"; import { AimeId } from "../../model";
import { Profile } from "../model/profile";
interface LoadGeneralRewardRequestBase { interface LoadGeneralRewardRequestBase {
type: "load_general_reward_req"; type: "load_general_reward_req";
profileId: ExtId<Profile>; aimeId: AimeId;
} }
export interface LoadGeneralRewardRequest1 export interface LoadGeneralRewardRequest1

View File

@ -1,7 +1,6 @@
import { ExtId } from "../model/base"; import { AimeId } from "../../model";
import { Profile } from "../model/profile";
export interface LoadStockerRequest { export interface LoadStockerRequest {
type: "load_stocker_req"; type: "load_stocker_req";
profileId: ExtId<Profile>; aimeId: AimeId;
} }

View File

@ -1,5 +1,5 @@
export interface LoadTeamRequest { export interface LoadTeamRequest {
type: "load_team_req"; type: "load_team_req";
profileId: number; aimeId: number;
teamId: number; teamId: number;
} }

View File

@ -1,6 +1,6 @@
import { ExtId, RouteNo } from "../model/base"; import { ExtId, RouteNo } from "../model/base";
import { Profile } from "../model/profile";
import { Team } from "../model/team"; import { Team } from "../model/team";
import { AimeId } from "../../model";
export interface LoadTopTenRequestSelector { export interface LoadTopTenRequestSelector {
routeNo: RouteNo; routeNo: RouteNo;
@ -14,6 +14,6 @@ export interface LoadTopTenRequest {
field_C4: number; field_C4: number;
field_C5: number; field_C5: number;
field_C6: number; field_C6: number;
profileId?: ExtId<Profile>; aimeId?: AimeId;
teamId?: ExtId<Team>; teamId?: ExtId<Team>;
} }

View File

@ -1,6 +1,6 @@
export interface LockProfileRequest { export interface LockProfileRequest {
type: "lock_profile_req"; type: "lock_profile_req";
profileId: number; aimeId: number;
pcbId: string; pcbId: string;
field_0018: number; field_0018: number;
} }

View File

@ -1,8 +1,7 @@
import { ExtId } from "../model/base"; import { AimeId } from "../../model";
import { Profile } from "../model/profile";
export interface LockProfileExtendRequest { export interface LockProfileExtendRequest {
type: "lock_profile_extend_req"; type: "lock_profile_extend_req";
profileId: ExtId<Profile>; aimeId: AimeId;
luid: string; luid: string;
} }

View File

@ -2,7 +2,7 @@ import { Car } from "../model/car";
export interface SaveGarageRequest { export interface SaveGarageRequest {
type: "save_garage_req"; type: "save_garage_req";
profileId: number; aimeId: number;
payload: Car; payload: Car;
field_0068: number[]; field_0068: number[];
field_0080: number; field_0080: number;

View File

@ -1,10 +1,9 @@
import { ExtId } from "../model/base";
import { Car } from "../model/car"; import { Car } from "../model/car";
import { Profile } from "../model/profile"; import { AimeId } from "../../model";
export interface SaveNewCarRequest { export interface SaveNewCarRequest {
type: "save_new_car_req"; type: "save_new_car_req";
profileId: ExtId<Profile>; aimeId: AimeId;
luid: string; luid: string;
car: Car; car: Car;
field_0080: number; field_0080: number;

View File

@ -1,15 +1,15 @@
import { BackgroundCode, CourseNo, ExtId, TitleCode } from "../model/base"; import { BackgroundCode, CourseNo, ExtId, TitleCode } from "../model/base";
import { Car } from "../model/car"; import { Car } from "../model/car";
import { MissionState } from "../model/mission"; import { MissionState } from "../model/mission";
import { Profile } from "../model/profile";
import { Settings } from "../model/settings"; import { Settings } from "../model/settings";
import { Story } from "../model/story"; import { Story } from "../model/story";
import { Tickets } from "../model/tickets"; import { Tickets } from "../model/tickets";
import { Unlocks } from "../model/unlocks"; import { Unlocks } from "../model/unlocks";
import { AimeId } from "../../model";
interface SaveProfileRequestBase { interface SaveProfileRequestBase {
type: "save_profile_req"; type: "save_profile_req";
profileId: ExtId<Profile>; aimeId: AimeId;
lv: number; lv: number;
exp: number; exp: number;
fame: number; fame: number;

View File

@ -1,10 +1,9 @@
import { ExtId } from "../model/base";
import { Profile } from "../model/profile";
import { Settings } from "../model/settings"; import { Settings } from "../model/settings";
import { AimeId } from "../../model";
export interface SaveSettingsRequest { export interface SaveSettingsRequest {
type: "save_settings_req"; type: "save_settings_req";
profileId: ExtId<Profile>; aimeId: AimeId;
dpoint: number; // ?? why dpoint: number; // ?? why
settings: Settings; settings: Settings;
field_0010: number; field_0010: number;

View File

@ -1,11 +1,11 @@
import { BackgroundCode, ExtId } from "../model/base"; import { BackgroundCode } from "../model/base";
import { CarSelector } from "../model/car"; import { CarSelector } from "../model/car";
import { Chara } from "../model/chara"; import { Chara } from "../model/chara";
import { Profile } from "../model/profile"; import { AimeId } from "../../model";
export interface SaveStockerRequest { export interface SaveStockerRequest {
type: "save_stocker_req"; type: "save_stocker_req";
profileId: ExtId<Profile>; aimeId: AimeId;
selectedCar: CarSelector; selectedCar: CarSelector;
backgrounds: Set<BackgroundCode>; backgrounds: Set<BackgroundCode>;
chara: Chara; chara: Chara;

View File

@ -1,11 +1,9 @@
import { ExtId } from "../model/base";
import { CarSelector } from "../model/car";
import { Profile } from "../model/profile";
import { TimeAttackScore } from "../model/timeAttack"; import { TimeAttackScore } from "../model/timeAttack";
import { AimeId } from "../../model";
export interface SaveTimeAttackRequest { export interface SaveTimeAttackRequest {
type: "save_time_attack_req"; type: "save_time_attack_req";
profileId: ExtId<Profile>; // u32 aimeId: AimeId;
dayNight: number; dayNight: number;
payload: TimeAttackScore; payload: TimeAttackScore;
field_0002: number; // u16, always 1 field_0002: number; // u16, always 1

View File

@ -1,5 +1,5 @@
export interface UnlockProfileRequest { export interface UnlockProfileRequest {
type: "unlock_profile_req"; type: "unlock_profile_req";
profileId: number; aimeId: number;
pcbId: string; pcbId: string;
} }

View File

@ -1,18 +1,18 @@
import { ExtId, TitleCode } from "../model/base"; import { TitleCode } from "../model/base";
import { Car } from "../model/car"; import { Car } from "../model/car";
import { Chara } from "../model/chara"; import { Chara } from "../model/chara";
import { MissionState } from "../model/mission"; import { MissionState } from "../model/mission";
import { Profile } from "../model/profile";
import { Settings } from "../model/settings"; import { Settings } from "../model/settings";
import { Story } from "../model/story"; import { Story } from "../model/story";
import { Tickets } from "../model/tickets"; import { Tickets } from "../model/tickets";
import { TimeAttackScore } from "../model/timeAttack"; import { TimeAttackScore } from "../model/timeAttack";
import { Unlocks } from "../model/unlocks"; import { Unlocks } from "../model/unlocks";
import { AimeId } from "../../model";
interface LoadProfileResponseBase { interface LoadProfileResponseBase {
type: "load_profile_res"; type: "load_profile_res";
name: string; name: string;
profileId: ExtId<Profile>; aimeId: AimeId;
lv: number; lv: number;
exp: number; exp: number;
fame: number; fame: number;