kinda finished
This commit is contained in:
parent
8a37f14a48
commit
11d9b7a0b4
11 changed files with 2706 additions and 162 deletions
5
.dockerignore
Normal file
5
.dockerignore
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
Dockerfile
|
||||||
|
node_modules/
|
||||||
|
build/
|
||||||
|
.svelte-kit/
|
||||||
|
.idea/
|
16
Dockerfile
Normal file
16
Dockerfile
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
FROM node:23-alpine AS base
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
FROM base AS dependencies
|
||||||
|
COPY package*.json /app/
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
FROM base AS build
|
||||||
|
COPY --from=dependencies /app/node_modules /app/node_modules
|
||||||
|
COPY . /app
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM base AS release
|
||||||
|
COPY --from=build /app/build /app/build
|
||||||
|
|
||||||
|
CMD ["node", "/app/build/index.js"]
|
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
2501
package-lock.json
generated
Normal file
2501
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/compat": "^1.2.3",
|
"@eslint/compat": "^1.2.3",
|
||||||
"@sveltejs/adapter-static": "^3.0.6",
|
"@sveltejs/adapter-node": "^5.2.11",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
||||||
"eslint": "^9.7.0",
|
"eslint": "^9.7.0",
|
||||||
|
@ -28,8 +28,5 @@
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
"typescript-eslint": "^8.0.0",
|
"typescript-eslint": "^8.0.0",
|
||||||
"vite": "^5.4.11"
|
"vite": "^5.4.11"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"svelte-adapter-bun": "^0.5.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
<div class="modal">
|
<div class="modal">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<button class="close" onclick={props.onclose}> X </button>
|
<button class="close" onclick={props.onclose}>X</button>
|
||||||
<video autoplay muted>
|
<video autoplay muted>
|
||||||
<source src={props.videoUrl} type="video/mp4" />
|
<source src={props.videoUrl} type="video/mp4" />
|
||||||
Your browser does not support the video tag.
|
Your browser does not support the video tag.
|
||||||
|
|
30
src/routes/+layout.svelte
Normal file
30
src/routes/+layout.svelte
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<script lang="ts">
|
||||||
|
let { children } = $props();
|
||||||
|
</script>
|
||||||
|
<main>
|
||||||
|
{@render children()}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:global(body) {
|
||||||
|
margin: 0;
|
||||||
|
font-family: 'Arial', sans-serif;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
color: #1c1919;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
background-color: #a8571c;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,6 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Modal from '$lib/Modal.svelte';
|
import Modal from '$lib/Modal.svelte';
|
||||||
|
import { page } from '$app/state';
|
||||||
|
|
||||||
const difficultyClass = 15;
|
const difficultyClass = 15;
|
||||||
const skin = 'winter';
|
const skin = 'winter';
|
||||||
|
|
||||||
|
@ -23,12 +24,14 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRoll = async () => {
|
const handleRoll = async () => {
|
||||||
|
if (rollResult) return;
|
||||||
rollResult = Math.floor(Math.random() * 20) + 1;
|
rollResult = Math.floor(Math.random() * 20) + 1;
|
||||||
rollVideoUrl = await getVideoUrl(skin, 'd20', rollResult);
|
rollVideoUrl = await getVideoUrl(skin, 'd20', rollResult);
|
||||||
showModal('roll');
|
showModal('roll');
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleGuidance = async () => {
|
const handleGuidance = async () => {
|
||||||
|
if (guidanceResult) return;
|
||||||
guidanceResult = Math.floor(Math.random() * 4) + 1;
|
guidanceResult = Math.floor(Math.random() * 4) + 1;
|
||||||
guidanceVideoUrl = await getVideoUrl(skin, 'd4', guidanceResult);
|
guidanceVideoUrl = await getVideoUrl(skin, 'd4', guidanceResult);
|
||||||
showModal('guidance');
|
showModal('guidance');
|
||||||
|
@ -49,182 +52,159 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main>
|
<section>
|
||||||
|
<h1>You have received a gift</h1>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Investigation</h2>
|
||||||
|
<p>Intelligence check</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Difficulty Class</h2>
|
||||||
|
<p>{difficultyClass}</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
{#if !pressedContinue}
|
||||||
<section>
|
<section>
|
||||||
<h1>You have received a gift</h1>
|
{#if !rollResult}
|
||||||
|
<button onclick={handleRoll}>Roll Ability</button>
|
||||||
|
{/if}
|
||||||
|
{#if rollResult && rollClickedExit}
|
||||||
|
<h2>Roll Result</h2>
|
||||||
|
<p>{rollResult}</p>
|
||||||
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
{#if rollModal && rollVideoUrl}
|
||||||
<h2>Investigation</h2>
|
<Modal onclose={() => {
|
||||||
<p>Intelligence check</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<h2>Difficulty Class</h2>
|
|
||||||
<p>{difficultyClass}</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
{#if !pressedContinue}
|
|
||||||
<section>
|
|
||||||
{#if !rollResult}
|
|
||||||
<button onclick={handleRoll}>Roll Ability</button>
|
|
||||||
{/if}
|
|
||||||
{#if rollResult && rollClickedExit}
|
|
||||||
<h2>Roll Result</h2>
|
|
||||||
<p>{rollResult}</p>
|
|
||||||
{/if}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{#if rollModal && rollVideoUrl}
|
|
||||||
<Modal onclose={() => {
|
|
||||||
rollModal = false;
|
rollModal = false;
|
||||||
rollClickedExit = true;
|
rollClickedExit = true;
|
||||||
}} videoUrl={rollVideoUrl} />
|
}} videoUrl={rollVideoUrl} />
|
||||||
{/if}
|
|
||||||
<section>
|
|
||||||
{#if !guidanceResult}
|
|
||||||
<button onclick={handleGuidance}>Roll Guidance</button>
|
|
||||||
{/if}
|
|
||||||
{#if guidanceResult && guidanceClickedExit}
|
|
||||||
<h2>Guidance Result</h2>
|
|
||||||
<p>{guidanceResult}</p>
|
|
||||||
{/if}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{#if guidanceModal && guidanceVideoUrl}
|
|
||||||
<Modal onclose={() => {
|
|
||||||
guidanceModal = false;
|
|
||||||
guidanceClickedExit = true;
|
|
||||||
}} videoUrl={guidanceVideoUrl} />
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if rollResult && guidanceResult}
|
|
||||||
<button class="continue" onclick={() => {pressedContinue = true}}>Continue</button>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
{#if rollResult && guidanceResult && pressedContinue}
|
{#if !guidanceResult}
|
||||||
<h2>Final Result</h2>
|
<button onclick={handleGuidance}>Roll Guidance</button>
|
||||||
<p>{rollResult + guidanceResult}</p>
|
{/if}
|
||||||
{#if rollResult + guidanceResult >= difficultyClass}
|
{#if guidanceResult && guidanceClickedExit}
|
||||||
<h2 class="success">Success</h2>
|
<h2>Guidance Result</h2>
|
||||||
<a href="/present">Collect your gift!</a>
|
<p>{guidanceResult}</p>
|
||||||
{:else}
|
|
||||||
<h2 class="failure">Failure</h2>
|
|
||||||
<button class="reset" onclick={resetPage}> Reset</button>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</main>
|
{#if guidanceModal && guidanceVideoUrl}
|
||||||
|
<Modal onclose={() => {
|
||||||
|
guidanceModal = false;
|
||||||
|
guidanceClickedExit = true;
|
||||||
|
}} videoUrl={guidanceVideoUrl} />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if rollResult && guidanceResult}
|
||||||
|
<button class="continue" onclick={() => {pressedContinue = true}}>Continue</button>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<section>
|
||||||
|
{#if rollResult && guidanceResult && pressedContinue}
|
||||||
|
<h2>Final Result</h2>
|
||||||
|
<p>{rollResult + guidanceResult}</p>
|
||||||
|
{#if rollResult + guidanceResult >= difficultyClass}
|
||||||
|
<h2 class="success">Success</h2>
|
||||||
|
<a href="/present{page.url.search}">Collect your gift!</a>
|
||||||
|
{:else}
|
||||||
|
<h2 class="failure">Failure</h2>
|
||||||
|
<button class="reset" onclick={resetPage}> Reset</button>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
:global(body) {
|
|
||||||
margin: 0;
|
|
||||||
font-family: 'Arial', sans-serif;
|
|
||||||
background-color: #f4f4f4;
|
|
||||||
color: #1c1919;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
h1, h2 {
|
||||||
display: flex;
|
font-size: 2rem;
|
||||||
flex-direction: column;
|
font-weight: bold;
|
||||||
justify-content: center;
|
margin: 20px 0;
|
||||||
align-items: center;
|
}
|
||||||
height: 100vh;
|
|
||||||
width: 100vw;
|
|
||||||
background-color: #a8571c;
|
|
||||||
color: white;
|
|
||||||
text-align: center;
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 20px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1, h2 {
|
section {
|
||||||
font-size: 2rem;
|
margin: 15px 0;
|
||||||
font-weight: bold;
|
width: 100%;
|
||||||
margin: 20px 0;
|
max-width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
section {
|
p {
|
||||||
margin: 15px 0;
|
font-size: 1.2rem;
|
||||||
width: 100%;
|
}
|
||||||
max-width: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
button {
|
||||||
font-size: 1.2rem;
|
background-color: #1c1919;
|
||||||
}
|
color: white;
|
||||||
|
padding: 12px 25px;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button:hover {
|
||||||
background-color: #1c1919;
|
background-color: #333;
|
||||||
color: white;
|
}
|
||||||
padding: 12px 25px;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
border: none;
|
|
||||||
border-radius: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 0.3s ease;
|
|
||||||
margin-top: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:hover {
|
button:disabled {
|
||||||
background-color: #333;
|
background-color: #aaa;
|
||||||
}
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
button:disabled {
|
a {
|
||||||
background-color: #aaa;
|
color: #fff;
|
||||||
cursor: not-allowed;
|
text-decoration: none;
|
||||||
}
|
font-weight: bold;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a:hover {
|
||||||
color: #fff;
|
text-decoration: underline;
|
||||||
text-decoration: none;
|
}
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
h2 {
|
||||||
text-decoration: underline;
|
color: #ffdf00;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2.success {
|
||||||
color: #ffdf00;
|
color: #4CAF50;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2.success {
|
h2.failure {
|
||||||
color: #4CAF50;
|
color: #FF6347;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2.failure {
|
button.reset {
|
||||||
color: #FF6347;
|
background-color: #ff6347;
|
||||||
}
|
padding: 10px 20px;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
button.reset {
|
button.reset:hover {
|
||||||
background-color: #ff6347;
|
background-color: #e55347;
|
||||||
padding: 10px 20px;
|
}
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.reset:hover {
|
button.continue {
|
||||||
background-color: #e55347;
|
background-color: #4CAF50;
|
||||||
}
|
padding: 10px 20px;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
button.continue {
|
button.continue:hover {
|
||||||
background-color: #4CAF50;
|
background-color: #45a049;
|
||||||
padding: 10px 20px;
|
}
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.continue:hover {
|
section > button {
|
||||||
background-color: #45a049;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
section > button {
|
|
||||||
margin-top: 20px;
|
|
||||||
}</style>
|
|
||||||
|
|
|
@ -1,8 +1,23 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
// Show the gift key that was in ENV during build
|
import { page } from '$app/state';
|
||||||
const steamGiftKey = import.meta.env.VITE_STEAM_GIFT_KEY;
|
|
||||||
|
let steamGiftKey = $state<string | null>(null);
|
||||||
|
let isLegit = $state<boolean>(true);
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
const bk = page.url.searchParams.get('bk');
|
||||||
|
if (!bk) {
|
||||||
|
isLegit = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
steamGiftKey = atob(bk);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1>Congrats!</h1>
|
{#if isLegit}
|
||||||
<h2>Here is your prize <3</h2>
|
<h1>Congrats!</h1>
|
||||||
<p>{steamGiftKey}</p>
|
<h2>Enjoy your gift <3</h2>
|
||||||
|
<p>{steamGiftKey}</p>
|
||||||
|
{:else}
|
||||||
|
<h1>Sorry, this gift is not for you</h1>
|
||||||
|
{/if}
|
Binary file not shown.
|
@ -1,4 +1,4 @@
|
||||||
import adapter from 'svelte-adapter-bun'
|
import adapter from '@sveltejs/adapter-node'
|
||||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||||
|
|
||||||
/** @type {import('@sveltejs/kit').Config} */
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
|
|
Loading…
Reference in a new issue