mirror of
https://gitea.tendokyu.moe/ppc/amnet.git
synced 2026-09-22 22:28:22 +03:00
move "most recent card used" tracking to separate table
This commit is contained in:
@@ -28,6 +28,7 @@ import {AMCard} from "../models/AMCard";
|
||||
|
||||
import {felicaCardReadAsync, icCard0008Number, ICType} from "../lib/iccard";
|
||||
import {
|
||||
AMCardInRequest,
|
||||
AMServerConnectionInfo,
|
||||
AMServerInstanceMetrics,
|
||||
fetchServerInfo,
|
||||
@@ -36,6 +37,7 @@ import {
|
||||
} from "amnet-shared";
|
||||
|
||||
import ObjectId = BSON.ObjectId;
|
||||
import {AMCardRecentUse} from "../models/AMCardRecentUse";
|
||||
|
||||
const {useRealm, useQuery, useObject} = RealmContext;
|
||||
|
||||
@@ -69,13 +71,9 @@ export default function ServerCardIn({route, navigation}) {
|
||||
const [cardInCompleted, setCardInCompleted] = useState<boolean>(null);
|
||||
|
||||
const disableCardIn = useMemo(() => cardInCompleted !== null || !serverConnectionSuccess, [cardInCompleted, serverConnectionSuccess]);
|
||||
const serverDefaultCard = useMemo(() => {
|
||||
if (server?.isValid() !== true || !server.gameId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return cards.find(x => x.lastUsedGameId === server.gameId);
|
||||
}, [cards, server?.gameId]);
|
||||
const serverDefaultCardQuery = useObject(AMCardRecentUse, server.gameId);
|
||||
const serverDefaultCard = serverDefaultCardQuery?.card ?? null;
|
||||
|
||||
const selectedCard = useMemo(() => [userSelectedCard, serverDefaultCard, cards.at(0)].find(x => x?.isValid() == true) ?? null, [userSelectedCard, serverDefaultCard, cards]);
|
||||
const unselectedCards = useMemo(() => cards.filter(x => x.isValid() === true && x._id.toHexString() !== selectedCard?._id.toHexString()), [cards, selectedCard]);
|
||||
@@ -154,17 +152,25 @@ export default function ServerCardIn({route, navigation}) {
|
||||
setCardInCompleted(false);
|
||||
|
||||
const abortController = new AbortController();
|
||||
|
||||
performCardIn(server, {
|
||||
const request: AMCardInRequest = {
|
||||
cardId: card.code,
|
||||
physicalCardIDm: card.physicalCardData?.cardIDm ?? undefined
|
||||
}, abortController.signal).then(r => {
|
||||
};
|
||||
|
||||
performCardIn(server, request, abortController.signal).then(r => {
|
||||
const now = new Date();
|
||||
realm.write(() => {
|
||||
server.lastUsed = now;
|
||||
|
||||
card.lastUsed = now;
|
||||
card.lastUsedGameId = server.gameId;
|
||||
|
||||
// replace the "most recent card" record
|
||||
if (server.gameId) {
|
||||
if (serverDefaultCardQuery) {
|
||||
realm.delete(serverDefaultCardQuery);
|
||||
}
|
||||
|
||||
realm.create(AMCardRecentUse.schema.name, AMCardRecentUse.generate(server.gameId, card));
|
||||
}
|
||||
});
|
||||
|
||||
setCardInCompleted(r);
|
||||
|
||||
@@ -5,8 +5,8 @@ import {CreditCard, Gem, History, Joystick, LucideIcon, RailSymbol} from "lucide
|
||||
import TimeAgo from "./TimeAgo";
|
||||
import {AMUICard, AMUICardActionProps, AMUICardDetail} from "./AMUICard";
|
||||
|
||||
import {AMCardData} from "../models/AMCard";
|
||||
import {AmusementICVendor, ICType} from "../lib/iccard";
|
||||
import {AMCardData} from "../models/AMCardData";
|
||||
|
||||
export interface ICCardProps extends AMUICardActionProps {
|
||||
card: AMCardData,
|
||||
@@ -68,7 +68,7 @@ function PhysicalICInfo(props: { card: AMCardData | null }) {
|
||||
function ICVendorName(vendor: AmusementICVendor): string {
|
||||
switch (vendor) {
|
||||
case AmusementICVendor.Sega:
|
||||
return "AiMe Card";
|
||||
return "Aime Card";
|
||||
|
||||
case AmusementICVendor.Konami:
|
||||
return "e-Amusement Pass";
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
import {Realm} from "realm";
|
||||
import {AmusementICVendor, ICType} from "../lib/iccard";
|
||||
|
||||
export interface AMCardData {
|
||||
code: string;
|
||||
name: string;
|
||||
|
||||
added: Date;
|
||||
lastUsed?: Date | null;
|
||||
isLimitedAimeCard: boolean;
|
||||
physicalCardData?: AMPhysicalCardData | null;
|
||||
}
|
||||
import {AMCardRecentUse} from "./AMCardRecentUse";
|
||||
import {AMCardData} from "./AMCardData";
|
||||
|
||||
export class AMCard extends Realm.Object<AMCard> implements AMCardData {
|
||||
_id!: Realm.BSON.ObjectId;
|
||||
@@ -18,9 +10,9 @@ export class AMCard extends Realm.Object<AMCard> implements AMCardData {
|
||||
name: string;
|
||||
|
||||
added: Date;
|
||||
lastUsed?: Date;
|
||||
lastUsedGameId?: string | null;
|
||||
lastUsed: Date;
|
||||
|
||||
recentUses: Realm.Results<AMCardRecentUse>;
|
||||
physicalCardData?: AMPhysicalCardData | null = null;
|
||||
|
||||
get isLimitedAimeCard() {
|
||||
@@ -43,6 +35,8 @@ export class AMCard extends Realm.Object<AMCard> implements AMCardData {
|
||||
realm.delete(card.physicalCardData);
|
||||
}
|
||||
|
||||
// remove any usage history tied to the card
|
||||
realm.delete(card.recentUses);
|
||||
realm.delete(card);
|
||||
});
|
||||
}
|
||||
@@ -54,15 +48,18 @@ export class AMCard extends Realm.Object<AMCard> implements AMCardData {
|
||||
properties: {
|
||||
_id: "objectId",
|
||||
code: "string",
|
||||
name: {type: "string", default: "New Card"},
|
||||
added: {type: "date", default: new Date()},
|
||||
name: {type: "string", default: "New Card", indexed: true},
|
||||
added: {type: "date", default: new Date(), indexed: true},
|
||||
lastUsed: {type: "date", optional: true, indexed: true},
|
||||
lastUsedGameId: {type: "string", optional: true, indexed: true},
|
||||
usageHistory: {type: "linkingObjects", objectType: "cardUsageHistory", property: "_id"},
|
||||
physicalCardData: {type: "object", objectType: "physicalCard", optional: true}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds physical card information when a card is imported via NFC/FeliCa
|
||||
*/
|
||||
export class AMPhysicalCardData extends Realm.Object<AMPhysicalCardData> {
|
||||
|
||||
cardIDm: string;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import {AMPhysicalCardData} from "./AMCard";
|
||||
|
||||
export interface AMCardData {
|
||||
code: string;
|
||||
name: string;
|
||||
|
||||
added: Date;
|
||||
lastUsed?: Date | null;
|
||||
isLimitedAimeCard: boolean;
|
||||
physicalCardData?: AMPhysicalCardData | null;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import {Realm} from "realm";
|
||||
import {AMCard} from "./AMCard";
|
||||
|
||||
/**
|
||||
* Represents a usage of a card for determining which card was last used on a specific game.
|
||||
*/
|
||||
export class AMCardRecentUse extends Realm.Object<AMCardRecentUse> {
|
||||
|
||||
/**
|
||||
* The game id that is being tracked
|
||||
*/
|
||||
gameId: string;
|
||||
|
||||
/**
|
||||
* The card that was last used on the game.
|
||||
* If the card is removed, this record will also be removed.
|
||||
*/
|
||||
card: AMCard;
|
||||
|
||||
static generate(gameId: string, card: AMCard) {
|
||||
return {
|
||||
gameId: gameId,
|
||||
card: card
|
||||
};
|
||||
}
|
||||
|
||||
static schema: Realm.ObjectSchema = {
|
||||
name: "cardUsageHistory",
|
||||
primaryKey: "gameId",
|
||||
|
||||
properties: {
|
||||
gameId: "string",
|
||||
card: {type: "object", objectType: "card", optional: false}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +1,43 @@
|
||||
import {Realm} from "realm";
|
||||
import {createRealmContext} from "@realm/react";
|
||||
import {AMCard, AMPhysicalCardData} from "./AMCard";
|
||||
|
||||
import {AMServer} from "./AMServer";
|
||||
import {AMCardRecentUse} from "./AMCardRecentUse";
|
||||
import {AMCard, AMPhysicalCardData} from "./AMCard";
|
||||
|
||||
const migrationFunction = (oldRealm: Realm, newRealm: Realm) => {
|
||||
if (oldRealm.schemaVersion < 5) {
|
||||
const oldCards = oldRealm.objects("card");
|
||||
const gameIdMap: Map<string, { card: any, lastUsed: Date }> = new Map();
|
||||
|
||||
// get last used card for each game
|
||||
oldCards.forEach((card: any) => {
|
||||
if (card.lastUsedGameId && card.lastUsed) {
|
||||
const existing = gameIdMap.get(card.lastUsedGameId);
|
||||
if (!existing || card.lastUsed > existing.lastUsed) {
|
||||
gameIdMap.set(card.lastUsedGameId, { card, lastUsed: card.lastUsed });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// write new history records
|
||||
const newCards = newRealm.objects("card");
|
||||
newRealm.write(() => {
|
||||
gameIdMap.forEach((value, gameId) => {
|
||||
const newCard = newCards.filtered(`_id == $0`, value.card._id)[0];
|
||||
newRealm.create("cardUsageHistory", {
|
||||
gameId: gameId,
|
||||
card: newCard
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
export default createRealmContext({
|
||||
schemaVersion: 4,
|
||||
schema: [AMPhysicalCardData, AMCard, AMServer],
|
||||
deleteRealmIfMigrationNeeded: false
|
||||
});
|
||||
schemaVersion: 5,
|
||||
schema: [AMPhysicalCardData, AMCardRecentUse, AMCard, AMServer],
|
||||
onMigration: migrationFunction,
|
||||
deleteRealmIfMigrationNeeded: false,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user