added kamaitachi export
This commit is contained in:
parent
0036ed8934
commit
4484bedb86
@ -0,0 +1,209 @@
|
||||
"use server";
|
||||
import { getAuth } from "@/auth/queries/getauth";
|
||||
import { getSupportedVersionNumber } from "@/lib/api";
|
||||
import { artemis } from "@/lib/prisma";
|
||||
import { fromZonedTime, toZonedTime } from "date-fns-tz";
|
||||
import { parse } from "date-fns";
|
||||
|
||||
const TACHI_CLASSES = [
|
||||
undefined,
|
||||
"DAN_I",
|
||||
"DAN_II",
|
||||
"DAN_III",
|
||||
"DAN_IV",
|
||||
"DAN_V",
|
||||
"DAN_INFINITE",
|
||||
] as const;
|
||||
const TACHI_DIFFICULTIES = [
|
||||
"BASIC",
|
||||
"ADVANCED",
|
||||
"EXPERT",
|
||||
"MASTER",
|
||||
"ULTIMA",
|
||||
] as const;
|
||||
|
||||
type BatchManualLamp =
|
||||
| "ALL JUSTICE CRITICAL"
|
||||
| "ALL JUSTICE"
|
||||
| "FULL COMBO"
|
||||
| "CLEAR"
|
||||
| "FAILED";
|
||||
interface BatchManualScore {
|
||||
identifier: string;
|
||||
matchType: "inGameID";
|
||||
score: number;
|
||||
lamp: BatchManualLamp;
|
||||
difficulty: "BASIC" | "ADVANCED" | "EXPERT" | "MASTER" | "ULTIMA";
|
||||
timeAchieved?: number;
|
||||
judgements?: {
|
||||
jcrit: number;
|
||||
justice: number;
|
||||
attack: number;
|
||||
miss: number;
|
||||
};
|
||||
optional?: {
|
||||
maxCombo: number;
|
||||
};
|
||||
}
|
||||
interface BatchManualImport {
|
||||
meta: {
|
||||
game: string;
|
||||
playtype: string;
|
||||
service: string;
|
||||
};
|
||||
scores: BatchManualScore[];
|
||||
classes?: {
|
||||
dan?: string;
|
||||
emblem?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export async function getTachiExport() {
|
||||
const { user } = await getAuth();
|
||||
const version = await getSupportedVersionNumber();
|
||||
|
||||
if (!user || !user.accessCode) {
|
||||
throw new Error("User is not authenticated or accessCode is missing");
|
||||
}
|
||||
|
||||
const profile = await artemis.chuni_profile_data.findFirst({
|
||||
where: {
|
||||
user: user.UserId,
|
||||
version,
|
||||
},
|
||||
select: {
|
||||
classEmblemBase: true,
|
||||
classEmblemMedal: true,
|
||||
},
|
||||
});
|
||||
const playlog = await artemis.chuni_score_playlog.findMany({
|
||||
where: {
|
||||
user: user.UserId,
|
||||
},
|
||||
select: {
|
||||
romVersion: true,
|
||||
userPlayDate: true,
|
||||
musicId: true,
|
||||
level: true,
|
||||
score: true,
|
||||
maxCombo: true,
|
||||
judgeGuilty: true,
|
||||
judgeAttack: true,
|
||||
judgeJustice: true,
|
||||
judgeCritical: true,
|
||||
judgeHeaven: true,
|
||||
isFullCombo: true,
|
||||
isAllJustice: true,
|
||||
isClear: true,
|
||||
},
|
||||
});
|
||||
|
||||
const tachiExport: BatchManualImport = {
|
||||
meta: {
|
||||
game: "chunithm",
|
||||
playtype: "Single",
|
||||
service: "Cozynet",
|
||||
},
|
||||
scores: [],
|
||||
classes: {
|
||||
dan: TACHI_CLASSES[profile?.classEmblemBase ?? 0],
|
||||
emblem: TACHI_CLASSES[profile?.classEmblemMedal ?? 0],
|
||||
},
|
||||
};
|
||||
|
||||
for (const log of playlog) {
|
||||
const {
|
||||
romVersion,
|
||||
userPlayDate,
|
||||
musicId,
|
||||
level,
|
||||
score,
|
||||
judgeHeaven,
|
||||
judgeCritical,
|
||||
judgeJustice,
|
||||
judgeAttack,
|
||||
judgeGuilty,
|
||||
maxCombo,
|
||||
isAllJustice,
|
||||
isFullCombo,
|
||||
isClear,
|
||||
} = log;
|
||||
|
||||
if (
|
||||
romVersion === null ||
|
||||
musicId === null ||
|
||||
level === null ||
|
||||
score === null ||
|
||||
judgeJustice === null ||
|
||||
isAllJustice === null ||
|
||||
isFullCombo === null ||
|
||||
isClear === null
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Filter out WORLD'S END scores
|
||||
if (romVersion.startsWith("1.") && level === 4) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (romVersion.startsWith("2.") && level === 5) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let lamp: BatchManualLamp = "FAILED";
|
||||
|
||||
if (isAllJustice && judgeJustice === 0) {
|
||||
lamp = "ALL JUSTICE CRITICAL";
|
||||
} else if (isAllJustice) {
|
||||
lamp = "ALL JUSTICE";
|
||||
} else if (isFullCombo) {
|
||||
lamp = "FULL COMBO";
|
||||
} else if (isClear) {
|
||||
lamp = "CLEAR";
|
||||
}
|
||||
|
||||
const tachiScore: BatchManualScore = {
|
||||
score,
|
||||
lamp,
|
||||
identifier: musicId.toString(),
|
||||
matchType: "inGameID",
|
||||
difficulty: TACHI_DIFFICULTIES[level],
|
||||
};
|
||||
|
||||
if (userPlayDate !== null) {
|
||||
tachiScore.timeAchieved = fromZonedTime(
|
||||
parse(
|
||||
userPlayDate,
|
||||
"yyyy-MM-dd HH:mm:ss",
|
||||
toZonedTime(new Date(), "Asia/Tokyo"),
|
||||
),
|
||||
"Asia/Tokyo",
|
||||
).valueOf();
|
||||
}
|
||||
|
||||
if (
|
||||
judgeCritical !== null &&
|
||||
judgeJustice !== null &&
|
||||
judgeAttack !== null &&
|
||||
judgeGuilty !== null
|
||||
) {
|
||||
tachiScore.judgements = {
|
||||
jcrit: (judgeHeaven ?? 0) + judgeCritical,
|
||||
justice: judgeJustice,
|
||||
attack: judgeAttack,
|
||||
miss: judgeGuilty,
|
||||
};
|
||||
}
|
||||
|
||||
if (maxCombo !== null) {
|
||||
tachiScore.optional = {
|
||||
maxCombo,
|
||||
};
|
||||
}
|
||||
|
||||
tachiExport.scores.push(tachiScore);
|
||||
}
|
||||
|
||||
return tachiExport;
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
|
||||
// Server action imported from server-side code
|
||||
import { getTachiExport } from "./action";
|
||||
|
||||
const TachiExport = () => {
|
||||
const { toast } = useToast();
|
||||
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
const result = await getTachiExport();
|
||||
|
||||
if (result) {
|
||||
const exportedFile = new Blob([JSON.stringify(result, null, 2)], {
|
||||
type: "application/json",
|
||||
});
|
||||
const url = URL.createObjectURL(exportedFile);
|
||||
const kamafile = document.createElement("a");
|
||||
kamafile.href = url;
|
||||
kamafile.download = "tachi_export.json";
|
||||
document.body.appendChild(kamafile);
|
||||
kamafile.click();
|
||||
document.body.removeChild(kamafile);
|
||||
|
||||
toast({
|
||||
title: "Success",
|
||||
description: "Data exported successfully!",
|
||||
});
|
||||
} else {
|
||||
toast({
|
||||
title: "Error",
|
||||
description: "Failed to export data",
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
toast({
|
||||
title: "Error",
|
||||
description: error.message || "An error occurred while exporting data",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card x-chunk="aimecard">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-2xl">Export to kamaitachi</CardTitle>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent>
|
||||
<Button onClick={handleExport} className="w-full">
|
||||
Export
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export { TachiExport };
|
@ -0,0 +1,10 @@
|
||||
import { TachiExport } from "./kamaitachiexport";
|
||||
|
||||
const SecuritySettingsPage = async () => {
|
||||
return (
|
||||
<div>
|
||||
<TachiExport />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default SecuritySettingsPage;
|
@ -2,7 +2,7 @@ import SecuritySettings from "./security";
|
||||
|
||||
const SecuritySettingsPage = async () => {
|
||||
return (
|
||||
<div className="flex min-h-screen w-full flex-col">
|
||||
<div>
|
||||
<SecuritySettings />
|
||||
</div>
|
||||
);
|
||||
|
@ -29,7 +29,7 @@ import {
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { getGameList, updatePlayerGameVersionChuni } from "./actions";
|
||||
import { getGameList, updatePlayerGameVersionChuni } from "./action";
|
||||
|
||||
type ChunithmGameVersionSelectionProps = {
|
||||
chunithmGameVersionNumber: {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { PlayerChangableChunithmGameVersionSelection } from "./gameSelection";
|
||||
import { getGameList } from "./actions";
|
||||
import { getGameList } from "./action";
|
||||
import { Card, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
|
||||
const getAllGamesChunithm = async () => {
|
||||
|
@ -6,6 +6,8 @@ import { usePathname } from "next/navigation";
|
||||
const NAV_ITEMS = [
|
||||
{ href: "/settings/home", label: "General" },
|
||||
{ href: "/settings/security", label: "Security" },
|
||||
{ href: "/settings/kamaitachi", label: "Kamaitachi Export" },
|
||||
|
||||
{ href: "/settings/versions", label: "Edit Game Version" },
|
||||
];
|
||||
|
||||
|
@ -58,6 +58,7 @@
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.0.0",
|
||||
"date-fns": "^3.6.0",
|
||||
"date-fns-tz": "^3.1.3",
|
||||
"embla-carousel-react": "^8.1.5",
|
||||
"encoding-japanese": "^2.2.0",
|
||||
"geist": "^1.3.0",
|
||||
|
Loading…
Reference in New Issue
Block a user