mirror of
https://github.com/MadeBaruna/paimon-moe.git
synced 2025-03-14 19:48:59 +01:00
Add wish tally submit
This commit is contained in:
parent
6ffdcbba0c
commit
da425bf0ac
9 changed files with 182 additions and 22 deletions
|
@ -1,3 +1,3 @@
|
|||
GOOGLE_DRIVE_CLIENT_ID=
|
||||
GOOGLE_DRIVE_API_KEY=
|
||||
CORS_HOST=
|
||||
API_HOST=http://localhost:3001
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
id: name.id,
|
||||
time: dayjs(time).unix(),
|
||||
pity,
|
||||
manualInput: true,
|
||||
};
|
||||
|
||||
addPullDetail(pull);
|
||||
|
@ -60,6 +61,7 @@
|
|||
id: name.id,
|
||||
time: dayjs(time).unix(),
|
||||
pity,
|
||||
manualInput: true,
|
||||
};
|
||||
|
||||
editPullDetail(pull);
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
<script>
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
import { mdiLoading, mdiPencil, mdiStar } from '@mdi/js';
|
||||
import { mdiCheckCircleOutline, mdiLoading, mdiPencil, mdiStar } from '@mdi/js';
|
||||
import Icon from './Icon.svelte';
|
||||
import Button from './Button.svelte';
|
||||
import Checkbox from '../components/Checkbox.svelte';
|
||||
|
||||
import { exportToExcel } from '../functions/export';
|
||||
import { submitWishTally } from '../functions/wishTally';
|
||||
import { pushToast } from '../stores/toast';
|
||||
|
||||
export let setManualInput;
|
||||
export let settings;
|
||||
|
||||
let loadingExport = false;
|
||||
let wishTallySubmitted = false;
|
||||
|
||||
let enableManual = settings.manualInput;
|
||||
|
||||
|
@ -20,6 +22,12 @@
|
|||
setManualInput(enableManual);
|
||||
}
|
||||
|
||||
function submitWish() {
|
||||
submitWishTally();
|
||||
pushToast($t('wish.help.wishTallyThankyou'));
|
||||
wishTallySubmitted = true;
|
||||
}
|
||||
|
||||
async function exportFile() {
|
||||
loadingExport = true;
|
||||
await exportToExcel();
|
||||
|
@ -43,6 +51,21 @@
|
|||
</Button>
|
||||
<!-- <Button disabled={loadingExport}>{$t('wish.help.import')}</Button> -->
|
||||
</div>
|
||||
<h1 class="font-display text-white text-xl mt-8 mb-2">{$t('wish.help.wishTallyTitle')}</h1>
|
||||
<div class="text-white p-2 bg-background rounded-xl">
|
||||
<p class="mb-1">{$t('wish.help.wishTally')}</p>
|
||||
<p class="mb-1">
|
||||
{$t('wish.help.wishTallyCollected.0')} 5<Icon size={0.8} path={mdiStar} className="mb-1" />
|
||||
{$t('wish.help.wishTallyCollected.1')} 4<Icon size={0.8} path={mdiStar} className="mb-1" />
|
||||
{$t('wish.help.wishTallyCollected.2')}
|
||||
</p>
|
||||
<Button className="mr-2" disabled={wishTallySubmitted} on:click={submitWish}>
|
||||
{#if wishTallySubmitted}
|
||||
<Icon path={mdiCheckCircleOutline} size={0.8} />
|
||||
{/if}
|
||||
{$t('wish.help.wishTallySubmit')}
|
||||
</Button>
|
||||
</div>
|
||||
<h1 class="font-display text-white text-xl mt-8 mb-2">{$t('wish.help.manualTitle')}</h1>
|
||||
<div class="text-white p-2 bg-background rounded-xl">
|
||||
<div class="py-2 pl-4">
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<script>
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
import { mdiClose, mdiDownload, mdiHelpCircle, mdiInformation, mdiLoading } from '@mdi/js';
|
||||
import { mdiChevronDown, mdiClose, mdiDownload, mdiHelpCircle, mdiInformation, mdiLoading, mdiStar } from '@mdi/js';
|
||||
import { onMount } from 'svelte';
|
||||
import { slide } from 'svelte/transition';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
import { pushToast } from '../stores/toast';
|
||||
|
@ -15,6 +16,7 @@
|
|||
import { characters } from '../data/characters';
|
||||
import { readSave, updateSave } from '../stores/saveManager';
|
||||
import { getAccountPrefix } from '../stores/account';
|
||||
import { submitWishTally } from '../functions/wishTally';
|
||||
|
||||
export let processFirstTimePopup;
|
||||
export let closeModal;
|
||||
|
@ -30,6 +32,9 @@
|
|||
let generatedTextInput = '';
|
||||
let genshinLink = '';
|
||||
|
||||
let wishTallyInfoExpanded = false;
|
||||
let wishTallyChecked = true;
|
||||
|
||||
let types = {
|
||||
100: {
|
||||
name: "Beginners' Wish",
|
||||
|
@ -166,7 +171,7 @@
|
|||
|
||||
try {
|
||||
const res = await fetchRetry(
|
||||
__paimon.env.CORS_HOST,
|
||||
`${__paimon.env.API_HOST}/corsproxy`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
|
@ -297,6 +302,10 @@
|
|||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
function toggleWishTallyInfo() {
|
||||
wishTallyInfoExpanded = !wishTallyInfoExpanded;
|
||||
}
|
||||
|
||||
function toggleFaqs(show) {
|
||||
showFaq = show;
|
||||
}
|
||||
|
@ -378,6 +387,11 @@
|
|||
calculatingPity = false;
|
||||
|
||||
pushToast($t('wish.import.success'));
|
||||
|
||||
if (wishTallyChecked) {
|
||||
submitWishTally();
|
||||
}
|
||||
|
||||
closeModal();
|
||||
}
|
||||
|
||||
|
@ -458,7 +472,7 @@
|
|||
{#each Object.entries(types) as [code, type]}
|
||||
<tr>
|
||||
<td class="border-b border-gray-700 py-1">
|
||||
<span class="text-white mr-2 whitespace-no-wrap">{type.name} Banner</span>
|
||||
<span class="text-white mr-2">{type.name} Banner</span>
|
||||
</td>
|
||||
<td class="border-b border-gray-700 py-1">
|
||||
{#if wishes[code] !== undefined}
|
||||
|
@ -473,6 +487,29 @@
|
|||
</tr>
|
||||
{/each}
|
||||
</table>
|
||||
<div class="mt-4 mb-2 rounded-xl px-2 py-2 md:px-4 md:py-2 bg-black bg-opacity-25 text-gray-400">
|
||||
<div class="pl-1 flex flex-col md:flex-row items-center">
|
||||
<Checkbox bind:checked={wishTallyChecked}>
|
||||
<p class="ml-1">{$t('wish.import.wishTallyCheck')}</p>
|
||||
</Checkbox>
|
||||
<div
|
||||
class="w-full py-1 md:py-0 md:w-12 md:px-3 flex items-center justify-center cursor-pointer"
|
||||
on:click={toggleWishTallyInfo}
|
||||
>
|
||||
<Icon path={mdiChevronDown} />
|
||||
</div>
|
||||
</div>
|
||||
{#if wishTallyInfoExpanded}
|
||||
<div class="pt-1" transition:slide>
|
||||
<p class="mb-1">{$t('wish.import.wishTally')}</p>
|
||||
<p>
|
||||
{$t('wish.import.wishTallyCollected.0')} 5<Icon size={0.8} path={mdiStar} className="mb-1" />
|
||||
{$t('wish.import.wishTallyCollected.1')} 4<Icon size={0.8} path={mdiStar} className="mb-1" />
|
||||
{$t('wish.import.wishTallyCollected.2')}
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<p class="mt-4">{$t('wish.import.importNotice1')}</p>
|
||||
<p>{$t('wish.import.importNotice2')}</p>
|
||||
<p class="font-semibold">{$t('wish.import.saveData')}</p>
|
||||
|
|
|
@ -67,7 +67,7 @@ export function process(id) {
|
|||
image,
|
||||
total: 0,
|
||||
legendary: [],
|
||||
rarePity: [0,0,0,0,0,0,0,0,0,0],
|
||||
rarePity: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
rare: {
|
||||
character: [],
|
||||
weapon: [],
|
||||
|
@ -89,6 +89,7 @@ export function process(id) {
|
|||
let striped = false;
|
||||
let startBanner = false;
|
||||
let currentBannerIndex = -1;
|
||||
let hasManualInput = false;
|
||||
|
||||
for (let i = 0; i < pullData.length; i++) {
|
||||
const pull = pullData[i];
|
||||
|
@ -154,6 +155,10 @@ export function process(id) {
|
|||
newPull.end = true;
|
||||
}
|
||||
|
||||
if (pull.manualInput === true) {
|
||||
hasManualInput = true;
|
||||
}
|
||||
|
||||
newPull.striped = striped;
|
||||
startBanner = false;
|
||||
|
||||
|
@ -163,5 +168,6 @@ export function process(id) {
|
|||
return {
|
||||
pulls: currentPulls,
|
||||
banner: selectedBanners,
|
||||
}
|
||||
hasManualInput,
|
||||
};
|
||||
}
|
||||
|
|
61
src/functions/wishTally.js
Normal file
61
src/functions/wishTally.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { process } from './wish';
|
||||
|
||||
const bannerCategories = ['beginners', 'standard', 'character-event', 'weapon-event'];
|
||||
|
||||
async function sendWish(data) {
|
||||
try {
|
||||
await fetch(`${__paimon.env.API_HOST}/wish`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
export async function submitWishTally() {
|
||||
let prefixId = 0;
|
||||
for (const id of bannerCategories) {
|
||||
prefixId += 100000;
|
||||
|
||||
const data = process(id);
|
||||
if (data === null) continue;
|
||||
if (data.hasManualInput) continue;
|
||||
|
||||
console.log('processing wish tally', id);
|
||||
|
||||
const { pulls, banner } = data;
|
||||
|
||||
const firstFivePulls = pulls.slice(0, 5).map((e) => [e.time.toString(), e.id, e.type, e.pity, e.group === 'group']);
|
||||
|
||||
for (let i = banner.length - 1; i >= Math.max(banner.length - 2, 0); i--) {
|
||||
const total = banner[i].total;
|
||||
if (total === 0) continue;
|
||||
|
||||
const rarePity = banner[i].rarePity;
|
||||
const legendaryCount = banner[i].legendary.length;
|
||||
const rareCount = banner[i].rare.character.length + banner[i].rare.weapon.length;
|
||||
const legendaryPulls = banner[i].legendary.map((e) => [
|
||||
e.time.toString(),
|
||||
e.id,
|
||||
e.type,
|
||||
e.pity,
|
||||
e.group === 'group',
|
||||
]);
|
||||
|
||||
console.log(legendaryPulls);
|
||||
console.log(rarePity);
|
||||
console.log(legendaryCount, rareCount, total);
|
||||
await sendWish({
|
||||
firstPulls: firstFivePulls,
|
||||
legendaryPulls,
|
||||
rarePulls: rarePity,
|
||||
banner: prefixId + i + 1,
|
||||
total,
|
||||
legendary: legendaryCount,
|
||||
rare: rareCount,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -48,6 +48,9 @@
|
|||
"timeout": "Connection timeout, please wait a moment and try again later",
|
||||
"invalidData": "Invalid data returned from API, try again later",
|
||||
"success": "Import success 😀!",
|
||||
"wishTallyCheck": "Submit pity for global wish tally",
|
||||
"wishTally": "We are doing a global wish tally! You can submit your wish tally to participate. All pity data will be aggregated to know what is the average pity of paimon.moe users.",
|
||||
"wishTallyCollected": ["What will be collected:", "and", "pity from your wish history"],
|
||||
"faqs": {
|
||||
"title": "Import Wish History FAQ",
|
||||
"q1": "How does it work?",
|
||||
|
@ -110,6 +113,11 @@
|
|||
"exporting": "Exporting...",
|
||||
"import": "Import",
|
||||
"exportFinish": "Export success, please wait until the browser download the file!",
|
||||
"wishTallyTitle": "Submit Wish Tally",
|
||||
"wishTally": "We are doing a global wish tally! You can submit your wish tally to participate. All pity data will be aggregated to know what is the average pity of paimon.moe users.",
|
||||
"wishTallyCollected": ["What will be collected:", "and", "pity from your wish history"],
|
||||
"wishTallySubmit": "Submit Wish Tally",
|
||||
"wishTallyThankyou": "Thankyou for participating!",
|
||||
"manualTitle": "Manual Input Setting",
|
||||
"enableManual": "Enable Manual Input",
|
||||
"notice": "Using Auto Import and manual input together is not recommended as it still requires some more testing!",
|
||||
|
|
|
@ -48,6 +48,9 @@
|
|||
"timeout": "Connection timeout, tunggu sebentar dan coba lagi nanti",
|
||||
"invalidData": "Invalid data dikembalikan dari API, coba lagi nanti",
|
||||
"success": "Import berhasil 😀!",
|
||||
"wishTallyCheck": "Submit pity untuk perhitungan pity global",
|
||||
"wishTally": "Kita sedang melakukan perhitungan pity global! Kamu bisa mensubmit pity mu untuk berpartisipasi. Semua data pity akan dikumpulkan untuk mengetahui berapa pity rata-rata pengguna paimon.moe.",
|
||||
"wishTallyCollected": ["Yang dikumpulkan:", "dan", "pity dari riwayat wish mu"],
|
||||
"faqs": {
|
||||
"title": "Import Riwayat Wish FAQS",
|
||||
"q1": "Cara kerjanya gimana?",
|
||||
|
@ -110,6 +113,11 @@
|
|||
"exporting": "Sedang meng-export...",
|
||||
"import": "Import",
|
||||
"exportFinish": "Export berhasil, harap tunggu sampai file nya sudah ter-download!",
|
||||
"wishTallyTitle": "Submit Perhitungan Pity Wish",
|
||||
"wishTally": "Kita sedang melakukan perhitungan pity global! Kamu bisa mensubmit pity mu untuk berpartisipasi. Semua data pity akan dikumpulkan untuk mengetahui berapa pity rata-rata pengguna paimon.moe.",
|
||||
"wishTallyCollected": ["Yang dikumpulkan:", "dan", "pity dari riwayat wish mu"],
|
||||
"wishTallySubmit": "Submit Perhitungan Pity Wish",
|
||||
"wishTallyThankyou": "Terimakasih sudah berpartisipasi!",
|
||||
"manualTitle": "Pengaturan Manual Input",
|
||||
"enableManual": "Nyalakan Manual Input",
|
||||
"notice": "Menggunakan Import Otomatis dan Manual Input secara bersamaan tidak direkomendasikan karena belum stabil, dan masih perlu di testing!",
|
||||
|
|
|
@ -39,24 +39,17 @@
|
|||
let rareEdit = 0;
|
||||
|
||||
let showRarity = [true, true, false];
|
||||
let sortedPull = [];
|
||||
|
||||
$: path = `wish-counter-${id}`;
|
||||
$: if ($fromRemote) {
|
||||
readLocalData();
|
||||
}
|
||||
$: sortedPull = pulls
|
||||
.slice()
|
||||
.filter((e) => {
|
||||
if (e.type === 'character') {
|
||||
return showRarity[5 - characters[e.id].rarity];
|
||||
} else if (e.type === 'weapon') {
|
||||
return showRarity[5 - weaponList[e.id].rarity];
|
||||
}
|
||||
})
|
||||
.reverse();
|
||||
$: showRarity, pulls, filterRarity();
|
||||
|
||||
onMount(() => {
|
||||
readLocalData();
|
||||
filterRarity();
|
||||
});
|
||||
|
||||
function toggleDetail() {
|
||||
|
@ -67,6 +60,27 @@
|
|||
showRarity[index] = !showRarity[index];
|
||||
}
|
||||
|
||||
function filterRarity() {
|
||||
const sorted = [];
|
||||
const reversedPulls = pulls.slice();
|
||||
for (let i = reversedPulls.length - 1; i >= 0; i--) {
|
||||
const e = reversedPulls[i];
|
||||
if (e.type === 'character' && showRarity[5 - characters[e.id].rarity]) {
|
||||
sorted.push({
|
||||
index: i,
|
||||
...e,
|
||||
});
|
||||
} else if (e.type === 'weapon' && showRarity[5 - weaponList[e.id].rarity]) {
|
||||
sorted.push({
|
||||
index: i,
|
||||
...e,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
sortedPull = sorted;
|
||||
}
|
||||
|
||||
function openAddModal(pity) {
|
||||
openModal(
|
||||
AddModal,
|
||||
|
@ -120,7 +134,7 @@
|
|||
}
|
||||
|
||||
function editPullDetail(index, updatePull) {
|
||||
const updated = sortedPull;
|
||||
const updated = pulls.slice();
|
||||
updated[index] = updatePull;
|
||||
pulls = updated;
|
||||
|
||||
|
@ -129,8 +143,9 @@
|
|||
}
|
||||
|
||||
function deletePullDetail(index) {
|
||||
sortedPull.splice(index, 1);
|
||||
pulls = sortedPull;
|
||||
const updated = pulls.slice();
|
||||
updated.splice(index, 1);
|
||||
pulls = updated;
|
||||
|
||||
closeModal();
|
||||
saveData();
|
||||
|
@ -361,8 +376,8 @@
|
|||
<th class="border-b border-gray-700 text-gray-400 font-display text-left pl-2">Time</th>
|
||||
<th class="border-b border-gray-700 text-gray-400 font-display text-right">Pity</th>
|
||||
</tr>
|
||||
{#each sortedPull as pull, index}
|
||||
<tr on:click={manualInput ? () => openEditModal(index, pull.type, pull.id, pull.time, pull.pity) : () => {}}>
|
||||
{#each sortedPull as pull}
|
||||
<tr on:click={manualInput ? () => openEditModal(pull.index, pull.type, pull.id, pull.time, pull.pity) : () => {}}>
|
||||
{#if pull.type === 'character'}
|
||||
<td
|
||||
class={`border-b border-gray-700 py-1 pl-2 font-semibold ${
|
||||
|
|
Loading…
Add table
Reference in a new issue