mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-10-31 03:08:29 +08:00
impr(result): add new crown states (error, warning, ineligible, normal)
This commit is contained in:
parent
aa2466a0d1
commit
bc3ecb25eb
6 changed files with 235 additions and 66 deletions
|
|
@ -181,8 +181,16 @@
|
|||
<div class="group wpm">
|
||||
<div class="top">
|
||||
<div class="text">wpm</div>
|
||||
<div class="crown hidden" aria-label="" data-balloon-pos="up">
|
||||
<div
|
||||
class="crown hidden"
|
||||
aria-label=""
|
||||
data-balloon-pos="up"
|
||||
data-balloon-length="medium"
|
||||
>
|
||||
<i class="fas fa-question"></i>
|
||||
<i class="fas fa-crown"></i>
|
||||
<i class="fas fa-slash"></i>
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom" aria-label="" data-balloon-pos="up">-</div>
|
||||
|
|
|
|||
|
|
@ -822,32 +822,76 @@
|
|||
font-size: 2rem;
|
||||
line-height: 1.5rem;
|
||||
display: flex;
|
||||
// margin-top: -0.5rem;
|
||||
|
||||
// .crownWrapper {
|
||||
// width: 1.7rem;
|
||||
// overflow: hidden;
|
||||
// height: 1.7rem;
|
||||
// margin-left: 0.5rem;
|
||||
// // margin-top: 0.98rem;
|
||||
// margin-top: -0.5rem;
|
||||
|
||||
.crown {
|
||||
height: 1.7rem;
|
||||
width: 1.7rem;
|
||||
--main: var(--main-color);
|
||||
--alt: var(--bg-color);
|
||||
|
||||
margin-left: 0.5rem;
|
||||
margin-top: -0.2rem;
|
||||
font-size: 0.7rem;
|
||||
line-height: 1.7rem;
|
||||
background: var(--main-color);
|
||||
color: var(--bg-color);
|
||||
border-radius: 0.6rem;
|
||||
text-align: center;
|
||||
align-self: center;
|
||||
background: var(--main);
|
||||
color: var(--alt);
|
||||
width: 1.7rem;
|
||||
height: 1.7rem;
|
||||
border-radius: var(--roundness);
|
||||
display: grid;
|
||||
grid-template-areas: "icon";
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
|
||||
transition: opacity 0.125s, background 0.125s, color 0.125s,
|
||||
outline 0.125s;
|
||||
|
||||
i {
|
||||
grid-area: icon;
|
||||
}
|
||||
|
||||
.fa-slash {
|
||||
color: var(--main);
|
||||
font-size: 1.2rem;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.fa-question,
|
||||
.fa-exclamation-triangle {
|
||||
color: var(--alt);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&.half {
|
||||
--main: var(--bg-color);
|
||||
--alt: var(--main-color);
|
||||
outline: 0.2em solid var(--main-color);
|
||||
}
|
||||
&.broken {
|
||||
--main: var(--sub-color);
|
||||
--alt: var(--bg-color);
|
||||
.fa-slash {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
&.error {
|
||||
--main: var(--error-color);
|
||||
--alt: var(--bg-color);
|
||||
.fa-crown {
|
||||
opacity: 0;
|
||||
}
|
||||
.fa-question {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
&.warning {
|
||||
--main: var(--sub-color);
|
||||
--alt: var(--bg-color);
|
||||
.fa-crown {
|
||||
opacity: 0;
|
||||
}
|
||||
.fa-exclamation-triangle {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
.bottom {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,36 @@
|
|||
export function hide(): void {
|
||||
visible = false;
|
||||
$("#result .stats .wpm .crown").css("opacity", 0).addClass("hidden");
|
||||
}
|
||||
|
||||
export function show(): void {
|
||||
$("#result .stats .wpm .crown")
|
||||
.removeClass("hidden")
|
||||
.css("opacity", "0")
|
||||
.animate(
|
||||
{
|
||||
opacity: 1,
|
||||
},
|
||||
250,
|
||||
"easeOutCubic"
|
||||
);
|
||||
export type CrownType = "normal" | "broken" | "half" | "error" | "warning";
|
||||
|
||||
let visible = false;
|
||||
let currentType: CrownType = "normal";
|
||||
|
||||
export function getCurrentType(): CrownType {
|
||||
return currentType;
|
||||
}
|
||||
|
||||
export function show(): void {
|
||||
if (visible) return;
|
||||
visible = true;
|
||||
const el = $("#result .stats .wpm .crown");
|
||||
el.removeClass("hidden").css("opacity", "0").animate(
|
||||
{
|
||||
opacity: 1,
|
||||
},
|
||||
250,
|
||||
"easeOutCubic"
|
||||
);
|
||||
}
|
||||
|
||||
export function update(type: CrownType): void {
|
||||
currentType = type;
|
||||
const el = $("#result .stats .wpm .crown");
|
||||
el.removeClass("broken");
|
||||
el.removeClass("half");
|
||||
el.removeClass("error");
|
||||
el.removeClass("warning");
|
||||
el.addClass(type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -363,8 +363,134 @@ function updateKey(): void {
|
|||
);
|
||||
}
|
||||
|
||||
export function showCrown(): void {
|
||||
export function showCrown(type: PbCrown.CrownType): void {
|
||||
PbCrown.show();
|
||||
PbCrown.update(type);
|
||||
}
|
||||
|
||||
export function updateCrownType(type: PbCrown.CrownType): void {
|
||||
PbCrown.update(type);
|
||||
}
|
||||
|
||||
export async function updateCrown(): Promise<void> {
|
||||
if (Config.mode === "quote") {
|
||||
hideCrown();
|
||||
return;
|
||||
}
|
||||
|
||||
let pbDiff = 0;
|
||||
const canGetPb = await resultCanGetPb();
|
||||
|
||||
if (canGetPb.value) {
|
||||
const lpb = await DB.getLocalPB(
|
||||
Config.mode,
|
||||
result.mode2,
|
||||
Config.punctuation,
|
||||
Config.numbers,
|
||||
Config.language,
|
||||
Config.difficulty,
|
||||
Config.lazyMode,
|
||||
Config.funbox
|
||||
);
|
||||
pbDiff = result.wpm - lpb;
|
||||
if (pbDiff <= 0) {
|
||||
hideCrown();
|
||||
} else {
|
||||
//show half crown as the pb is not confirmed by the server
|
||||
showCrown("half");
|
||||
$("#result .stats .wpm .crown").attr(
|
||||
"aria-label",
|
||||
"+" + Format.typingSpeed(pbDiff, { showDecimalPlaces: true })
|
||||
);
|
||||
}
|
||||
} else {
|
||||
const lpb = await DB.getLocalPB(
|
||||
Config.mode,
|
||||
result.mode2,
|
||||
Config.punctuation,
|
||||
Config.numbers,
|
||||
Config.language,
|
||||
Config.difficulty,
|
||||
Config.lazyMode,
|
||||
"none"
|
||||
);
|
||||
pbDiff = result.wpm - lpb;
|
||||
if (pbDiff <= 0) {
|
||||
// hideCrown();
|
||||
showCrown("warning");
|
||||
$("#result .stats .wpm .crown").attr(
|
||||
"aria-label",
|
||||
`This result is not eligible for a new PB (${canGetPb.reason})`
|
||||
);
|
||||
} else {
|
||||
showCrown("broken");
|
||||
$("#result .stats .wpm .crown").attr(
|
||||
"aria-label",
|
||||
`You could've gotten a new PB (+${Format.typingSpeed(pbDiff, {
|
||||
showDecimalPlaces: true,
|
||||
})}), but your config does not allow it (${canGetPb.reason})`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function hideCrown(): void {
|
||||
PbCrown.hide();
|
||||
$("#result .stats .wpm .crown").attr("aria-label", "");
|
||||
}
|
||||
|
||||
export function showErrorCrownIfNeeded(): void {
|
||||
if (PbCrown.getCurrentType() !== "half") return;
|
||||
PbCrown.show();
|
||||
PbCrown.update("error");
|
||||
$("#result .stats .wpm .crown").attr(
|
||||
"aria-label",
|
||||
`Local PB data is out of sync with the server - please refresh (pb mismatch)`
|
||||
);
|
||||
}
|
||||
|
||||
type CanGetPbObject =
|
||||
| {
|
||||
value: true;
|
||||
}
|
||||
| {
|
||||
value: false;
|
||||
reason: string;
|
||||
};
|
||||
|
||||
async function resultCanGetPb(): Promise<CanGetPbObject> {
|
||||
const funboxes = result.funbox?.split("#") ?? [];
|
||||
const funboxObjects = await Promise.all(
|
||||
funboxes.map(async (f) => JSONData.getFunbox(f))
|
||||
);
|
||||
const allFunboxesCanGetPb = funboxObjects.every((f) => f?.canGetPb);
|
||||
|
||||
const funboxesOk =
|
||||
result.funbox === "none" || funboxes.length === 0 || allFunboxesCanGetPb;
|
||||
const notUsingStopOnLetter = Config.stopOnError !== "letter";
|
||||
|
||||
if (funboxesOk && notUsingStopOnLetter) {
|
||||
return {
|
||||
value: true,
|
||||
};
|
||||
} else {
|
||||
if (!funboxesOk) {
|
||||
return {
|
||||
value: false,
|
||||
reason: "funbox",
|
||||
};
|
||||
}
|
||||
if (!notUsingStopOnLetter) {
|
||||
return {
|
||||
value: false,
|
||||
reason: "stop on letter",
|
||||
};
|
||||
}
|
||||
return {
|
||||
value: false,
|
||||
reason: "unknown",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function showConfetti(): void {
|
||||
|
|
@ -399,30 +525,6 @@ export function showConfetti(): void {
|
|||
})();
|
||||
}
|
||||
|
||||
export function hideCrown(): void {
|
||||
PbCrown.hide();
|
||||
$("#result .stats .wpm .crown").attr("aria-label", "");
|
||||
}
|
||||
|
||||
export async function updateCrown(): Promise<void> {
|
||||
let pbDiff = 0;
|
||||
const lpb = await DB.getLocalPB(
|
||||
Config.mode,
|
||||
result.mode2,
|
||||
Config.punctuation,
|
||||
Config.numbers,
|
||||
Config.language,
|
||||
Config.difficulty,
|
||||
Config.lazyMode,
|
||||
Config.funbox
|
||||
);
|
||||
pbDiff = Math.abs(result.wpm - lpb);
|
||||
$("#result .stats .wpm .crown").attr(
|
||||
"aria-label",
|
||||
"+" + Format.typingSpeed(pbDiff, { showDecimalPlaces: true })
|
||||
);
|
||||
}
|
||||
|
||||
async function updateTags(dontSave: boolean): Promise<void> {
|
||||
const activeTags: MonkeyTypes.UserTag[] = [];
|
||||
const userTagsCount = DB.getSnapshot()?.tags?.length ?? 0;
|
||||
|
|
@ -451,14 +553,6 @@ async function updateTags(dontSave: boolean): Promise<void> {
|
|||
);
|
||||
$("#result .stats .tags .editTagsButton").addClass("invisible");
|
||||
|
||||
const funboxes = result.funbox?.split("#") ?? [];
|
||||
|
||||
const funboxObjects = await Promise.all(
|
||||
funboxes.map(async (f) => JSONData.getFunbox(f))
|
||||
);
|
||||
|
||||
const allFunboxesCanGetPb = funboxObjects.every((f) => f?.canGetPb);
|
||||
|
||||
let annotationSide = "start";
|
||||
let labelAdjust = 15;
|
||||
activeTags.forEach(async (tag) => {
|
||||
|
|
@ -479,7 +573,7 @@ async function updateTags(dontSave: boolean): Promise<void> {
|
|||
if (
|
||||
Config.mode !== "quote" &&
|
||||
!dontSave &&
|
||||
(result.funbox === "none" || funboxes.length === 0 || allFunboxesCanGetPb)
|
||||
(await resultCanGetPb()).value
|
||||
) {
|
||||
if (tpb < result.wpm) {
|
||||
//new pb for that tag
|
||||
|
|
@ -763,6 +857,7 @@ export async function update(
|
|||
updateTestType(randomQuote);
|
||||
updateQuoteSource(randomQuote);
|
||||
updateQuoteFavorite(randomQuote);
|
||||
await updateCrown();
|
||||
await updateGraph();
|
||||
await updateGraphPBLine();
|
||||
await updateTags(dontSave);
|
||||
|
|
|
|||
|
|
@ -1195,8 +1195,7 @@ async function saveResult(
|
|||
) {
|
||||
Result.showConfetti();
|
||||
}
|
||||
Result.showCrown();
|
||||
await Result.updateCrown();
|
||||
Result.showCrown("normal");
|
||||
await DB.saveLocalPB(
|
||||
Config.mode,
|
||||
completedEvent.mode2,
|
||||
|
|
@ -1210,6 +1209,8 @@ async function saveResult(
|
|||
completedEvent.rawWpm,
|
||||
completedEvent.consistency
|
||||
);
|
||||
} else {
|
||||
Result.showErrorCrownIfNeeded();
|
||||
}
|
||||
|
||||
// if (response.data.dailyLeaderboardRank) {
|
||||
|
|
|
|||
1
shared-types/types.d.ts
vendored
1
shared-types/types.d.ts
vendored
|
|
@ -237,6 +237,7 @@ declare namespace SharedTypes {
|
|||
charTotal: number;
|
||||
stringified?: string;
|
||||
hash?: string;
|
||||
stopOnLetter: boolean;
|
||||
}
|
||||
|
||||
type CustomTextMode = "repeat" | "random" | "shuffle";
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue