diff --git a/src/components/Tooltip.svelte b/src/components/Tooltip.svelte index 606e5810..82ffe513 100644 --- a/src/components/Tooltip.svelte +++ b/src/components/Tooltip.svelte @@ -28,6 +28,7 @@ diff --git a/src/data/banners.js b/src/data/banners.js index 70e22041..2185c17d 100644 --- a/src/data/banners.js +++ b/src/data/banners.js @@ -314,6 +314,17 @@ export const banners = { // featured: ['zhongli', 'ganyu'], // featuredRare: ['xingqiu', 'beidou', 'yanfei'], // }, + { + name: 'Everbloom Violet', + image: 1, + shortName: 'Yae', + start: '2022-02-16 06:00:00', + end: '2022-03-08 17:59:59', + color: '#ffd1f9', + featured: ['yae_miko'], + featuredRare: ['thoma', 'diona', 'fischl'], + timezoneDependent: true, + }, ], weapons: [ { @@ -581,5 +592,16 @@ export const banners = { featured: ['amos_bow', 'vortex_vanquisher'], featuredRare: ['lithic_blade', 'favonius_sword', 'dragons_bane', 'favonius_codex', 'sacrificial_bow'], }, + { + name: 'Epitome Invocation', + image: 25, + start: '2022-02-16 06:00:00', + end: '2022-03-08 17:59:59', + shortName: 'Verity', + color: '#b042f5', + featured: ['kaguras_verity', 'primordial_jade_cutter'], + featuredRare: ['wavebreakers_fin', 'sacrificial_sword', 'rainslasher', 'eye_of_perception', 'the_stringless'], + timezoneDependent: true, + }, ], }; diff --git a/src/locales/en.json b/src/locales/en.json index d32404b7..9f3f2b19 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -448,6 +448,10 @@ "won": "Won 50:50", "lost": "Lost 50:50", "guaranteed": "Guaranteed" + }, + "backupReminder": { + "title": "All data are saved on your browser!", + "desc": "So if by any chance the browser cache got deleted, your wish history will be gone! You can enable Google Drive sync on setting to backup your data, or download the data manually there." } }, "calculator": { diff --git a/src/routes/wish/[id].svelte b/src/routes/wish/[id].svelte index 9c22cbd2..449095eb 100644 --- a/src/routes/wish/[id].svelte +++ b/src/routes/wish/[id].svelte @@ -47,6 +47,7 @@ let errorProcessingPull = null; const bannerType = bannerTypes[id]; + const withRateIcon = bannerType === 'characters' || bannerType === 'weapons'; let bannerChart; let pieChart; @@ -208,16 +209,20 @@ }; if (item.rarity === 5) { - newPull.guaranteed = rateUp; - rateUp = !currentBanner.featured.includes(newPull.id); - newPull.loseRateOff = rateUp; + if (withRateIcon) { + newPull.guaranteed = rateUp; + rateUp = !currentBanner.featured.includes(newPull.id); + newPull.loseRateOff = rateUp; + } selectedBanners[currentBannerIndex].legendary.push(newPull); allLegendary.push(newPull); } else if (item.rarity === 4) { - newPull.guaranteed = rateUpRare; - rateUpRare = !currentBanner.featuredRare.includes(newPull.id); - newPull.loseRateOff = rateUpRare; + if (withRateIcon) { + newPull.guaranteed = rateUpRare; + rateUpRare = !currentBanner.featuredRare.includes(newPull.id); + newPull.loseRateOff = rateUpRare; + } allRare.push(newPull); if (pull.type === 'character') { @@ -612,7 +617,7 @@ {/if} - {:else if pull.rarity > 3} + {:else if pull.guaranteed === true && withRateIcon} diff --git a/src/routes/wish/_backupReminder.svelte b/src/routes/wish/_backupReminder.svelte new file mode 100644 index 00000000..be8cc9ed --- /dev/null +++ b/src/routes/wish/_backupReminder.svelte @@ -0,0 +1,12 @@ + + +

{$t('wish.backupReminder.title')}

+

{$t('wish.backupReminder.desc')}

+
+ +
diff --git a/src/routes/wish/_counter.svelte b/src/routes/wish/_counter.svelte index d769c47e..7187b732 100644 --- a/src/routes/wish/_counter.svelte +++ b/src/routes/wish/_counter.svelte @@ -3,7 +3,7 @@ import { onMount, getContext } from 'svelte'; import { slide } from 'svelte/transition'; - import { mdiPencil, mdiStar, mdiChevronDown, mdiTableOfContents } from '@mdi/js'; + import { mdiPencil, mdiStar, mdiChevronDown, mdiTableOfContents, mdiArrowUpCircle } from '@mdi/js'; import debounce from 'lodash/debounce'; const { open: openModal, close: closeModal } = getContext('simple-modal'); @@ -18,6 +18,7 @@ import dayjs from 'dayjs'; import { weaponList } from '../../data/weaponList'; import { getAccountPrefix } from '../../stores/account'; + import Tooltip from '../../components/Tooltip.svelte'; let numberFormat = Intl.NumberFormat(); @@ -41,6 +42,11 @@ let showRarity = [true, true, false]; let sortedPull = []; + let guaranteed = { + legendary: false, + rare: false, + }; + $: path = `wish-counter-${id}`; $: if ($fromRemote) { readLocalData(); @@ -199,6 +205,11 @@ legendary = counterData.legendary; rare = counterData.rare; pulls = counterData.pulls || []; + + if (counterData.guaranteed) { + guaranteed.legendary = counterData.guaranteed.legendary; + guaranteed.rare = counterData.guaranteed.rare; + } } } @@ -278,7 +289,6 @@ rare = 0; saveData(); } -
@@ -310,7 +320,9 @@ {#if isEdit} - {:else}{total}{/if} + {:else} + {total} + {/if}
{/if} - 5 - - {$t('wish.pity')} + 5★ {$t('wish.pity')}
{$t('wish.guarantee', { values: { pity: legendaryPity } })}
{#if isEdit} - {:else}{legendary}{/if} + {:else} + {#if guaranteed.legendary} + + + {$t('wish.detail.guaranteed')} + + {/if} + {legendary} + {/if}
{/if} - 4 - - {$t('wish.pity')} + 4★ {$t('wish.pity')}
{$t('wish.guarantee', { values: { pity: 10 } })}
{#if isEdit} - {:else}{rare}{/if} + {:else} + {#if guaranteed.rare} + + + {$t('wish.detail.guaranteed')} + + {/if} + {rare} + {/if}
{#if isEdit} @@ -491,4 +515,31 @@ } } + .rate-tooltip { + @apply relative; + + .tooltip-content { + top: 30px; + right: 0px; + width: 250px; + @apply absolute; + @apply hidden; + @apply text-background; + @apply rounded-xl; + @apply p-2; + @apply text-sm z-20; + @apply border-background border-2; + + &.legendary { + @apply bg-legendary-from; + } + &.rare { + @apply bg-rare-from; + } + } + + &:hover .tooltip-content { + @apply block; + } + } diff --git a/src/routes/wish/import.svelte b/src/routes/wish/import.svelte index e3287bd6..c6349756 100644 --- a/src/routes/wish/import.svelte +++ b/src/routes/wish/import.svelte @@ -21,8 +21,9 @@ import Input from '../../components/Input.svelte'; import Select from '../../components/Select.svelte'; import Icon from '../../components/Icon.svelte'; - import { server } from '../../stores/server'; + import { getTimeOffset, server } from '../../stores/server'; import ImportFaqModal from './_importFaq.svelte'; + import BackupReminderModal from './_backupReminder.svelte'; import Textarea from '../../components/Textarea.svelte'; import { getAccountPrefix } from '../../stores/account'; import { getLocalSaveJson, readSave, updateSave } from '../../stores/saveManager'; @@ -32,6 +33,8 @@ import { submitWishTally } from '../../functions/wishTally'; import Ad from '../../components/Ad.svelte'; import Checkbox from '../../components/Checkbox.svelte'; + import { driveSignedIn } from '../../stores/dataSync'; + import { banners } from '../../data/banners'; const numberFormat = Intl.NumberFormat(); let fetchController; @@ -107,6 +110,8 @@ let error = ''; + let bannerList = []; + let wishes = {}; async function downloadBackup() { @@ -370,6 +375,8 @@ manualInput: false, }); + if ($driveSignedIn === false) openBackupReminder(); + pushToast($t('wish.import.success')); goto('/wish'); } @@ -394,6 +401,9 @@ const combined = [...localWishes, ...importedWishes]; + let latestLegendary = null; + let latestRare = null; + let rare = 0; let legendary = 0; for (let i = 0; i < combined.length; i++) { @@ -408,10 +418,12 @@ } if (rarity === 5) { + latestLegendary = combined[i]; combined[i].pity = legendary; legendary = 0; // rare = 0; } else if (rarity === 4) { + latestRare = combined[i]; combined[i].pity = rare; rare = 0; } else { @@ -419,11 +431,37 @@ } } + let rateUpLegendary = false; + let rateUpRare = false; + if (type.id === 'character-event' || type.id === 'weapon-event') { + processBannerList(type.id); + + if (latestLegendary !== null) { + const itemBanner = getBannerByTime(latestLegendary.time); + console.log(latestLegendary.time, itemBanner); + if (itemBanner && itemBanner.featured) { + rateUpLegendary = !itemBanner.featured.includes(latestLegendary.id); + } + } + + if (latestRare !== null) { + const itemBanner = getBannerByTime(latestRare.time); + console.log(latestRare.time, itemBanner); + if (itemBanner && itemBanner.featured) { + rateUpRare = !itemBanner.featuredRare.includes(latestRare.id); + } + } + } + const data = { total: combined.length, legendary, rare, pulls: combined, + guaranteed: { + legendary: rateUpLegendary, + rare: rateUpRare, + }, }; await updateSave(`${prefix}${path}`, data); @@ -600,6 +638,19 @@ ); } + function openBackupReminder() { + openModal( + BackupReminderModal, + { + close: closeModal, + }, + { + closeButton: false, + styleWindow: { background: '#25294A', width: '500px' }, + }, + ); + } + function detectPlatform() { const userAgent = navigator.userAgent || navigator.vendor; if (/android/i.test(userAgent)) { @@ -628,6 +679,35 @@ }, 2000); } + function processBannerList(bannerType) { + const type = bannerType === 'character-event' ? 'characters' : 'weapons'; + + bannerList = banners[type].map((e) => { + // banner data based on Asia time + const diff = e.timezoneDependent === true ? 8 - getTimeOffset() : 0; + + const id = `${e.name} ${e.image}`; + const start = dayjs(e.start, 'YYYY-MM-DD HH:mm:ss').subtract(diff, 'hour'); + const end = dayjs(e.end, 'YYYY-MM-DD HH:mm:ss'); + + return { + ...e, + id, + start: start.unix(), + end: end.unix(), + }; + }); + } + + function getBannerByTime(time) { + const unixTime = dayjs(time).unix(); + for (let i = bannerList.length - 1; i >= 0; i--) { + if (unixTime >= bannerList[i].start && unixTime < bannerList[i].end) { + return bannerList[i]; + } + } + } + function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }