diff --git a/schema/init/idz.sql b/schema/init/idz.sql index 9084f02..6252169 100644 --- a/schema/init/idz.sql +++ b/schema/init/idz.sql @@ -278,3 +278,12 @@ create table "idz_weekly_missions" ( "progress_right" integer not null, "params_right" integer not null ); + +create table "idz_my_chara" ( + "id" integer primary key not null, + "profile_id" integer not null + references "idz_profile"("id") + on delete cascade, + "my_chara_no" integer not null, + constraint "idz_my_chara_uq" unique ("profile_id", "my_chara_no") +); diff --git a/schema/migrate/M0017-idz-v2-support.sql b/schema/migrate/M0017-idz-v2-support.sql index 8a88986..d04bffb 100644 --- a/schema/migrate/M0017-idz-v2-support.sql +++ b/schema/migrate/M0017-idz-v2-support.sql @@ -1,3 +1,12 @@ +create table "idz_my_chara" ( + "id" integer primary key not null, + "profile_id" integer not null + references "idz_profile"("id") + on delete cascade, + "my_chara_no" integer not null, + constraint "idz_my_chara_uq" unique ("profile_id", "my_chara_no") +); + create table "new_idz_settings" ( "id" integer primary key not null references "idz_profile"("id") diff --git a/src/idz/userdb/model/base.ts b/src/idz/userdb/model/base.ts index 21e0b94..e15d7ce 100644 --- a/src/idz/userdb/model/base.ts +++ b/src/idz/userdb/model/base.ts @@ -4,6 +4,7 @@ export type BackgroundCode = number & { __brand: "backgroundCode" }; export type CourseNo = number & { __brand: "courseNo" }; export type ExtId = number & { __extId: T }; +export type MyCharaCode = number & { __brand: "myCharaCode" }; export type RouteNo = number & { __brand: "routeNo" }; export type StampCode = number & { __brand: "stampCode" }; export type TitleCode = number & { __brand: "titleCode" }; diff --git a/src/idz/userdb/model/index.ts b/src/idz/userdb/model/index.ts index 4802903..de2c806 100644 --- a/src/idz/userdb/model/index.ts +++ b/src/idz/userdb/model/index.ts @@ -2,6 +2,7 @@ export { BackgroundCode, CourseNo, ExtId, + MyCharaCode, RouteNo, StampCode, TitleCode, diff --git a/src/idz/userdb/repo.ts b/src/idz/userdb/repo.ts index 55e1935..2e88570 100644 --- a/src/idz/userdb/repo.ts +++ b/src/idz/userdb/repo.ts @@ -177,6 +177,8 @@ export interface Repositories { // not really a facet tbh missions(): FacetRepository; + myChara(): FlagRepository; + profile(): ProfileRepository; settings(): FacetRepository; diff --git a/src/idz/userdb/sql/index.ts b/src/idz/userdb/sql/index.ts index 486a908..953f93f 100644 --- a/src/idz/userdb/sql/index.ts +++ b/src/idz/userdb/sql/index.ts @@ -3,6 +3,7 @@ import { SqlCarRepository } from "./car"; import { SqlCharaRepository } from "./chara"; import { SqlCoursePlaysRepository } from "./coursePlays"; import { SqlMissionsRepository } from "./missions"; +import { SqlMyCharaRepository } from "./myChara"; import { SqlProfileRepository } from "./profile"; import { SqlSettingsRepository } from "./settings"; import { SqlStampsRepository } from "./stamps"; @@ -43,6 +44,10 @@ export class SqlRepositories implements Repo.Repositories { return new SqlMissionsRepository(this._txn); } + myChara(): Repo.FlagRepository { + return new SqlMyCharaRepository(this._txn); + } + profile(): Repo.ProfileRepository { return new SqlProfileRepository(this._txn); } diff --git a/src/idz/userdb/sql/myChara.ts b/src/idz/userdb/sql/myChara.ts new file mode 100644 index 0000000..6060b96 --- /dev/null +++ b/src/idz/userdb/sql/myChara.ts @@ -0,0 +1,52 @@ +import sql from "sql-bricks-postgres"; + +import { MyCharaCode } from "../model/base"; +import { Profile } from "../model/profile"; +import { FlagRepository } from "../repo"; +import { Id } from "../../../model"; +import { Transaction } from "../../../sql"; + +export class SqlMyCharaRepository implements FlagRepository { + constructor(private readonly _txn: Transaction) {} + + async loadAll(id: Id): Promise> { + const loadSql = sql + .select("mc.my_chara_no") + .from("idz_mychara_unlock mc") + .join("idz_profile p", { "mc.profile_id": "p.id" }) + .where("p.id", id); + + const rows = await this._txn.fetchRows(loadSql); + const result = new Set(); + + for (const row of rows) { + result.add(parseInt(row.my_chara_no!) as MyCharaCode); + } + + return result; + } + + async saveAll( + profileId: Id, + flags: Set + ): Promise { + const existing = await this.loadAll(profileId); + + for (const flag of flags) { + if (existing.has(flag)) { + continue; + } + + const saveSql = sql + .insert("idz_mychara_unlock", { + id: this._txn.generateId(), + profile_id: profileId, + my_chara_no: flag, + }) + .onConflict("profile_id", "my_chara_no") + .doNothing(); + + await this._txn.modify(saveSql); + } + } +}