Add luckiness rate

pull/1/head
Made Baruna 2022-06-12 22:09:43 +07:00
parent 67c4eb95c8
commit 7a9ebd7a77
6 changed files with 204 additions and 37 deletions

View File

@ -455,11 +455,22 @@
"desc": "So if by any chance the browser cache got deleted, your wish history will be gone! You can enable Google Drive sync in the Settings menu to backup your data, or download the data manually there."
},
"rank": {
"title": "Your Global Rank",
"level": "Your Total Pulls Rank",
"based": "Based on Global Wish Stats",
"current": "Current {banner} median is {median} pulls",
"more": "You have more pull than {percentage}% of paimon.moe users",
"less": "You have less pull than {percentage}% of paimon.moe users"
"less": "You have less pull than {percentage}% of paimon.moe users",
"currentLuck": "Current {banner} median is {median}%",
"totalPull": "Total Pull",
"luck5": "Luckiness 5★",
"luck4": "Luckiness 4★",
"medianTotal": "Global Median {median} pulls",
"medianLuck": "Global Median {median}%",
"moreTotal": "More pulls than {percentage}% of paimon.moe users",
"lessTotal": "Less pulls than {percentage}% of paimon.moe users",
"moreLuck": "Luckier than {percentage}% of paimon.moe users",
"lessLuck": "Less lucky than {percentage}% of paimon.moe users"
}
},
"calculator": {

View File

@ -455,11 +455,23 @@
"desc": "Jadi jika terjadi sesuatu yang menyebabkan cache browser mu terhapus, data riwayat wish mu akan hilang! Kamu bisa menyalakan Google Drive sync di setting untuk membackup datamu, atau kamu bisa mendownload secara manual datanya di sana."
},
"rank": {
"title": "Ranking Global Mu",
"level": "Ranking Total Wish Mu",
"based": "Dari Perhitungan Pity Global",
"current": "Median {banner} saat ini {median} pull",
"more": "Kamu wish lebih banyak dari {percentage}% pengguna paimon.moe",
"less": "Kamu wish lebih sedikit dari {percentage}% pengguna paimon.moe"
"less": "Kamu wish lebih sedikit dari {percentage}% pengguna paimon.moe",
"luck": "Ranking Keberuntunganmu",
"currentLuck": "Median {banner} saat ini {median}%",
"totalPull": "Total Wish",
"luck5": "Keberuntungan 5★",
"luck4": "Keberuntungan 4★",
"medianTotal": "Median Global {median} pull",
"medianLuck": "Median Global {median}%",
"moreTotal": "Lebih banyak dari {percentage}% pengguna paimon.moe",
"lessTotal": "Lebih sedikit dari {percentage}% pengguna paimon.moe",
"moreLuck": "Lebih beruntung dari {percentage}% pengguna paimon.moe",
"lessLuck": "Lebih sial dari {percentage}% pengguna paimon.moe"
}
},
"calculator": {

View File

@ -1,14 +1,12 @@
<script>
import { mdiLoading } from '@mdi/js';
import { t } from 'svelte-i18n';
import Icon from '../../components/Icon.svelte';
export let wishTotal = {
'character-event': 0,
'weapon-event': 0,
standard: 0,
};
export let wishPercentage;
let current = 'character-event';
let wishCount = 0;
@ -16,10 +14,23 @@
let data = [];
let percentage = 0;
let median = '...';
let loading = true;
let percentageLuck = {
legendary: 0,
rare: 0,
};
let medianLuck = {
legendary: '...',
rare: '...',
};
let loading = {
total: true,
legendary: true,
rare: true,
};
export async function getData() {
loading = true;
loading.total = true;
percentage = 0;
median = '...';
wishCount = wishTotal[current];
@ -62,19 +73,160 @@
percentage = 100 - (totalLower / total) * 100;
console.log(totalLower, percentage, value);
loading = false;
loading.total = false;
}
async function getDataLuck(rarity, percentages) {
loading[rarity] = true;
percentageLuck[rarity] = 0;
medianLuck[rarity] = '...';
try {
const url = new URL(`${__paimon.env.API_HOST}/wish/summary/luck`);
const query = new URLSearchParams({ banner: current, rarity });
url.search = query.toString();
const res = await fetch(url, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
data = await res.json();
total = 0;
const sorted = [];
for (const item of data) {
total += item[1];
sorted.push(...new Array(item[1]).fill(item[0]));
}
medianLuck[rarity] = (sorted[Math.round(sorted.length / 2)] * 100).toFixed(2);
getPercentileLuck(percentages[current][rarity], rarity);
} catch (err) {
console.error(err);
}
}
function getPercentileLuck(value, rarity) {
let totalLower = 0;
for (const item of data) {
const qty = item[0];
const amount = item[1];
totalLower += amount;
if (qty >= value) break;
}
percentageLuck[rarity] = 100 - (totalLower / total) * 100;
console.log(totalLower, percentage, value);
loading[rarity] = false;
}
export function getDataLuckAll(percentages) {
const sources = percentages === undefined ? wishPercentage : percentages;
getDataLuck('legendary', sources);
getDataLuck('rare', sources);
}
function change(type) {
current = type;
getData();
getDataLuckAll();
}
$: fixedPoint = percentage < 0.1 ? 2 : percentage < 2 ? 1 : 0;
$: fixedPointLegendary = percentageLuck.legendary < 0.1 ? 2 : percentageLuck.legendary < 2 ? 1 : 0;
$: fixedPointRare = percentageLuck.rare < 0.1 ? 2 : percentageLuck.rare < 2 ? 1 : 0;
</script>
<div class="flex flex-col items-center bg-item rounded-xl p-4 w-full mt-4">
<div class="flex -m-1 pb-5">
<div class="flex flex-col items-center pb-4">
<p class="text-lg text-white leading-none font-semibold">{$t('wish.rank.title')}</p>
<p class="text-sm text-gray-400 leading-none">{$t('wish.rank.based')}</p>
</div>
<div class="bg-background flex-row items-center justify-center mb-2 p-4 rounded-xl flex relative group w-full">
<div
class="group-hover:flex hidden absolute left-0 items-center z-10"
style="max-width: 80%; bottom: 12px; left: 12px;"
>
<div class="bg-gray-200 text-gray-900 px-4 py-1 rounded-xl text-sm md:text-base">
{$t('wish.rank.medianTotal', { values: { median } })}
</div>
</div>
<div class="text-gray-200 flex-1">
<p class="text-gray-200">{$t('wish.rank.totalPull')}</p>
<p class="text-sm text-gray-600 leading-none">
{#if percentage < 50}
{$t('wish.rank.moreTotal', { values: { percentage: (100 - percentage).toFixed(fixedPoint) } })}
{:else}
{$t('wish.rank.lessTotal', { values: { percentage: percentage.toFixed(0) } })}
{/if}
</p>
</div>
<div class="pl-1">
<span class="text-sm font-black text-white opacity-75 block leading-none">TOP</span>
<span class="text-white font-black text-3xl leading-none block" style="line-height: 0.75;">
{loading.total ? '...' : percentage.toFixed(fixedPoint)}%
</span>
</div>
</div>
<div class="bg-background flex-row items-center justify-center mb-2 p-4 rounded-xl flex relative group w-full">
<div
class="group-hover:flex hidden absolute left-0 items-center z-10"
style="max-width: 80%; bottom: 12px; left: 12px;"
>
<div class="bg-gray-200 text-gray-900 px-4 py-1 rounded-xl text-sm md:text-base">
{$t('wish.rank.medianLuck', { values: { median: medianLuck.legendary } })}
</div>
</div>
<div class="text-gray-200 flex-1">
<p class="text-gray-200">{$t('wish.rank.luck5')}</p>
<p class="text-sm text-gray-600 leading-none">
{#if percentageLuck.legendary < 50}
{$t('wish.rank.moreLuck', {
values: { percentage: (100 - percentageLuck.legendary).toFixed(fixedPointLegendary) },
})}
{:else}
{$t('wish.rank.lessLuck', { values: { percentage: percentageLuck.legendary.toFixed(0) } })}
{/if}
</p>
</div>
<div class="pl-1">
<span class="text-sm font-black text-legendary-from opacity-75 block leading-none">TOP</span>
<span class="text-legendary-from font-black text-3xl leading-none block" style="line-height: 0.75;">
{loading.legendary ? '...' : percentageLuck.legendary.toFixed(fixedPointLegendary)}%
</span>
</div>
</div>
<div class="bg-background flex-row items-center justify-center p-4 rounded-xl flex relative group w-full">
<div
class="group-hover:flex hidden absolute left-0 items-center z-10"
style="max-width: 80%; bottom: 12px; left: 12px;"
>
<div class="bg-gray-200 text-gray-900 px-4 py-1 rounded-xl text-sm md:text-base">
{$t('wish.rank.medianLuck', { values: { median: medianLuck.rare } })}
</div>
</div>
<div class="text-gray-200 flex-1">
<p class="text-gray-200">{$t('wish.rank.luck4')}</p>
<p class="text-sm text-gray-600 leading-none">
{#if percentageLuck.rare < 50}
{$t('wish.rank.moreLuck', { values: { percentage: (100 - percentageLuck.rare).toFixed(fixedPointRare) } })}
{:else}
{$t('wish.rank.lessLuck', { values: { percentage: percentageLuck.rare.toFixed(0) } })}
{/if}
</p>
</div>
<div class="pl-1">
<span class="text-sm font-black text-rare-from opacity-75 block leading-none">TOP</span>
<span class="text-rare-from font-black text-3xl leading-none block" style="line-height: 0.75;">
{loading.rare ? '...' : percentageLuck.rare.toFixed(fixedPointRare)}%
</span>
</div>
</div>
<div class="flex -m-1 pt-4">
<button class="pill m-1 {current === 'character-event' ? 'active' : ''}" on:click={() => change('character-event')}>
{$t('wish.detail.character')}
</button>
@ -85,26 +237,6 @@
{$t('wish.types.standard')}
</button>
</div>
<div class="flex flex-row items-end">
<div class="flex flex-col text-white font-black text-4xl pr-4">
<span class="text-sm text-left text-gray-400" style="line-height: 0.7;">TOP</span>
<span class="text-right leading-none">{loading ? '...' : percentage.toFixed(fixedPoint)}%</span>
</div>
<div class="flex flex-col text-white" style="margin-bottom: 2px;">
<p>{$t('wish.rank.level')}</p>
<p class="text-sm text-gray-400 leading-none">{$t('wish.rank.based')}</p>
</div>
</div>
<p class="text-sm text-gray-400 mt-2 text-center">
{$t('wish.rank.current', { values: { median, banner: $t(`wish.types.${current}`) } })}
</p>
<p class="text-sm text-gray-400 text-center">
{#if percentage < 50}
{$t('wish.rank.more', { values: { percentage: (100 - percentage).toFixed(fixedPoint) } })}
{:else}
{$t('wish.rank.less', { values: { percentage: percentage.toFixed(0) } })}
{/if}
</p>
</div>
<style>

View File

@ -1,7 +1,7 @@
<script>
import { t } from 'svelte-i18n';
import { onMount } from 'svelte';
import { createEventDispatcher, onMount } from 'svelte';
import dayjs from 'dayjs';
import debounce from 'lodash/debounce';
@ -15,6 +15,8 @@
import Icon from '../../components/Icon.svelte';
import { mdiEarth } from '@mdi/js';
const dispatch = createEventDispatcher();
let numberFormat = Intl.NumberFormat();
export let monthlyData = {};
@ -24,6 +26,7 @@
let loading = true;
let wishCount = 0;
const avg = {};
const percentages = {};
const readDebounced = debounce(() => {
readLocalData();
@ -79,8 +82,6 @@
},
};
export async function readLocalData() {
let totalWish = 0;
console.log('wish summary read local');
@ -209,6 +210,11 @@
pulls: legendaryPulls,
},
};
percentages[type.id] = {
legendary: avg[type.id].legendary.percentage,
rare: avg[type.id].rare.percentage,
};
}
}
@ -221,10 +227,10 @@
await updateSave(`${prefix}collectables-updated`, false);
}
// console.log(avg);
dispatch('summaryread', percentages);
loading = false;
}
</script>
{#if !loading}

View File

@ -8,7 +8,7 @@
export let type;
let numberFormat = Intl.NumberFormat('en', {
maximumFractionDigits: 1,
maximumFractionDigits: 2,
minimumFractionDigits: 0,
});

View File

@ -32,6 +32,7 @@
'weapon-event': 0,
standard: 0,
};
let wishPercentage;
const path = 'wish-counter-setting';
@ -117,6 +118,11 @@
}
}
function setRankWishPercentage(event) {
wishPercentage = event.detail;
rank.getDataLuckAll(event.detail);
}
function closeImportModal() {
closeModal();
counter1.readLocalData();
@ -220,12 +226,12 @@
name={$t('wish.types.beginners')}
/>
<MonthlyGraph bind:data={monthlyData} />
<Rank bind:this={rank} {wishTotal} />
<Rank bind:this={rank} {wishTotal} {wishPercentage} />
<div class="mt-4 flex justify-center">
<Ad type="mobile" variant="mpu" id="1" />
</div>
</div>
<Summary bind:monthlyData />
<Summary bind:monthlyData on:summaryread={(val) => setRankWishPercentage(val)} />
</div>
<div class="hidden md:flex flex-1">
<Ad class="ml-4" type="desktop" variant="mpu" id="1" />