Compare commits

..

No commits in common. "main" and "list" have entirely different histories.
main ... list

379 changed files with 3105 additions and 6115 deletions
.forgejo/workflows
CarouselExample.htmlbuild.shjsconfig.jsonpackage-lock.jsonpackage.jsonpnpm-lock.yamlpostcss.config.js
src
static/images

View file

@ -1,23 +0,0 @@
name: Rebuild signaller for deprived.dev to rebuild site
on: [push]
jobs:
test_service:
runs-on: native
steps:
- name: Get branch
run: echo "BRANCH=$(echo "${{ gitea.ref }}" | cut -d'/' -f3)" >> $GITHUB_ENV
- name: Signal deprived.dev for rebuild
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }}
run: |
sshkey=$(mktemp)
trap "rm -rf $sshkey" exit
echo -e $SSH_PRIVATE_KEY > $sshkey
service="build-deprived-website-$BRANCH"
sshargs="-o LogLevel=ERROR -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
echo "Starting systemd oneshot service: $service"
ssh -i $sshkey -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no deprivedbuilder@deprived.dev -t "sudo /run/current-system/sw/bin/systemctl start $service"
echo "Build Log: $(ssh -i $sshkey $sshargs deprivedbuilder@deprived.dev "cat ~/latest_build.log")"

66
CarouselExample.html Normal file
View file

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML Carousel Example</title>
<!-- Include Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<div id="carouselExample" class="carousel slide" data-bs-ride="carousel">
<!-- Indicators -->
<div class="carousel-indicators">
<button type="button" data-bs-target="#carouselExample" data-bs-slide-to="0" class="active"
aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-bs-target="#carouselExample" data-bs-slide-to="1"
aria-label="Slide 2"></button>
<button type="button" data-bs-target="#carouselExample" data-bs-slide-to="2"
aria-label="Slide 3"></button>
</div>
<!-- Carousel Items -->
<div class="carousel-inner">
<div class="carousel-item active">
<img src="https://via.placeholder.com/800x400" class="d-block w-100" alt="Slide 1">
<div class="carousel-caption d-none d-md-block">
<h5>First Slide</h5>
<p>Description for the first slide.</p>
</div>
</div>
<div class="carousel-item">
<img src="https://via.placeholder.com/800x400" class="d-block w-100" alt="Slide 2">
<div class="carousel-caption d-none d-md-block">
<h5>Second Slide</h5>
<p>Description for the second slide.</p>
</div>
</div>
<div class="carousel-item">
<img src="https://via.placeholder.com/800x400" class="d-block w-100" alt="Slide 3">
<div class="carousel-caption d-none d-md-block">
<h5>Third Slide</h5>
<p>Description for the third slide.</p>
</div>
</div>
</div>
<!-- Controls -->
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExample" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselExample" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
</div>
<!-- Include Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

24
build.sh Normal file → Executable file
View file

@ -4,10 +4,28 @@
# NODE_ENV is set to production, npm won't install anything # NODE_ENV is set to production, npm won't install anything
unset NODE_ENV unset NODE_ENV
git pull echo "Rebuilding deprived main site"
git reset --hard main echo "cwd: ${pwd}"
npm ci #rm -rf deprived-main-website
#git clone https://gitea.deprived.dev/Sveskejuice/deprived-main-website.git
git restore .
git clean -fd
git pull
git checkout WeGoingBasic
echo "Project files up to date. Proceeding to install deps"
echo "npm config list:"
npm config list
npm cache clean --force
npm i
npm i @sveltejs/adapter-static
npm i @sveltejs/kit
npm i @zerodevx/svelte-img
npm tailwind init
echo "Ready to build, building..." echo "Ready to build, building..."

View file

@ -10,12 +10,7 @@
"sourceMap": true, "sourceMap": true,
"strict": true, "strict": true,
"moduleResolution": "bundler", "moduleResolution": "bundler",
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true
"paths": {
"@images/*": ["./src/images/*"],
"@src/*": ["./src/*"],
"@static/*": ["./static/*"]
}
} }
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias and https://kit.svelte.dev/docs/configuration#files // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias and https://kit.svelte.dev/docs/configuration#files
// //

2140
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,33 +6,33 @@
"dev": "vite dev", "dev": "vite dev",
"build": "vite build", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --compiler-warnings \"css-unused-selector:ignore,unused-export-let:ignore\" --threshold error", "check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch --threshold error" "check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch"
}, },
"devDependencies": { "devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/adapter-static": "^3.0.1", "@sveltejs/adapter-static": "^3.0.1",
"@sveltejs/kit": "^2.20.4", "@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0",
"@tailwindcss/typography": "^0.5.15", "@tailwindcss/typography": "^0.5.15",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"daisyui": "^5.0.12", "daisyui": "^4.12.12",
"postcss": "^8.4.47",
"sass": "^1.77.4", "sass": "^1.77.4",
"svelte": "^5.25.7", "svelte": "^4.2.7",
"svelte-check": "^3.8.6", "svelte-check": "^3.6.0",
"svelte-highlight": "^7.6.0", "svelte-highlight": "^7.6.0",
"tailwindcss": "^4.1.3", "tailwindcss": "^3.4.13",
"typescript": "^5.0.0", "typescript": "^5.0.0",
"vite": "^5.0.3", "vite": "^5.0.3",
"vite-plugin-svgr": "^4.2.0" "vite-plugin-svgr": "^4.2.0"
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@lucide/svelte": "^0.487.0",
"@tailwindcss/vite": "^4.1.3",
"lucide-svelte": "^0.475.0", "lucide-svelte": "^0.475.0",
"svelte-katex": "^0.1.2", "svelte-katex": "^0.1.2",
"svelte-media-queries": "^1.6.2", "svelte-media-queries": "^1.6.2",
"svelte-parallax": "^0.6.0",
"theme-change": "^2.5.0" "theme-change": "^2.5.0"
} }
} }

2502
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

6
postcss.config.js Normal file
View file

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View file

@ -1,222 +0,0 @@
@import "tailwindcss";
@plugin "daisyui";
@plugin "daisyui/theme" {
name: "Deprived";
default: true;
prefersdark: true;
--color-base-100: oklch(14% 0 0);
--color-base-200: oklch(20% 0 0);
--color-base-300: oklch(26% 0 0);
--color-base-content: oklch(97% 0 0);
--color-primary: oklch(72% 0.219 149.579);
--color-primary-content: oklch(98% 0.018 155.826);
--color-secondary: oklch(58% 0.233 277.117);
--color-secondary-content: oklch(96% 0.018 272.314);
--color-accent: oklch(60% 0.25 292.717);
--color-accent-content: oklch(96% 0.016 293.756);
--color-neutral: oklch(20% 0 0);
--color-neutral-content: oklch(98% 0 0);
--color-info: oklch(58% 0.158 241.966);
--color-info-content: oklch(97% 0.013 236.62);
--color-success: oklch(64% 0.2 131.684);
--color-success-content: oklch(98% 0.031 120.757);
--color-warning: oklch(68% 0.162 75.834);
--color-warning-content: oklch(98% 0.026 102.212);
--color-error: oklch(57% 0.245 27.325);
--color-error-content: oklch(97% 0.013 17.38);
--radius-selector: 1rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 0;
--noise: 0;
}
@plugin "daisyui/theme" {
name: "dark";
color-scheme: "dark";
--color-base-100: oklch(14% 0 0);
--color-base-200: oklch(20% 0 0);
--color-base-300: oklch(26% 0 0);
--color-base-content: oklch(97% 0 0);
--color-primary: oklch(90% 0.182 98.111);
--color-primary-content: oklch(28% 0.066 53.813);
--color-secondary: oklch(84% 0.143 164.978);
--color-secondary-content: oklch(26% 0.051 172.552);
--color-accent: oklch(87% 0.01 258.338);
--color-accent-content: oklch(13% 0.028 261.692);
--color-neutral: oklch(26% 0 0);
--color-neutral-content: oklch(98% 0 0);
--color-info: oklch(71% 0.143 215.221);
--color-info-content: oklch(98% 0.019 200.873);
--color-success: oklch(76% 0.233 130.85);
--color-success-content: oklch(98% 0.031 120.757);
--color-warning: oklch(70% 0.213 47.604);
--color-warning-content: oklch(98% 0.016 73.684);
--color-error: oklch(65% 0.241 354.308);
--color-error-content: oklch(97% 0.014 343.198);
--radius-selector: 0rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 0;
--noise: 1;
}
@plugin "daisyui/theme" {
name: "pink";
color-scheme: "light";
--color-base-100: oklch(96% 0.015 12.422);
--color-base-200: oklch(94% 0.03 12.58);
--color-base-300: oklch(89% 0.058 10.001);
--color-base-content: oklch(41% 0.159 10.272);
--color-primary: oklch(86% 0.127 207.078);
--color-primary-content: oklch(30% 0.056 229.695);
--color-secondary: oklch(0% 0 0);
--color-secondary-content: oklch(100% 0 0);
--color-accent: oklch(87% 0.169 91.605);
--color-accent-content: oklch(27% 0.077 45.635);
--color-neutral: oklch(51% 0.222 16.935);
--color-neutral-content: oklch(96% 0.015 12.422);
--color-info: oklch(74% 0.16 232.661);
--color-info-content: oklch(29% 0.066 243.157);
--color-success: oklch(77% 0.152 181.912);
--color-success-content: oklch(27% 0.046 192.524);
--color-warning: oklch(75% 0.183 55.934);
--color-warning-content: oklch(26% 0.079 36.259);
--color-error: oklch(70% 0.191 22.216);
--color-error-content: oklch(25% 0.092 26.042);
--radius-selector: 0.25rem;
--radius-field: 0.25rem;
--radius-box: 0.25rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 0;
}
@plugin "daisyui/theme" {
name: "netherrack";
color-scheme: "dark";
--color-base-100: oklch(25% 0.092 26.042);
--color-base-200: oklch(39% 0.141 25.723);
--color-base-300: oklch(44% 0.177 26.899);
--color-base-content: oklch(93% 0.032 17.717);
--color-primary: oklch(83% 0.128 66.29);
--color-primary-content: oklch(26% 0.079 36.259);
--color-secondary: oklch(82% 0.111 230.318);
--color-secondary-content: oklch(29% 0.066 243.157);
--color-accent: oklch(78% 0.115 274.713);
--color-accent-content: oklch(25% 0.09 281.288);
--color-neutral: oklch(57% 0.245 27.325);
--color-neutral-content: oklch(97% 0.013 17.38);
--color-info: oklch(71% 0.143 215.221);
--color-info-content: oklch(98% 0.019 200.873);
--color-success: oklch(72% 0.219 149.579);
--color-success-content: oklch(98% 0.018 155.826);
--color-warning: oklch(76% 0.188 70.08);
--color-warning-content: oklch(98% 0.022 95.277);
--color-error: oklch(63% 0.237 25.331);
--color-error-content: oklch(97% 0.013 17.38);
--radius-selector: 2rem;
--radius-field: 2rem;
--radius-box: 2rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 1;
}
@plugin "daisyui/theme" {
name: "green";
color-scheme: "dark";
--color-base-100: oklch(26% 0.065 152.934);
--color-base-200: oklch(39% 0.095 152.535);
--color-base-300: oklch(44% 0.119 151.328);
--color-base-content: oklch(96% 0.044 156.743);
--color-primary: oklch(80% 0.105 251.813);
--color-primary-content: oklch(28% 0.091 267.935);
--color-secondary: oklch(80% 0.105 251.813);
--color-secondary-content: oklch(28% 0.091 267.935);
--color-accent: oklch(89% 0.196 126.665);
--color-accent-content: oklch(27% 0.072 132.109);
--color-neutral: oklch(52% 0.154 150.069);
--color-neutral-content: oklch(98% 0.018 155.826);
--color-info: oklch(78% 0.154 211.53);
--color-info-content: oklch(30% 0.056 229.695);
--color-success: oklch(79% 0.209 151.711);
--color-success-content: oklch(26% 0.065 152.934);
--color-warning: oklch(85% 0.199 91.936);
--color-warning-content: oklch(28% 0.066 53.813);
--color-error: oklch(71% 0.202 349.761);
--color-error-content: oklch(28% 0.109 3.907);
--radius-selector: 0.25rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 0;
--noise: 1;
}
.bg-grid-100 {
background:
linear-gradient(-90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px),
linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px), #f2f2f2;
background-size:
4px 4px,
4px 4px,
80px 80px,
80px 80px,
80px 80px,
80px 80px,
80px 80px,
80px 80px;
background-color: var(--color-base-100);
}
.bg-grid-200 {
background:
linear-gradient(-90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px),
linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px), #f2f2f2;
background-size:
4px 4px,
4px 4px,
80px 80px,
80px 80px,
80px 80px,
80px 80px,
80px 80px,
80px 80px;
background-color: var(--color-base-200);
}
.bg-grid-300 {
background:
linear-gradient(-90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px),
linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px), #f2f2f2;
background-size:
4px 4px,
4px 4px,
80px 80px,
80px 80px,
80px 80px,
80px 80px,
80px 80px,
80px 80px;
background-color: var(--color-base-300);
}
@media print {
.hide-on-print {
display: none !important;
}
}

View file

@ -1,42 +1,18 @@
<!doctype html> <!doctype html>
<html lang="en" data-theme="Deprived" style="overflow-x: hidden"> <html lang="en" data-theme="Synthwave" style="overflow-x: hidden;">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta <meta name="description" content="
name="description" We are the deprived devs, and we are a team of developers specializing in indie game development, full-stack development, and anything tech-related!">
content=" <link rel="icon" href="%sveltekit.assets%/favicon.png" />
We are the deprived devs, and we are a team of developers specializing in indie game development, full-stack development, and anything tech-related!" <meta name="viewport" content="width=device-width, initial-scale=1" />
/>
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Change theme for site here --> <!-- Change theme for site here -->
<link rel="stylesheet" href="/stylesheets/global.css" /> <link rel="stylesheet" href="/stylesheets/main-theme.css" />
%sveltekit.head% <link rel="stylesheet" href="/stylesheets/global.css" />
%sveltekit.head%
<script> </head>
let theme = null;
if (typeof localStorage !== "undefined") { <body style="display: contents">%sveltekit.body%</div>
theme = localStorage.getItem("theme");
}
window.AvailableThemes = ["green", "netherrack", "dark", "pink"];
if (!theme) {
// const randomNumber = Math.floor(Math.random() * 4);
// console.log("Slecting: " + AvailableThemes[randomNumber]);
// document.documentElement.setAttribute('data-theme', AvailableThemes[randomNumber]);
localStorage.setItem("theme", AvailableThemes[0]);
}
//else {
// console.log("Slecting: " + theme);
// document.documentElement.setAttribute('data-theme', theme);
//}
</script>
</head>
<body style="display: contents">
<div class="inline relative w-full h-full">%sveltekit.body%</div>
</body>
</html> </html>

3
src/lib/app.css Normal file
View file

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

File diff suppressed because one or more lines are too long

View file

@ -11,7 +11,9 @@
version="1.1" version="1.1"
viewBox="0 0 28 20" viewBox="0 0 28 20"
width="28" width="28"
xml:space="preserve"><defs xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1" /><path id="defs1" /><path
d="M 2,4 H 26 C 27.104,4 28,3.104 28,2 28,0.896 27.104,0 26,0 H 2 C 0.896,0 0,0.896 0,2 0,3.104 0.896,4 2,4 Z M 26,8 H 2 c -1.104,0 -2,0.896 -2,2 0,1.104 0.896,2 2,2 h 24 c 1.104,0 2,-0.896 2,-2 0,-1.104 -0.896,-2 -2,-2 z m 0,8 H 2 c -1.104,0 -2,0.896 -2,2 0,1.104 0.896,2 2,2 h 24 c 1.104,0 2,-0.896 2,-2 0,-1.104 -0.896,-2 -2,-2 z" d="M 2,4 H 26 C 27.104,4 28,3.104 28,2 28,0.896 27.104,0 26,0 H 2 C 0.896,0 0,0.896 0,2 0,3.104 0.896,4 2,4 Z M 26,8 H 2 c -1.104,0 -2,0.896 -2,2 0,1.104 0.896,2 2,2 h 24 c 1.104,0 2,-0.896 2,-2 0,-1.104 -0.896,-2 -2,-2 z m 0,8 H 2 c -1.104,0 -2,0.896 -2,2 0,1.104 0.896,2 2,2 h 24 c 1.104,0 2,-0.896 2,-2 0,-1.104 -0.896,-2 -2,-2 z"
id="path1" id="path1"

Binary file not shown.

Before

(image error) Size: 673 KiB

Binary file not shown.

Before

(image error) Size: 14 KiB

View file

@ -1,313 +1,296 @@
<!-- If url contains "hideOnPrint" param, then detect if start printing then hide elements --> <!-- If url contains "hideOnPrint" param, then detect if start printing then hide elements -->
<script lang="ts"> <script lang="ts">
import "../app.css"; import "$lib/app.css";
import { fly } from "svelte/transition";
import MediaQuery from "svelte-media-queries";
import { Dices } from "@lucide/svelte";
let hideOnPrint: boolean = $state(false);
let { children } = $props(); import { fly } from 'svelte/transition';
import MediaQuery from 'svelte-media-queries';
export let hideOnPrint: boolean;
import DeprivedLogo from "$lib/images/DeprivedLogo.svelte"; import DeprivedLogo from "$lib/images/DeprivedLogo.svelte";
import HamburgerMenuIcon from "$lib/images/HamburgerMenuIcon.svelte"; import HamburgerMenuIcon from "$lib/images/HamburgerMenuIcon.svelte";
const footerCollapseThreshold: string = "1000px"; import svelteLogo from "$lib/svelteLogos/svelte-logo.png"
const headerCollapseThreshold: string = "1000px";
let footerCollapse: boolean;
let isMobile: boolean = $state(false);
let navbarHidden: boolean = $state(true); const footerCollapseThreshold : string = '1000px';
const headerCollapseThreshold : string = '1000px';
let footerCollapse : boolean;
let isMobile : boolean;
function resetNavBar() { let navbarHidden : boolean = true;
navbarHidden = true;
}
import { afterNavigate } from "$app/navigation"; function resetNavBar() {
afterNavigate(() => { navbarHidden = true;
const params = new URLSearchParams(window.location.search);
hideOnPrint = params.get("hideOnPrint") === "1";
console.log(hideOnPrint);
});
import { onMount } from "svelte";
import Zooter from "./comps/Zooter.svelte";
onMount(async () => {
const lock = document.createElement("meta");
lock.name = "darkreader-lock";
document.head.appendChild(lock);
});
function nextTheme() {
let theme: string | null = null;
if (typeof localStorage !== "undefined") {
theme = localStorage.getItem("theme");
} }
const themesArr = (window as any).AvailableThemes; import { afterNavigate } from '$app/navigation';
let nextTheme = "dark"; afterNavigate(() => {
if ( const params = new URLSearchParams(window.location.search);
theme == "null" || hideOnPrint = params.get('hideOnPrint') === '1';
theme == "undefined" || //console.log(hideOnPrint);
theme == undefined || });
theme == null
) {
} else {
nextTheme = themesArr[(1 - -themesArr.indexOf(theme)) % themesArr.length];
}
console.log("Slecting: " + nextTheme); import { onMount } from 'svelte';
document.documentElement.setAttribute("data-theme", nextTheme); import { themeChange } from 'theme-change'
localStorage.setItem("theme", nextTheme); onMount(() => {
} const lock = document.createElement('meta');
lock.name = 'darkreader-lock';
document.head.appendChild(lock);
themeChange(false) // false parameter is required for svelte
});
</script> </script>
{#snippet SwitchThemeButton()}
<div
class="tooltip tooltip-bottom grid place-content-center"
data-tip="Switch theme"
>
<button class="cursor-pointer" onclick={nextTheme}> <Dices /></button>
</div>
{/snippet}
<!-- Detect mobile --> <!-- Detect mobile -->
<MediaQuery <MediaQuery query='(max-width: {footerCollapseThreshold})' bind:matches={footerCollapse} />
query="(max-width: {footerCollapseThreshold})" <MediaQuery query='(max-width: {headerCollapseThreshold})' bind:matches={isMobile} />
bind:matches={footerCollapse}
/>
<MediaQuery
query="(max-width: {headerCollapseThreshold})"
bind:matches={isMobile}
/>
<!-- Nav bar --> <!-- Nav bar -->
<div class=" bg-base-200 p-0"> <div class="bg-base-200 p-0">
<header class="{hideOnPrint ? 'hide-on-print' : ''} bg-base-300"> <header class="{hideOnPrint ? 'hide-on-print' : ''}">
<div class="nav-bar pr-4"> <div class="nav-bar pr-4 bg-base-200">
{#if !isMobile} {#if !isMobile}
<div class="desktop"> <div class="desktop">
<a href="/" class="nav-head"> <a href="/" class="nav-head">
<DeprivedLogo <DeprivedLogo Class="fill-base-content p-2" Style="width: 3.5rem; height: auto;"/>
Class="fill-base-content p-2" <!-- <h3 id="logo-text">The Deprived Devs</h3> -->
Style="width: 3.5rem; height: auto;" </a>
/> <div class="nav-spacer" />
<!-- <h3 id="logo-text">The Deprived Devs</h3> -->
</a>
<div class="nav-spacer" />
<!-- <a href="/">Home</a> --> <!-- <a href="/">Home</a> -->
<!-- <a href="/zhen/notes/physics/1?hideOnPrint=1" target="_blank" style="width: 7.5rem;">Notes</a> --> <!-- <a href="/zhen/notes/physics/1?hideOnPrint=1" target="_blank" style="width: 7.5rem;">Notes</a> -->
<a href="/zhen/cv/rev2?hideOnPrint=1" target="_blank" style="width: 7.5rem;">Zhen CV</a>
{@render SwitchThemeButton()} <a href="/tools" style="width: 7.5rem;">Tools</a>
<a href="https://botalex.itch.io/" target="_blank">Games</a>
<a <!-- <a href="/posts">Blog</a>
href="/zhen/cv/rev2?hideOnPrint=1"
target="_blank"
style="width: 7.5rem;">Zhen CV</a
>
<a href="/tools" style="width: 7.5rem;">Tools</a>
<a href="https://botalex.itch.io/" target="_blank">Games</a>
<!-- <a href="/posts">Blog</a>
<a href="/about">About</a> --> <a href="/about">About</a> -->
</div>
{:else}
<div class="collapsed">
<a on:click={resetNavBar} href="/" class="nav-head">
<DeprivedLogo Class="fill-base-content p-2" Style="width: 3.5rem; height: auto;"/>
<!-- <h3 id="logo-text">The Deprived Devs</h3> -->
</a>
<div class="nav-spacer" />
<button id="toggle-nav" on:click={() => navbarHidden = !navbarHidden}>
<HamburgerMenuIcon Class="fill-base-content"/>
</button>
</div>
{#if !navbarHidden}
<div class="nav-list" transition:fly={{ y: -25, duration: 350 }}>
<!-- <a on:click={resetNavBar} href="/">Home</a> -->
<a on:click={resetNavBar} href="https://botalex.itch.io/" target="_blank">Games</a>
<a href="/zhen/cv/rev2?hideOnPrint=1" target="_blank">Zhen's CV</a>
<!-- <a on:click={resetNavBar} href="/posts">Blog</a>
<a on:click={resetNavBar} href="/about">About</a> -->
</div>
{/if}
{/if}
</div> </div>
{:else} </header>
<div class="collapsed shadow-xl">
<a onclick={resetNavBar} href="/" class="nav-head"> <!-- Page content -->
<DeprivedLogo <slot />
Class="fill-base-content p-2"
Style="width: 3.5rem; height: auto;" <!-- About footer -->
/> <footer class="{hideOnPrint ? 'hide-on-print' : ''}">
<!-- <h3 id="logo-text">The Deprived Devs</h3> --> <div class="about-container">
</a> <div class="credits">
<div class="nav-spacer" /> <span>© 2023-2024</span>
{@render SwitchThemeButton()} <br>
<div class="px-1"></div> <span>Benjamin Dreyer</span>
<button <br>
id="toggle-nav" <span>Oliver Schwenger</span>
onclick={() => { <br>
navbarHidden = !navbarHidden; <span>Sylvester Junge</span>
console.log(navbarHidden); <br>
}} <span>Snorre Ettrup Altschul</span>
> <br>
<HamburgerMenuIcon Class="fill-base-content" /> <span>Zhentao Wei</span>
</button> </div>
<div>
<h3><b>About this website</b></h3>
<!-- <a href="/" target="_blank">Recursion</a> -->
<div class="flex justify-center">
This website was made using <a class="grid place-content-center" target="_blank" href="https://kit.svelte.dev/">
<img class="pl-2" src={svelteLogo} style="height: 2rem;" alt="SvelteKit logo"/></a>
</div>
<span>Website <a href="https://gitea.deprived.dev/Sveskejuice/deprived-main-website/src/branch/WeGoingBasic" target="_blank">source code</a></span>
</div>
<div class="contact">
<h3><b>Contact</b></h3>
<a href="mailto:zhen@deprived.dev">zhen@deprived.dev</a>
<div class="mt-2"></div>
<a href="https://discord.gg/awatEEqc3M" target="_blank" class="social">
<!-- <span>Discord</span> -->
<img src="/images/icons/discord.svg" alt="Discord"/>
</a>
</div>
</div> </div>
{#if !navbarHidden} </footer>
<div class="nav-list" transition:fly={{ y: -25, duration: 350 }}>
<!-- <a onclick={resetNavBar} href="/">Home</a> -->
<a
onclick={resetNavBar}
href="https://botalex.itch.io/"
target="_blank">Games</a
>
<a href="/zhen/cv/rev2?hideOnPrint=1" target="_blank">Zhen's CV</a>
<!-- <a onclick={resetNavBar} href="/posts">Blog</a>
<a onclick={resetNavBar} href="/about">About</a> -->
</div>
{/if}
{/if}
</div>
</header>
<!-- Page content -->
{@render children?.()}
<Zooter bind:hideOnPrint />
</div> </div>
{#if footerCollapse}
<style> <style lang="scss">
.about-container { /* Nav bar. */
flex-direction: column; header {
justify-content: center !important; display: flex;
gap: 25px; justify-content: center;
} }
</style>
header a {
text-decoration: none;
}
.nav-bar {
width: 100%;
max-width: 1400px;
}
.desktop {
width: 100%;
display: flex;
gap: 30px;
}
.collapsed {
width: 100%;
display: flex;
}
#toggle-nav {
background: transparent;
border: none;
}
.nav-list {
display: flex;
flex-direction: column;
gap: 10px;
align-items: center;
}
.nav-head {
display: flex;
align-items: center;
gap: 10px;
}
#logo-link {
width: 64px;
aspect-ratio: 1 / 1;
}
#logo-text {
font-size: 24px;
color: oklch(var(--bc));
font-family: var(--title-font);
margin: 0;
min-width: 200px;
}
.nav-spacer {
width: 100%;
}
header a {
display: flex;
align-items: center;
font-size: 22px;
font-family: var(--title-font);
// Text color
color: oklch(var(--bc));
}
/* Footer. */
footer {
margin-top: 50px;
padding: 25px 0;
background-color: oklch(var(--b3));
height: 100%;
display: flex;
justify-content: center;
}
.about-container {
width: 80%;
height: 100%;
color: oklch(var(--bc));
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
& h3 {
font-size: larger;
}
}
.about-container > div {
align-items: center;
text-align: center;
}
.credits {
line-height: 2;
}
.contact {
display: flex;
flex-direction: column;
}
.social {
display: flex;
align-content: center;
gap: 10px;
}
.social > img {
width: 24px;
}
footer h3 {
margin-top: 0px;
color: var(--text2);
}
footer a {
color: var(--text2);
text-decoration-line: underline;
}
a:hover {
filter: brightness(130%);
}
@media print {
.hide-on-print {
display: none;
}
}
</style>
{#if footerCollapse}
<style>
.about-container {
flex-direction: column;
justify-content: center !important;
gap: 25px;
}
</style>
{/if} {/if}
{#if isMobile} {#if isMobile}
<style> <style>
</style>
</style>
{/if} {/if}
<style lang="scss">
/* Nav bar. */
header {
display: flex;
justify-content: center;
}
header a {
text-decoration: none;
}
.nav-bar {
width: 100%;
max-width: 1400px;
}
.desktop {
width: 100%;
display: flex;
gap: 30px;
}
.collapsed {
width: 100%;
display: flex;
}
#toggle-nav {
background: transparent;
border: none;
}
.nav-list {
display: flex;
flex-direction: column;
gap: 10px;
align-items: center;
}
.nav-head {
display: flex;
align-items: center;
gap: 10px;
}
#logo-link {
width: 64px;
aspect-ratio: 1 / 1;
}
#logo-text {
font-size: 24px;
color: oklch(var(--bc));
font-family: var(--title-font);
margin: 0;
min-width: 200px;
}
.nav-spacer {
width: 100%;
}
header a {
display: flex;
align-items: center;
font-size: 22px;
font-family: var(--title-font);
// Text color
color: oklch(var(--bc));
}
/* Footer. */
footer {
margin-top: 50px;
padding: 25px 0;
background-color: oklch(var(--b3));
height: 100%;
display: flex;
justify-content: center;
}
.about-container {
width: 80%;
height: 100%;
color: oklch(var(--bc));
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
& h3 {
font-size: larger;
}
}
.about-container > div {
align-items: center;
text-align: center;
}
.credits {
line-height: 2;
}
.contact {
display: flex;
flex-direction: column;
}
.social {
display: flex;
align-content: center;
gap: 10px;
}
.social > img {
width: 24px;
}
footer h3 {
margin-top: 0px;
color: var(--text2);
}
footer a {
color: var(--text2);
text-decoration-line: underline;
}
a:hover {
filter: brightness(130%);
}
</style>

View file

@ -6,7 +6,8 @@
import Button from '$lib/IO/Button.svelte'; import Button from '$lib/IO/Button.svelte';
import { ButtonType } from '$lib/IO/ButtonType.ts'; import { ButtonType } from '$lib/IO/ButtonType.ts';
import Timeline from '../comps/timeline/timeline.svelte'; import Timeline from '../comps/timeline/timeline.svelte';
import { onMount, tick } from 'svelte' import { Parallax, ParallaxLayer, StickyLayer } from "svelte-parallax";
import { tick } from 'svelte'
import PreviewDeprivedLogo from "$lib/images/DeprivedLogo-NoBackground.png"; import PreviewDeprivedLogo from "$lib/images/DeprivedLogo-NoBackground.png";
@ -34,28 +35,22 @@
const mobileThreshold : string = '600px'; // was 1000px. zhen testing const mobileThreshold : string = '600px'; // was 1000px. zhen testing
let mobile : boolean; let mobile : boolean;
onMount(()=> {
let tabTittleElement = window.document.getElementById("TabTittle");
if (tabTittleElement) // Not null
tabTittleElement.innerHTML = "Deprived devs";
});
</script> </script>
<!-- Detect mobile --> <!-- Detect mobile -->
<MediaQuery query='(max-width: {mobileThreshold})' bind:matches={mobile} /> <MediaQuery query='(max-width: {mobileThreshold})' bind:matches={mobile} />
<title id="TabTittle">We are the DEPRIVED DEVS</title> <title>We are the DEPRIVED DEVS</title>
<meta content="We are the deprived devs" property="og:title" /> <meta content="We are the deprived devs" property="og:title" />
<meta content="We make everything frontend, backend, games, websites, machine learning, whatever. We're just abunch of nerds, and we love it!" property="og:description" /> <meta content="We collaborate to create game, and hopefully more in the future! Wanna join? Hit us up." property="og:description" />
<meta content={PreviewDeprivedLogo} property="og:image" /> <meta content={PreviewDeprivedLogo} property="og:image" />
<meta content="#bdd6ee" data-react-helmet="true" name="theme-color" /> <meta content="#bdd6ee" data-react-helmet="true" name="theme-color" />
<div class="pointer-events-auto" style="position: relative; width: 100%; height: 100%; overflow: hidden;"> <div class="pointer-events-auto" style="position: relative; width: 100%; height: 100%; overflow: hidden;">
<img id="backgroundGif" src="{BackgroundVideo}" alt="Background video"/> <img id="backgroundGif" src="{BackgroundVideo}" alt="Background video"/>
<div class="main-title m-auto cozette" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; display: flex; justify-content: center; align-items: center; gap: 2rem; color: white; padding: 1rem;"> <div class="main-title m-auto" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; display: flex; justify-content: center; align-items: center; gap: 2rem; color: white; padding: 1rem;">
<h1 style="font-size: {!mobile ? 5 : 3}rem; text-shadow: 0.2rem 0.2rem 1rem rgba(0, 0, 0, 0.9);"> <h1 style="font-size: {!mobile ? 5 : 3}rem; text-shadow: 0.2rem 0.2rem 1rem rgba(0, 0, 0, 0.9); z-index: 100;">
{#if !mobile} {#if !mobile}
Deprived Devs Deprived Devs
{:else} {:else}
@ -72,67 +67,75 @@
</div> </div>
</div> </div>
<div class="cozette flex flex-col justify-center items-center w-full md:px-8 pt-4"> <div class="flex justify-center w-full px-8 py-4">
<h2 class="text-center" style="font-size: {!mobile ? 3 : 2}rem;"> <div class="grid space-y-5" style="width: 100%; max-width: 21cm;">
Developers <h2 class="prose main-title" style="font-size: {!mobile ? 3 : 2}rem;">
</h2> Developers
<div class=""> </h2>
<div class="grid max-lg:grid-cols-1 sm:grid-cols-2 gap-4 p-4 max-lg:px-0 w-full">
<Profile name="Zhen / Alex" tags={["Programmer", "3D artist", "UX Designer"]} isMobile={mobile}> <Profile name="Zhen / Alex" tags={["Programmer", "3D artist", "UX Designer"]} isMobile={mobile}>
<span> <span>
<p>Hi, I am Alex/Zhen, {@html !mobile ? "" : "<br/>"} I'm that chinese guy.</p> <p>Hi, I am Alex/Zhen, {@html !mobile ? "" : "<br/>"} I'm that chinese guy.</p>
<p>Here's my CV: <a href="/zhen/cv/rev2?hideOnPrint=1" style="color:lightblue;">pdf</a></p> <p>Here's my CV: <a href="/zhen/cv/rev2?hideOnPrint=1" style="color:lightblue;">pdf</a></p>
</span> </span>
</Profile> </Profile>
<Profile name="Sveske / Benjamin" tags={["Programmer", "Back-end Admin"]} isMobile={mobile}> <ProfileSpacer/>
<span> <Profile name="Sveske / Benjamin" tags={["Programmer", "Back-end Admin"]} isMobile={mobile}>
<p><span class="inline line-through">Hi, I use Arch, btw. </span> I use NixOS now</p> <span>
<p><a href="https://www.linkedin.com/in/benjamin-dreyer/" target="_blank" style="color:lightblue;">Linked-in</a></p> <p>Hi, I use Arch, btw.</p>
</span> <p><a href="https://www.linkedin.com/in/benjamin-dreyer/" target="_blank" style="color:lightblue;">Linked-in</a></p>
</Profile> </span>
</Profile>
<Profile isSnorre={true} tags={["Programmer"]} isMobile={mobile}/> <ProfileSpacer/>
<Profile isSnorre={true} tags={["Programmer"]} isMobile={mobile}/>
<Profile name="Oliver" tags={["Sound/Story","2D Artist", "Programmer"]} isMobile={mobile}> <ProfileSpacer/>
<span> <Profile name="Oliver" tags={["Sound designer", "Story designer","2D Artist", "Programmer"]} isMobile={mobile}>
<p>Snorre does not get paid.</p> <span>
<p><a href="https://www.linkedin.com/in/oliver-schwenger-291944278/" target="_blank" style="color:lightblue;">Linked-in</a></p> <p>Snorre does not get paid.</p>
</span> <p><a href="https://www.linkedin.com/in/oliver-schwenger-291944278/" target="_blank" style="color:lightblue;">Linked-in</a></p>
</Profile> </span>
</Profile>
<Profile name="Kim" tags={["Cinemachine", "3D Artist", "Programmer"]} isMobile={mobile}> <ProfileSpacer/>
<span> <Profile name="Kim" tags={["Cinemachine", "3D Artist", "Programmer"]} isMobile={mobile}>
<p>Abla espaniol</p> <span>
<p><a href="https://www.linkedin.com/in/kim-rex-de-dios-408860299/" target="_blank" style="color:lightblue;">Linked-in</a></p> <p>Abla espaniol</p>
</span> <p><a href="https://www.linkedin.com/in/kim-rex-de-dios-408860299/" target="_blank" style="color:lightblue;">Linked-in</a></p>
</Profile> </span>
</Profile>
<Profile name="Zylvester" tags={["Sound/Story", "2D/3D artist"]} isMobile={mobile}> <ProfileSpacer/>
<span> <Profile name="Zylvester" tags={["2D/3D Artist", "Sound designer", "Story designer"]} isMobile={mobile}>
<p>Closeted omega weeb</p> <span>
<p><a href="https://www.linkedin.com/in/sylvester-junge-0b2a73196/" target="_blank" style="color:lightblue;">Linked-in</a>, <a href="https://www.youtube.com/watch?v=xvFZjo5PgG0" style="color:lightblue;">Funny link</a></p> <p>Hi, I am [insert text here]</p>
</span> <p>Here's a joke about recursion: <a href="/" target="_blank" style="color:lightblue;">recursion</a></p>
</Profile> </span>
</div> </Profile>
</div> </div>
</div> </div>
<div class="py-4"></div> <!-- space -->
<div class="py-8 flex justify-center">
<div style="width: 50%;">
<ProfileSpacer/>
</div>
</div>
<div class="grid place-content-center place-items-center pointer-events-auto font-mono"> <div class="grid place-content-center place-items-center min-h-screen pointer-events-auto font-mono">
<!-- <article class="pt-16 prose overflow-hidden {mobile ? "px-8" : ""}"> <article class="pt-16 prose overflow-hidden {mobile ? "px-8" : ""}">
<h2 class="main-title {!mobile ? "text-center m-auto" : "m-0"}" style="font-size: {!mobile ? 3 : 3}rem; ">About us</h2> <h2 class="main-title {!mobile ? "text-center m-auto" : "m-0"}" style="font-size: {!mobile ? 3 : 3}rem; ">About us</h2>
<p>We are a small group of developers and artists who started out as classmates, united by our passion for all things technology.</p> <p>We are a small group of developers and artists who started out as classmates, united by our passion for all things technology.</p>
</article> --> </article>
<!-- Spacer --> <!-- Spacer -->
<!-- <div style="width: 50%;" class="{!mobile ? "py-16" : "py-4"}"> <div style="width: 50%;" class="{!mobile ? "py-16" : "py-4"}">
<ProfileSpacer/> <ProfileSpacer/>
</div> --> </div>
<article class="prose {mobile ? "px-8" : ""}"> <article class="pt-16 prose {mobile ? "px-8" : ""}">
<h2 class="main-title {!mobile ? "text-center m-auto" : "m-0"}" style="font-size: {!mobile ? 3 : 3}rem; ">Games</h2> <h2 class="main-title {!mobile ? "text-center m-auto" : "m-0"}" style="font-size: {!mobile ? 3 : 3}rem; ">Games</h2>
<p>Here are some of our games from various gamejams from the past. <br/>(<span class="font-bold">ONLY</span> 48 hours per game)</p> <p>Here are some of our games from various gamejams from the past. <br/>(<span class="font-bold">ONLY</span> 48 hours per game)</p>
</article> </article>
@ -158,7 +161,7 @@
<br/> <br/>
<p>This was made during <a href="https://itch.io/jam/nordic-game-jam-2024/rate/2659665" class="underline">Nordic gamejam 2024</a></p> <p>This was made during <a href="https://itch.io/jam/nordic-game-jam-2024/rate/2659665" class="underline">Nordic gamejam 2024</a></p>
<div class="card-actions justify-end"> <div class="card-actions justify-end">
<a href="https://botalex.itch.io/corrobot-rebounce" target="_blank" class="btn btn-primary text-primary-content">View on itch.io</a> <a href="https://botalex.itch.io/corrobot-rebounce" target="_blank" class="btn btn-primary">View on itch.io</a>
</div> </div>
</div> </div>
</div> </div>
@ -180,7 +183,7 @@
<br/> <br/>
<p>This was made during <a href="https://itch.io/jam/future-game-makers-jam-2024" class="underline">Future Game Makers</a>, and of course our team won the competition.</p> <p>This was made during <a href="https://itch.io/jam/future-game-makers-jam-2024" class="underline">Future Game Makers</a>, and of course our team won the competition.</p>
<div class="card-actions justify-end"> <div class="card-actions justify-end">
<a href="https://botalex.itch.io/mop-of-the-dead" target="_blank" class="btn btn-primary text-primary-content">View on itch.io</a> <a href="https://botalex.itch.io/mop-of-the-dead" target="_blank" class="btn btn-primary">View on itch.io</a>
</div> </div>
</div> </div>
</div> </div>
@ -202,7 +205,7 @@
<br/> <br/>
<p>This was made during <a href="https://itch.io/jam/dmspiljam-november-2021" class="underline">Denmark Masters jam</a>. This jam has youths allover Denmark to compete, and of course our team won the competition again.</p> <p>This was made during <a href="https://itch.io/jam/dmspiljam-november-2021" class="underline">Denmark Masters jam</a>. This jam has youths allover Denmark to compete, and of course our team won the competition again.</p>
<div class="card-actions justify-end"> <div class="card-actions justify-end">
<a href="https://botalex.itch.io/one-more-time" target="_blank" class="btn btn-primary text-primary-content">View on itch.io</a> <a href="https://botalex.itch.io/one-more-time" target="_blank" class="btn btn-primary">View on itch.io</a>
</div> </div>
</div> </div>
</div> </div>
@ -210,9 +213,7 @@
<div class="games card bg-base-100 w-96 shadow-xl"> <div class="games card bg-base-100 w-96 shadow-xl">
<figure class="rounded-b-none" style="height: 15em;"> <figure class="skeleton rounded-b-none" style="height: 15em;"></figure>
<div class="bg-grid-100 flex w-full h-full"></div>
</figure>
<div class="card-body"> <div class="card-body">
<h2 class="card-title">What's next?</h2> <h2 class="card-title">What's next?</h2>
<div class="skeleton mt-1 h-4 w-28"></div> <div class="skeleton mt-1 h-4 w-28"></div>
@ -222,7 +223,7 @@
<div class="skeleton h-4 w-full"></div> <div class="skeleton h-4 w-full"></div>
<div class="flex grow"/> <div class="flex grow"/>
<div class="card-actions justify-end"> <div class="card-actions justify-end">
<a href="/" target="_blank" class="btn btn-primary text-primary-content text-primary-content">RECURSION!</a> <a href="/" target="_blank" class="btn btn-primary">RECURSION!</a>
</div> </div>
</div> </div>
</div> </div>
@ -231,6 +232,11 @@
<style> <style>
.main-title {
width: 80%;
font-family: var(--title-font);
}
#backgroundGif{ #backgroundGif{
width: 100%; width: 100%;
height: 100%; height: 100%;

View file

@ -1,64 +0,0 @@
<script lang="ts">
import { onMount } from "svelte";
let scrollY = 0;
const animateInterval = 16;
const startMove = 64;
const numFrames = 312;
let framesLoaded = 1;
let ballsLoaded = 0;
let frameLoader: HTMLImageElement;
let frameLoader2: HTMLImageElement;
let frameLoader3: HTMLImageElement;
let frameLoader4: HTMLImageElement;
onMount(()=>{
// Force load once
ballsLoaded = 4;
onLoaded();
});
function onLoaded (){
ballsLoaded++;
if (ballsLoaded > 3) {
frameLoader.src = "/images/spinning_cat/untitled_" + framesLoaded.toString().padStart(5, '0') + ".png";
framesLoaded++;
frameLoader2.src = "/images/spinning_cat/untitled_" + framesLoaded.toString().padStart(5, '0') + ".png";
framesLoaded++;
frameLoader3.src = "/images/spinning_cat/untitled_" + framesLoaded.toString().padStart(5, '0') + ".png";
framesLoaded++;
frameLoader4.src = "/images/spinning_cat/untitled_" + framesLoaded.toString().padStart(5, '0') + ".png";
framesLoaded++;
ballsLoaded = 0;
}
}
let frameIndex = 0;
$: frameIndex = Math.min(Math.floor(Math.max(scrollY-startMove, 0) / animateInterval+1), numFrames);
</script>
<svelte:window bind:scrollY />
<div class="w-full flex justify-center" style="height: 5000px;">
<!-- Image Loader -->
<img on:load={()=>{onLoaded()}} bind:this={frameLoader} style="height: 0.01px; width: 0.01px;" class="" src="/images/spinning_cat/untitled_00001.png" alt="">
<img on:load={()=>{onLoaded()}} bind:this={frameLoader2} style="height: 0.01px; width: 0.01px;" class="" src="/images/spinning_cat/untitled_00001.png" alt="">
<img on:load={()=>{onLoaded()}} bind:this={frameLoader3} style="height: 0.01px; width: 0.01px;" class="" src="/images/spinning_cat/untitled_00001.png" alt="">
<img on:load={()=>{onLoaded()}} bind:this={frameLoader4} style="height: 0.01px; width: 0.01px;" class="" src="/images/spinning_cat/untitled_00001.png" alt="">
<!-- add "top-0" so it sticks at the top -->
<div class="sticky top-0" style="width: 200px; height: 200px;">
<div class="flex justify-center items-center" style="width: 200px; height: 200px;">
<img src="/images/spinning_cat/untitled_{frameIndex.toString().padStart(5, '0')}.png" class="object-contain w-full h-full" alt="">
</div>
<div>{frameIndex}</div>
</div>
</div>
<div class="h-[1000px] bg-amber-700 w-full">
</div>

View file

@ -11,15 +11,14 @@
</script> </script>
<div class="bg-grid-100 border-2 border-base-100 pl-1 pr-4 rounded-md cozette max-lg:pb-2">
{#if !isSnorre} {#if !isSnorre}
<div class="developersProfile {isSnorre ? "isSnorre" : ""} pl-1 font-mono"> <div class="developersProfile {isSnorre ? "isSnorre" : ""} pl-4 font-mono">
<NameAndTag name={name} tags={tags} isMobile={isMobile}/> <NameAndTag name={name} tags={tags} isMobile={isMobile}/>
<slot/> <slot/>
<MobileTags tags={tags} isMobile={isMobile}/> <MobileTags tags={tags} isMobile={isMobile}/>
</div> </div>
{:else} {:else}
<div class="w-full pl-1"> <div class="w-full">
<div class="developersProfile absolute snorre pl-4 font-mono pointer-events-none select-none"> <div class="developersProfile absolute snorre pl-4 font-mono pointer-events-none select-none">
<pre style="font-size: {!isMobile ? 1.5 : 1.5}rem;"> </pre> <pre style="font-size: {!isMobile ? 1.5 : 1.5}rem;"> </pre>
<span> <span>
@ -30,38 +29,35 @@
<pre> </pre> <pre> </pre>
{/if} {/if}
</div> </div>
<div class="developersProfile snorre-overlay relative pl-1 font-mono"> <div class="developersProfile snorre-overlay relative pl-4 font-mono">
<NameAndTag name="Snorre" tags={tags} isMobile={isMobile}/> <NameAndTag name="Snorre" tags={tags} isMobile={isMobile}/>
<span> <span>
<p>I'm the diversity hire. <span class="border-b" style="border-image: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet); border-image-slice: 1;">(Gay)</span></p> <p>I'm the diversity hire. (Gay)</p>
<!-- <p><a href="https://www.linkedin.com/in/snorrealtschul/" target="_blank" style="color:lightblue;">My website</a></p> --> <p><a href="https://www.linkedin.com/in/snorrealtschul/" target="_blank" style="color:lightblue;">Linked-in</a></p>
<p><a href="https://spoodythe.one/" target="_blank" style="color:lightblue;">My website</a></p>
</span> </span>
<MobileTags tags={tags} isMobile={isMobile}/> <MobileTags tags={tags} isMobile={isMobile}/>
</div> </div>
</div> </div>
{/if} {/if}
</div>
<style> <style>
.developersProfile:not(.snorre):not(.snorre-overlay){ .developersProfile:not(.snorre):not(.snorre-overlay){
/* background-image: linear-gradient(var(--color-neutral) 33%, rgba(255,255,255,0) 0%); */ background-image: linear-gradient(oklch(var(--p)) 33%, rgba(255,255,255,0) 0%);
/* background-image: linear-gradient(var(--color-neutral) 100%);
background-position: left; background-position: left;
background-size: 0.1rem 0.5rem; background-size: 0.1rem 0.5rem;
background-repeat: repeat-y; */ background-repeat: repeat-y;
} }
.snorre { .snorre {
/* border-left: dashed transparent 0.1rem; border-left: dashed transparent 0.1rem;
border-image: linear-gradient(to bottom, red, orange, yellow, green, blue, indigo, violet); border-image: linear-gradient(to bottom, red, orange, yellow, green, blue, indigo, violet);
border-image-slice: 1; */ border-image-slice: 1;
} }
.snorre-overlay { .snorre-overlay {
/* background-image: linear-gradient(rgba(255,255,255,0) 0%, rgba(255,255,255,0) 40%, var(--color-base-200) 40%); */ background-image: linear-gradient(rgba(255,255,255,0) 0%, rgba(255,255,255,0) 40%, oklch(var(--b1)) 40%);
/* background-position: left; background-position: left;
background-size: 0.1rem 0.5rem; background-size: 0.1rem 0.5rem;
background-repeat: repeat-y; */ background-repeat: repeat-y;
} }
</style> </style>

View file

@ -1,6 +1,8 @@
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte"; import { onMount } from "svelte";
import { Vector2 } from "../zhen/Utils/Vector2"; import { Vector2 } from "./../zhen/Utils/Vector2";
import { Parallax, ParallaxLayer, StickyLayer } from "svelte-parallax";
// Params // Params
let mouseMoveScale: number = 0.25; let mouseMoveScale: number = 0.25;

View file

@ -1,77 +1,38 @@
<script lang="ts"> <script lang="ts">
export let Tags = ["null"]; export let Tags= ["null"];
export let isMobile = false; export let isMobile = false;
type ColorType = string | { color1: string; color2: string; rotation: string; offset: string };
let colors: { [String: string]: ColorType} = {
"programmer": "#0CC27F",
"uxdesigner": "#027893",
"3dartist": "#F4881C",
"2dartist": "#F1EAC0",
"2d/3dartist": {"color1":"#F1EAC0", "color2":"#F4881C","rotation": "-65deg", "offset": "71.5%"},
"sounddesigner": "#F3EC2A",
"storydesigner": "#EEC12A",
"back-endadmin": "#3236a8",
};
// Define an interface for our detailed color object.
interface ColorObject {
color1: string;
color2: string;
rotation: string;
offset: string;
}
// ColorType can be a simple string or a ColorObject.
type ColorType = string | ColorObject;
// Create an interface for the color mapping.
interface ColorsMapping {
[key: string]: ColorType;
}
// Define a class to manage the colors.
class ColorManager {
private colors: ColorsMapping;
constructor() {
this.colors = {
"programmer": "#0CC27F",
"uxdesigner": "#027893",
"3dartist": "#F4881C",
"2dartist": "#F1EAC0",
"2d/3dartist": { color1: "#F1EAC0", color2: "#F4881C", rotation: "-65deg", offset: "71.5%" },
"sound/story": { color1: "#F3EC2A", color2: "#EEC12A", rotation: "-65deg", offset: "50%" },
"sounddesigner": "#F3EC2A",
"storydesigner": "#EEC12A",
"back-endadmin": "#3236a8",
};
}
// Return the color for the given key or a default value.
getColor(key: string): ColorType {
return this.colors[key] || "#ccc";
}
}
// Create an instance of ColorManager.
const colorManager = new ColorManager();
</script> </script>
<div class="flex gap-2" style="font-size: { !isMobile ? '0.875rem' : '2vw' };"> <div class="flex gap-2" style='font-size: {!isMobile ? "0.875rem" : "2vw"};'>
{#each Tags as tag} {#each Tags as tag}
{@const key = tag.replaceAll(" ", "").toLowerCase()} {@const key = tag.replaceAll(" ", "").toLowerCase()}
{@const color = colorManager.getColor(key)}
{#if key.indexOf("/") < 0} {#if key.indexOf("/") < 0}
<!-- Single Color Badge --> <div class="badge2 text-primary-content cozette" style="background-color: {colors[key] || "#ccc"};">{tag}</div>
<div class="badge2" style="background-color: {typeof color === 'string' ? color : '#ccc'};"> {:else}
<span class="invert">
{tag}
</span>
</div>
{:else}
<!-- Gradient Badge --> <!-- Gradient Badge -->
{#if typeof color === 'object' && color !== null} {#if typeof colors[key] === 'object' && colors[key] !== null}
<div <div
class="badge2 cozette" class="badge2 text-primary-content cozette"
style="background: linear-gradient({color.rotation}, {color.color2} {color.offset}, {color.color1} {color.offset});"> style="background: linear-gradient({colors[key].rotation}, {colors[key].color2} {colors[key].offset}, {colors[key].color1} {colors[key].offset});">
<span class="invert"> {tag}
{tag}
</span>
</div> </div>
{:else} {:else}
<div class="badge2 cozette" style="background-color: #ccc;"> <div
<span class="invert"> class="badge2 text-primary-content cozette"
{tag} style="background-color: #ccc;">
</span> {tag}
</div> </div>
{/if} {/if}
{/if} {/if}
@ -83,11 +44,12 @@
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 1.25rem; /* 20px */ height: 1.25rem /* 20px */;
line-height: 1.25rem; /* 20px */ line-height: 1.25rem /* 20px */;
width: fit-content; width: fit-content;
padding-left: 0.563rem; /* 9.008px */ padding-left: 0.563rem /* 9.008px */;
padding-right: 0.563rem; /* 9.008px */ padding-right: 0.563rem /* 9.008px */;
border-radius: var(--rounded-badge, 1.9rem); /* 30.4px */ border-radius: var(--rounded-badge, 1.9rem /* 30.4px */);
} }
</style> </style>

View file

@ -1,258 +0,0 @@
<script lang="ts">
import svelteLogo from "$lib/svelteLogos/svelte-logo.png";
import { browser } from "$app/environment";
import { onDestroy, onMount } from "svelte";
import { ArrowBigDown } from "lucide-svelte";
import { fly } from "svelte/transition";
const buildTime = __BUILD_TIME__;
let scrollY = 0;
const unscrollSpeed = 100;
let unscrollScrollDiv: HTMLDivElement;
let totalScroll = 0;
let unscrollInterval: number | undefined = undefined;
let lastScrollTime = 0; // Used to have delay before unscrolling
let isBeingTouched = false; // Phone support
const unscrollDelay = 100;
let isLeavingAnimating = false;
// prevent direct scroll
let notFirstScroll = false;
let tranisitionOverlay: HTMLElement;
// Function with more scroll control, by chatgpt
function smoothScrollTo(targetY: number, duration: number = 500): void {
const startY: number = window.scrollY;
const diff: number = targetY - startY;
if (duration <= 0) {
window.scrollTo(0, targetY);
return;
}
let startTime: number | null = null;
function step(timestamp: number): void {
if (startTime === null) startTime = timestamp;
const time = timestamp - startTime;
const percent = Math.min(time / duration, 1);
// easeInOutQuad easing
const ease =
percent < 0.5
? 2 * percent * percent
: -1 + (4 - 2 * percent) * percent;
window.scrollTo(0, startY + diff * ease);
if (time < duration) {
requestAnimationFrame(step);
}
}
requestAnimationFrame(step);
}
// Out animation:
function flyInFromTop(
node: HTMLElement,
{
y = -window.innerHeight,
duration = 400,
opacity = 0,
}: { y?: number; duration?: number; opacity?: number } = {},
) {
const {
delay = 0,
duration: d,
easing = (t) => t,
css,
} = fly(node, { y, duration: d, opacity });
let start: number;
function step(now: number) {
if (!start) start = now;
const elapsed = now - start - delay;
if (elapsed < 0) return requestAnimationFrame(step);
const t = Math.min(elapsed / d, 1);
if (css) node.style.cssText = css(easing(t), 1 - easing(t));
if (elapsed < d) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
onMount(() => {
return; // Fuck this, I'm too lazy to fix this atm
totalScroll = document.documentElement.scrollHeight - window.innerHeight;
unscrollInterval = setInterval(() => {
// Prevents scroll to bottom on first try
if (
!notFirstScroll &&
scrollY > totalScroll - unscrollScrollDiv.scrollHeight
) {
smoothScrollTo(totalScroll - unscrollScrollDiv.scrollHeight * 1.1, 0);
// Allow further scroll after delay
setTimeout(() => {
notFirstScroll = true;
}, 1000);
}
// console.log("Time with delay: " + (Date.now() - -unscrollDelay) + " Other " + lastScrollTime);
// console.log(isBeingTouched);
if (
!notFirstScroll ||
isBeingTouched ||
Date.now() < lastScrollTime - -unscrollDelay
) {
// console.log("nah");
return;
}
if (totalScroll - unscrollScrollDiv.scrollHeight < scrollY) {
smoothScrollTo(totalScroll - unscrollScrollDiv.scrollHeight, 200);
}
if (totalScroll <= scrollY) {
console.log("Hit!");
// isLeavingAnimating = true;
flyInFromTop(tranisitionOverlay, { duration: 800 });
}
}, 10);
});
function onScroll() {
lastScrollTime = Date.now();
// console.log("scroll");
}
function onResize() {
totalScroll = document.documentElement.scrollHeight - window.innerHeight;
}
onDestroy(() => {
clearInterval(unscrollInterval);
});
export let hideOnPrint: boolean;
</script>
<svelte:window
bind:scrollY
on:scroll={() => {
onScroll();
}}
on:touchstart={() => {
isBeingTouched = true;
}}
on:touchend={() => {
isBeingTouched = false;
}}
on:resize={onResize}
/>
<div class="{hideOnPrint ? 'hide-on-print' : ''} w-full">
<!-- Keep scrolling thing -->
<div class="hidden h-64 w-full flex flex-col justify-center items-center">
<div>Keep scrolling to veiw Zhen's portfolio site!</div>
<div class="flex justify-center">
<ArrowBigDown />
<ArrowBigDown />
<ArrowBigDown />
<ArrowBigDown />
</div>
</div>
<div
class="hidden h-64 w-full flex flex-col justify-end items-center"
bind:this={unscrollScrollDiv}
>
<img
src="/images/memes/WhatDaDog.png"
class="w-32 h-32 object-contain"
alt="da dog"
/>
</div>
<!-- About footer -->
<div
class="sticky bottom-0 flex flex-col justify-center pt-8 bg-base-300 mt-8"
>
<div class="flex justify-center">
<div class="grid gap-8 sm:grid-cols-3 items-center w-full">
<div class="flex flex-col items-center">
<span class="font-bold">© 2023-2025</span>
<br />
<span>Benjamin Dreyer</span>
<br />
<span>Oliver Schwenger</span>
<br />
<span>Sylvester Junge</span>
<br />
<span>Snorre Ettrup Altschul</span>
<br />
<span>Zhentao Wei</span>
</div>
<div class="flex flex-col items-center">
<h3><b>About this website</b></h3>
<!-- <a href="/" target="_blank">Recursion</a> -->
<div class="flex justify-center">
This website was made using <a
class="grid place-content-center"
target="_blank"
href="https://kit.svelte.dev/"
>
<img
class="pl-2"
src={svelteLogo}
style="height: 1.5rem;"
alt="SvelteKit logo"
/></a
>
</div>
<span
>Website <a
href="https://git.deprived.dev/DeprivedDevs/deprived-main-website"
target="_blank">source code</a
></span
>
</div>
<div class="flex flex-col items-center">
<h3><b>Contact</b></h3>
<a href="mailto:zhen@deprived.dev">zhen@deprived.dev</a>
<div class="mt-2"></div>
<a
href="https://discord.gg/awatEEqc3M"
target="_blank"
class="social"
>
<!-- <span>Discord</span> -->
<img
src="/images/icons/discord.svg"
class="w-8 h-8 object-contain"
alt="Discord"
/>
</a>
</div>
</div>
</div>
<div
class="flex w-full justify-center border-t border-base-100 border-dashed"
>
Last build: {buildTime} (+2 UTC)
</div>
</div>
</div>
<div
bind:this={tranisitionOverlay}
class="{isLeavingAnimating
? ''
: 'hidden'} fixed top-0 left-0 w-screen h-screen bg-base-200"
></div>
<!-- {#if isLeavingAnimating}
{/if} -->

View file

@ -1,7 +1,7 @@
<script> <script>
import A4 from "../zhen/notes/physics/sharedComps/A4.svelte"; import A4 from "../zhen/notes/physics/sharedComps/A4.svelte";
import ToolButton from "./comps/ToolButton.svelte"; import ToolButton from "./comps/ToolButton.svelte";
import { BatteryMedium } from '@lucide/svelte'; import { BatteryMedium } from 'lucide-svelte';
</script> </script>
<div class="flex justify-center pt-10"> <div class="flex justify-center pt-10">
@ -11,7 +11,7 @@
class="cozette text-base-content h-full" class="cozette text-base-content h-full"
> >
<div class="p-4 flex flex-col h-full"> <div class="p-4 flex flex-col h-full">
<h1 class="text-5xl font-bold">Tools (NOT FINISHED. come back in the future.)</h1> <h1 class="text-5xl font-bold">Tools</h1>
<span class="w-full text-xl" <span class="w-full text-xl"
>These are the tools collected from different places of the >These are the tools collected from different places of the
internet</span internet</span
@ -28,19 +28,19 @@
title="Sleeping battery life" title="Sleeping battery life"
desc="Calculates the battery life depending on sleep and non-sleep power usage." desc="Calculates the battery life depending on sleep and non-sleep power usage."
btnText="To calculator" btnText="To calculator"
toolIcon={BatteryMedium} icon={BatteryMedium}
/> />
<!-- <ToolButton <!-- <ToolButton
title="Sleeping battery life" title="Sleeping battery life"
desc="Calculates the battery life depending on sleep and non-sleep power usage." desc="Calculates the battery life depending on sleep and non-sleep power usage."
btnText="To calculator" btnText="To calculator"
toolIcon={BatteryMedium} icon={BatteryMedium}
/> />
<ToolButton <ToolButton
title="Sleeping battery life" title="Sleeping battery life"
desc="Calculates the battery life depending on sleep and non-sleep power usage." desc="Calculates the battery life depending on sleep and non-sleep power usage."
btnText="To calculator" btnText="To calculator"
toolIcon={BatteryMedium} icon={BatteryMedium}
/> --> /> -->
</div> </div>
</div> </div>

View file

@ -1,18 +1,16 @@
<script lang="ts"> <script lang="ts">
import A4 from "../../zhen/notes/physics/sharedComps/A4.svelte"; import A4 from "../../zhen/notes/physics/sharedComps/A4.svelte";
import { BatteryLifeCalculator } from "./pageSrc/BatteryCalc"; import { BatteryLifeCalculator } from "./pageSrc/BatteryCalc";
import { getMCU, type MCU_Type } from "./pageSrc/MCU_defs";
// let mathMachine = new BatteryLifeCalculator(); let mathMachine = new BatteryLifeCalculator();
let useCustom: boolean = false; let useCustom: boolean = false;
let selectedText: string = ""; let selectedText: string = "";
let selectedMcu: MCU_Type | undefined = undefined;
$: selectedMcu = getMCU(selectedText)
const options = ["esp32-s3", "esp32-s3"];
const options = ["esp32-s3", "Text Two", "Text Three"];
</script> </script>
<div class="flex justify-center pt-10"> <div class="flex justify-center pt-10">
@ -84,28 +82,21 @@
</div> </div>
{#if !useCustom} {#if !useCustom}
<div> <select
<select bind:value={selectedText}
bind:value={selectedText} class="select select-sm select-bordered w-56 max-w-xs"
class="select select-sm select-bordered w-56 max-w-xs" >
> <option disabled value="">Select a text</option>
<option disabled value="">Select a text</option> {#each options as option}
{#each options as option} <option value={option}>{option}</option>
<option value={option}>{option}</option> {/each}
{/each} </select>
</select>
{#if selectedMcu != undefined && selectedMcu?.wifi != undefined} {#if selectedText}
<p class="mt-4 text-lg"> <p class="mt-4 text-lg">
wifi You selected: {selectedText}
</p> </p>
{/if} {/if}
{#if selectedMcu != undefined && selectedMcu?.wifi != undefined}
<p class="mt-4 text-lg">
ble
</p>
{/if}
</div>
{:else} {:else}
<div class="form-control"> <div class="form-control">
<span class="text-sm text-slate-300 text-opacity-60" <span class="text-sm text-slate-300 text-opacity-60"

View file

@ -0,0 +1,108 @@
export class BatteryLifeCalculator {
constructor(
timeRunSeconds,
timeSleepSeconds,
consumptionActiveMilliAmpHours,
consumptionSleepMilliAmpHours,
powerBatteryTotalMilliAmpHours,
powerBatteryBufferBeforeEmptyPercent = 20) {
this.timeRunSeconds = timeRunSeconds
this.timeSleepSeconds = timeSleepSeconds
this.consumptionActiveMilliAmpHours = consumptionActiveMilliAmpHours
this.consumptionSleepMilliAmpHours = consumptionSleepMilliAmpHours
this.powerBatteryTotalMilliAmpHours = powerBatteryTotalMilliAmpHours
this.powerBatteryBufferBeforeEmptyPercent = powerBatteryBufferBeforeEmptyPercent
console.log("The source of this battery calc is here: https://github.com/simonneutert/batterylife-calculator\nI was too lazy to make the math myself.");
}
// public API
milliAmpToMicroAmp(milliAmps) {
return milliAmps * 1000
}
microAmpToMilliAmp(milliAmps) {
return milliAmps * 0.001
}
calculate() {
return {
powerAveragePerHour: this.powerEstimatedHourly(),
runtimeHoursEstimated: this.runtimeHoursEstimated(),
runtimeDaysEstimated: this.runtimeDaysEstimated(),
runtimeDaysRemainingHoursEstimated: this.runtimeDaysRemainingHoursEstimated()
}
}
powerEstimatedHourly() {
return this.calcPowerEst(
this.powerRun(),
this.consumptionActiveMilliAmpHours,
this.powerSleep(),
this.consumptionSleepMilliAmpHours
)
}
runtimeHoursEstimated() {
return parseInt(this.powerLipo() / this.powerEstimatedHourly())
}
runtimeDaysEstimated() {
return parseInt(this.runtimeHoursEstimated() / 24)
}
runtimeDaysRemainingHoursEstimated() {
return parseInt(this.runtimeHoursEstimated() % 24)
}
// private
roundOff(x) {
return Math.round(x * 100.0) / 100.0
}
calcPowerLipo(x, y) {
return parseFloat((x * (100 - y)) / 100)
}
calcRuns(x, y) {
return parseFloat(60 / (x + y))
}
calcRunsHour(x, y) {
return parseFloat(3600 / (x + y))
}
calcPowerRun(x, y) {
return parseFloat((x / (x + y)) * 3600)
}
calcPowerSleep(x, y) {
return parseFloat((y / (x + y)) * 3600)
}
powerLipo() {
return this.calcPowerLipo(this.powerBatteryTotalMilliAmpHours, this.powerBatteryBufferBeforeEmptyPercent)
}
runs() {
return this.calcRuns(this.timeRunSeconds, this.timeSleepSeconds)
}
runsHour() {
return this.calcRunsHour(this.timeRunSeconds, this.timeSleepSeconds)
}
powerRun() {
return this.calcPowerRun(this.timeRunSeconds, this.timeSleepSeconds)
}
powerSleep() {
return this.calcPowerSleep(this.timeRunSeconds, this.timeSleepSeconds)
}
calcPowerEst(a, b, c, d) {
return parseFloat((a / 3600) * b + (c / 3600) * d)
}
}

View file

@ -1,123 +0,0 @@
export class BatteryLifeCalculator {
timeRunSeconds: number;
timeSleepSeconds: number;
consumptionActiveMilliAmpHours: number;
consumptionSleepMilliAmpHours: number;
powerBatteryTotalMilliAmpHours: number;
powerBatteryBufferBeforeEmptyPercent: number;
constructor(
timeRunSeconds: number,
timeSleepSeconds: number,
consumptionActiveMilliAmpHours: number,
consumptionSleepMilliAmpHours: number,
powerBatteryTotalMilliAmpHours: number,
powerBatteryBufferBeforeEmptyPercent: number = 20
) {
this.timeRunSeconds = timeRunSeconds;
this.timeSleepSeconds = timeSleepSeconds;
this.consumptionActiveMilliAmpHours = consumptionActiveMilliAmpHours;
this.consumptionSleepMilliAmpHours = consumptionSleepMilliAmpHours;
this.powerBatteryTotalMilliAmpHours = powerBatteryTotalMilliAmpHours;
this.powerBatteryBufferBeforeEmptyPercent = powerBatteryBufferBeforeEmptyPercent;
console.log(
"The source of this battery calc is here: https://github.com/simonneutert/batterylife-calculator\nI was too lazy to make the math myself."
);
}
// public API
milliAmpToMicroAmp(milliAmps: number): number {
return milliAmps * 1000;
}
microAmpToMilliAmp(milliAmps: number): number {
return milliAmps * 0.001;
}
calculate(): {
powerAveragePerHour: number;
runtimeHoursEstimated: number;
runtimeDaysEstimated: number;
runtimeDaysRemainingHoursEstimated: number;
} {
return {
powerAveragePerHour: this.powerEstimatedHourly(),
runtimeHoursEstimated: this.runtimeHoursEstimated(),
runtimeDaysEstimated: this.runtimeDaysEstimated(),
runtimeDaysRemainingHoursEstimated: this.runtimeDaysRemainingHoursEstimated(),
};
}
powerEstimatedHourly(): number {
return this.calcPowerEst(
this.powerRun(),
this.consumptionActiveMilliAmpHours,
this.powerSleep(),
this.consumptionSleepMilliAmpHours
);
}
runtimeHoursEstimated(): number {
return parseInt((this.powerLipo() / this.powerEstimatedHourly()).toString(), 10);
}
runtimeDaysEstimated(): number {
return parseInt((this.runtimeHoursEstimated() / 24).toString(), 10);
}
runtimeDaysRemainingHoursEstimated(): number {
return parseInt((this.runtimeHoursEstimated() % 24).toString(), 10);
}
// private methods
private roundOff(x: number): number {
return Math.round(x * 100.0) / 100.0;
}
private calcPowerLipo(x: number, y: number): number {
return parseFloat(((x * (100 - y)) / 100).toString());
}
private calcRuns(x: number, y: number): number {
return parseFloat((60 / (x + y)).toString());
}
private calcRunsHour(x: number, y: number): number {
return parseFloat((3600 / (x + y)).toString());
}
private calcPowerRun(x: number, y: number): number {
return parseFloat(((x / (x + y)) * 3600).toString());
}
private calcPowerSleep(x: number, y: number): number {
return parseFloat(((y / (x + y)) * 3600).toString());
}
powerLipo(): number {
return this.calcPowerLipo(this.powerBatteryTotalMilliAmpHours, this.powerBatteryBufferBeforeEmptyPercent);
}
runs(): number {
return this.calcRuns(this.timeRunSeconds, this.timeSleepSeconds);
}
runsHour(): number {
return this.calcRunsHour(this.timeRunSeconds, this.timeSleepSeconds);
}
powerRun(): number {
return this.calcPowerRun(this.timeRunSeconds, this.timeSleepSeconds);
}
powerSleep(): number {
return this.calcPowerSleep(this.timeRunSeconds, this.timeSleepSeconds);
}
private calcPowerEst(a: number, b: number, c: number, d: number): number {
return parseFloat(((a / 3600) * b + (c / 3600) * d).toString());
}
}

View file

@ -6,9 +6,9 @@ export interface MCU_Type {
bluetooth?: { [key: string]: Number }; bluetooth?: { [key: string]: Number };
} }
const MCUs: MCU_Type[] = [ export const MCUs: MCU_Type[] = [
{ {
name: "esp32-s3", name: "ESP32-S3",
cpu: { // mili amps cpu: { // mili amps
single_core_40MHz: 21.8, single_core_40MHz: 21.8,
dual_core_40MHz: 24.4, dual_core_40MHz: 24.4,
@ -33,10 +33,10 @@ const MCUs: MCU_Type[] = [
}, },
{ {
name: "esp32-c3", name: "ESP32-C3",
cpu: { cpu: {
single_core_80MHz: 22, active: 130,
single_core_160MHz: 54.6, sleep: 15
}, },
sleep: { sleep: {
@ -51,13 +51,3 @@ const MCUs: MCU_Type[] = [
} }
} }
]; ];
export function getMCU(name: string): MCU_Type | undefined{
for (let i = 0; i < MCUs.length; i++) {
const element = MCUs[i];
if (element.name == name)
return element
}
return undefined;
}

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import type { Component } from 'svelte'; import type { SvelteComponent } from "svelte";
export let toolIcon: Component | undefined = undefined; export let icon: typeof SvelteComponent | undefined = undefined;
export let title: string = "Sleeping battery life"; export let title: string = "Sleeping battery life";
export let desc: string = "Calculates the battery life depending on sleep and non-sleep power usage."; export let desc: string = "Calculates the battery life depending on sleep and non-sleep power usage.";
@ -18,8 +18,8 @@
<div class="text-sm">{desc}</div> <div class="text-sm">{desc}</div>
<div class="flex pt-4"> <div class="flex pt-4">
{#if toolIcon != undefined} {#if icon != undefined}
<svelte:component this={toolIcon}/> <svelte:component this={icon}/>
{/if} {/if}
<a href="{btnHref}" class="btn ml-auto btn-primary btn-sm">{btnText}</a> <a href="{btnHref}" class="btn ml-auto btn-primary btn-sm">{btnText}</a>
</div> </div>

View file

@ -0,0 +1,17 @@
<script lang="ts">
import TopAnimatedBackground from "./Comps/TopAnimatedBackground.svelte";
import { Parallax, ParallaxLayer, StickyLayer } from "svelte-parallax";
import ZhenInformatikTimeline from "./Comps/ZhenInformatikTimeline.svelte"
import AboutMe from "./Comps/AboutMe.svelte"
</script>
<Parallax sections={3} config={{ stiffness: 0.1, damping: 0.3 }}>
<TopAnimatedBackground/>
<ParallaxLayer rate={0.5} offset={0.5} style="background-color: var(--background);">
<AboutMe/>
</ParallaxLayer>
<ParallaxLayer rate={0.5} offset={0.8} style="background-color: var(--background);">
<ZhenInformatikTimeline/>
</ParallaxLayer>
</Parallax>

View file

@ -0,0 +1,229 @@
<script lang="ts">
import { onMount } from "svelte";
import { Vector2 } from "./../Utils/Vector2";
import TopNameTextPlate from "./TopNameTextPlate.svelte";
//import { throttle } from "./../Utils/Throttle";
import { Parallax, ParallaxLayer, StickyLayer } from "svelte-parallax";
// Params
let mouseMoveScale: number = 0.25;
let targetTextLenght: number = 100;
// Site variables
let mousePos: Vector2;
// Element binded variables
let mouseRelativeScaled: Vector2 = new Vector2(0, 0);
let windowWidth = 0;
let windowHeight = 0;
let screenCenter: Vector2;
let StartPageAnimated: Element | null;
let windowRef: Window;
function onMouseMoved(event: MouseEvent) {
mousePos = new Vector2(event.clientX, event.clientY);
updateAnimation(mousePos);
}
function updateAnimation(mousePos: Vector2) {
let mouseRelativePos = mousePos.Sub(screenCenter);
mouseRelativeScaled = mouseRelativePos.Scale(mouseMoveScale);
//console.log(mouseRelativePos.x+"\n"+mouseRelativePos.y);
}
onMount(() => {
windowRef = window;
const updateDimensions = () => {
windowWidth = windowRef.innerWidth;
windowHeight = windowRef.innerHeight;
screenCenter = new Vector2(windowWidth / 2, windowHeight / 2);
//console.log("Window size changed: (" + windowWidth + ", " + windowHeight + ")");
};
updateDimensions(); // On first pass
windowRef.addEventListener("resize", updateDimensions);
const RevertToOrigin = () => {
if (
navigator.userAgent.search(/gecko/i) > 0 &&
StartPageAnimated !== null
) {
StartPageAnimated.classList.add("FirefoxSmoothTranition");
}
updateAnimation(new Vector2(windowWidth / 2, windowHeight / 2));
};
document.documentElement.addEventListener("mouseleave", RevertToOrigin);
const RemoveFirefoxSmoothTranition = () => {
if (
navigator.userAgent.search(/gecko/i) > 0 &&
StartPageAnimated !== null
) {
StartPageAnimated.classList.remove("FirefoxSmoothTranition");
}
};
document.documentElement.addEventListener(
"mouseenter",
RemoveFirefoxSmoothTranition,
);
return () => {
windowRef.removeEventListener("resize", updateDimensions);
};
});
const programmingLanguages: string[] = [
"C++",
"C#",
"ARDUINO",
"PYTHON",
"JAVA",
"JAVASCRIPT",
"TYPESCRIPT",
"HTML",
"CSS",
];
function getRandomInt(max: number) {
return Math.floor(Math.random() * max);
}
function GrabRandomString() {
let outString: string = "";
while (outString.length < targetTextLenght) {
outString +=
programmingLanguages[
getRandomInt(programmingLanguages.length)
] + " ";
}
return outString; // At about target size
}
</script>
<svelte:window on:mousemove={onMouseMoved} />
<ParallaxLayer class="StartPageContainer" rate={0.25} offset={0} span={0}>
<div
class="StartPageAnimated"
bind:this={StartPageAnimated}
style="transform: translate({mouseRelativeScaled.x}px, {mouseRelativeScaled.y}px) translateZ(0) rotate(0.001deg);"
>
{#each { length: 100 } as _, i}
<span class="rotate45 SkillsText">
{GrabRandomString()}
</span>
{/each}
</div>
</ParallaxLayer>
<ParallaxLayer rate={0} offset={0.25} span={0}>
<TopNameTextPlate />
</ParallaxLayer>
<!-- <div class="StartPageContainer">
<div class="TopOverlay">
<TopNameTextPlate/>
</div>
<div
class="StartPageAnimated"
id="StartPageAnimated"
bind:this={StartPageAnimated}
style="transform: translate({mouseRelativeScaled.x}px, {mouseRelativeScaled.y}px) translateZ(0) rotate(0.001deg);"
>
{#each {length: 100} as _, i}
<span
class="rotate45 SkillsText"
>
{GrabRandomString()}
</span
>
{/each}
</div>
</div> -->
<div id="DummyDiv" class="FirefoxSmoothTranition StartPageContainer TopOverlay" style="display: none !important;" />
<style>
.StartPageContainer {
/* height: 40vh; */
background-color: burlywood;
overflow: hidden;
position: relative;
justify-content: center;
align-items: center;
display: flex;
padding: 0;
}
.StartPageAnimated {
/* background: url("https://i1.adis.ws/i/canon/future_of_forests_header_16x9_dc14bbe1e35040f79bf566eedaf5c8f7?$hero-header-half-16by9-dt$"); */
background-color: #131313;
position: absolute;
height: 150vh;
width: 150vw;
padding: 0;
transition: transform 1000ms cubic-bezier(0.16, 1.63, 0.01, 0.99);
-moz-transition: none;
left: -25vw;
top: -50vh;
justify-content: center;
vertical-align: middle;
display: flex;
pointer-events: none;
}
.FirefoxSmoothTranition {
transition: transform 1000ms cubic-bezier(0.16, 1.63, 0.01, 0.99);
-moz-transition: transform 1000ms cubic-bezier(0.16, 1.63, 0.01, 0.99) !important;
}
.SkillsText {
font-family: "CozetteVector";
text-align: start;
font-size: x-large;
display: flex;
justify-content: center;
align-items: center;
white-space: nowrap;
width: 2rem;
color: rgb(66, 66, 66);
}
.TopOverlay {
position: absolute;
z-index: 1;
width: 100%;
height: 100%;
padding: 0;
}
.rotate45 {
transform: rotate(-45deg); /* Rotate the element by 45 degrees */
}
</style>

View file

@ -11,7 +11,7 @@
<p class="NickNameText">Alex</p> <p class="NickNameText">Alex</p>
</span> </span>
</div> </div>
<div style="flex-grow: 2;" /> <div style="flex-grow: 2;" />
</div> </div>
<style> <style>

View file

@ -0,0 +1,21 @@
export function throttle(callback, wait) {
let timeoutId = null;
let lastExecutedTime = 0;
return function (...args) {
const currentTime = Date.now();
const execute = () => {
lastExecutedTime = currentTime;
callback.apply(this, args);
};
if (currentTime - lastExecutedTime >= wait) {
execute();
} else {
clearTimeout(timeoutId);
timeoutId = setTimeout(execute, wait - (currentTime - lastExecutedTime));
}
};
}

View file

@ -7,15 +7,15 @@ export class Vector2 {
this.y = y; this.y = y;
} }
Add(vec2: Vector2) { Add(vec2: Vector2){
return new Vector2(this.x + vec2.x, this.y + vec2.y); return new Vector2(this.x + vec2.x, this.y + vec2.y);
} }
Sub(vec2: Vector2) { Sub(vec2: Vector2){
return new Vector2(this.x - vec2.x, this.y - vec2.y); return new Vector2(this.x - vec2.x, this.y - vec2.y);
} }
Scale(mult: number) { Scale(mult: number){
return new Vector2(this.x * mult, this.y * mult);; return new Vector2(this.x * mult, this.y * mult);;
} }
} }

View file

@ -1,53 +1,51 @@
<script> <script>
export let Style = ""; export let Style = "";
</script> </script>
<div class="container" style={Style}> <div class="container" style="{Style}">
<div class="w-full flex justify-center"> <div/>
<div class="text-center"></div> <div>
</div> <div>
Thank you! ❤
</div>
</div>
</div> </div>
<style lang="scss"> <style lang="scss">
.container { .container {
position: absolute; position: absolute;
transform: translate(20.3mm, -5mm) rotate(-45deg); transform: translate(40.2mm, 5mm) rotate(-45deg);
display: grid; display: grid;
justify-self: end; justify-self: end;
vertical-align: bottom; vertical-align: bottom;
align-self: flex-end; align-self: flex-end;
z-index: 0; z-index: 0;
> div:nth-child(1) { > div:nth-child(1) {
padding-top: 5mm; padding-top: 5mm;
//border-bottom: #4472c4 dashed 2mm; //border-bottom: #4472c4 dashed 2mm;
background-image: linear-gradient( background-image: linear-gradient(to right, #4472c4 70%, rgba(255,255,255,0) 0%);
to right, background-position: top;
#4472c4 70%, background-size: 6mm 1.5mm;
rgba(255, 255, 255, 0) 0% background-repeat: repeat-x;
); }
background-position: top;
background-size: 6mm 1.5mm; > div:nth-child(2) {
background-repeat: repeat-x; background-color: #2f5496;
width: 100mm;
height: 25mm;
// Text
display: grid;
place-content: center;
align-content: flex-start;
> div {
padding-top: 3.5mm;
color: #4a7bcf;
font-weight: bold;
}
}
} }
> div:nth-child(2) {
background-color: #2f5496;
width: 100mm;
height: 25mm;
// Text
display: grid;
place-content: center;
align-content: flex-start;
> div {
padding-top: 3.5mm;
color: #4a7bcf;
font-weight: bold;
}
}
}
</style> </style>

View file

@ -53,4 +53,11 @@
width: 100%; width: 100%;
} }
} }
.imagesContainer {
> img {
border-radius: 5mm;
filter: drop-shadow(1mm 1mm 1mm #0000009d);
}
}
</style> </style>

View file

@ -1,23 +0,0 @@
<script>
export let Style = "";
</script>
<div class="container" style="{Style}">
ALEX
</div>
<style lang="scss">
.container {
position: absolute;
display: grid;
justify-self: end;
vertical-align: bottom;
align-self: flex-end;
// font settings
font-size: 80mm;
color: #e4e4e4;
transform: translate(32%, -32%) rotate(-90deg);
}
</style>

View file

@ -1,27 +0,0 @@
<div class="short-profile-container">
<div>
<b style="text-align:left;">
Biggest flex
</b>
</div>
<div>
Me and my small group of devs has won each and every gamejam, which we have participated in. <br/>
<h1 style="font-size: 0.75rem; color: grey;">*Gamejams that had competitions.</h1>
</div>
</div>
<style>
.short-profile-container{
display: grid;
place-items: center;
width: 90%;
}
.short-profile-container > div:first-child {
width: 100%;
/* Bottom border stripe*/
border-bottom: 1mm solid black;
}
</style>

View file

@ -1,53 +0,0 @@
<script>
export let Style = "";
</script>
<div class="container" style={Style}>
<div class="w-full flex justify-center">
<div class="text-center"></div>
</div>
</div>
<style lang="scss">
.container {
position: absolute;
transform: translate(20.3mm, -5mm) rotate(-45deg);
display: grid;
justify-self: end;
vertical-align: bottom;
align-self: flex-end;
z-index: 0;
> div:nth-child(1) {
padding-top: 5mm;
//border-bottom: #4472c4 dashed 2mm;
background-image: linear-gradient(
to right,
#4472c4 70%,
rgba(255, 255, 255, 0) 0%
);
background-position: top;
background-size: 6mm 1.5mm;
background-repeat: repeat-x;
}
> div:nth-child(2) {
background-color: #2f5496;
width: 100mm;
height: 25mm;
// Text
display: grid;
place-content: center;
align-content: flex-start;
> div {
padding-top: 3.5mm;
color: #4a7bcf;
font-weight: bold;
}
}
}
</style>

View file

@ -1,7 +0,0 @@
<script>
import Contact from "./Contact.svelte";
import OtherContact from "./OtherContact.svelte";
</script>
<Contact/>
<OtherContact/>

View file

@ -1,76 +0,0 @@
<div class="container">
<div>
<b style="text-align:left;">
Contact
</b>
</div>
<div class="table-display">
<div class="table-item">
<div>Email</div>
<div>Zhen@deprived.dev</div>
</div>
<div class="table-item">
<div>Phone</div>
<div>+45 42535723</div>
</div>
<div class="table-item">
<div>LinkedIn</div>
<a href="https://www.linkedin.com/in/zhentao-wei-3a3a0a182/">Zhentao-Wei</a>
</div>
</div>
</div>
<style lang="scss">
.container{
display: grid;
place-items: center;
width: 70%;
}
.container > div:first-child {
width: 100%;
/* Bottom border stripe*/
border-bottom: 1mm solid black;
}
.table-display {
width: 100%;
}
.table-item {
display: flex;
justify-items: start;
width: 100%;
border-bottom: 0.25mm solid #000000;
> a {
text-decoration: underline;
}
> div, > a {
color: #000000;
&:first-child {
width: 35%;
font-size: 4mm;
display: grid;
place-content: center start;
border-right: rgba(128, 128, 128, 0.4) dashed 0.1mm;
}
&:nth-child(2) {
width: 65%;
font-size: 3.25mm;
display: grid;
place-content: center;
padding-left: 1mm;
}
}
}
</style>

View file

@ -1,47 +0,0 @@
<script>
import placeholder from "$lib/zhen/cv-comps/400x400.png";
import DTU_Logo from "$lib/zhen/cv-comps/DTU_Logo.png";
import NextLogo from "$lib/zhen/cv-comps/nextKbhLogo.png";
import SasLogo from "$lib/zhen/cv-comps/SASLogo.png";
import EmphasysLogo from "$lib/zhen/cv-comps/EmphasysLogo.png";
import IconAndText2 from "./IconAndText2.svelte";
</script>
<div class="container">
<div>
<b style="text-align:left;"> Education </b>
</div>
<div class="imagesContainer flex justify-center p-2 gap-4" id="balls">
<IconAndText2 logo={DTU_Logo}>
<b>DTU</b><br />
<p style="font-size: 0.5rem;">Artificial intelligence</p>
</IconAndText2>
<IconAndText2 logo={NextLogo}>
<b>Next</b><br />
<p style="font-size: 0.5rem;">Computer science</p>
</IconAndText2>
<IconAndText2 logo={SasLogo}>
<b>Master class</b><br />
<p style="font-size: 0.5rem;">SAS Programming</p>
</IconAndText2>
<IconAndText2 logo={EmphasysLogo}>
<b>Emphasys center</b><br />
<p style="font-size: 0.5rem;">VR development</p>
</IconAndText2>
</div>
</div>
<style lang="scss">
.container {
display: grid;
place-items: center;
width: 90%;
> div:first-child {
border-bottom: black 1mm solid;
width: 100%;
}
}
</style>

View file

@ -1,78 +0,0 @@
<script>
import placeholder from "$lib/zhen/cv-comps/400x400.png";
import MakerspaceLogo from "$lib/zhen/cv-comps/MakerspaceLogo.png";
import EposLogo from "$lib/zhen/cv-comps/EposLogo.png";
import KhoraLogo from "$lib/zhen/cv-comps/KhoraLogo.jpg";
import GrazperAILogo from "$lib/zhen/cv-comps/GrazperLogo.jpg";
import YaaummaLogo from "$lib/zhen/cv-comps/YaaummaLogo.png";
import IconAndText from "./IconAndText.svelte";
</script>
<div class="container">
<div>
<b style="text-align:left;"> Experience </b>
</div>
<div class="table">
<div class="table-item">
<IconAndText logo={YaaummaLogo}>
<b>Full-stack</b><br />
Yaaumma<br />
<i>Feb 2025 - Now</i>
</IconAndText>
</div>
<div class="table-item">
<IconAndText logo={GrazperAILogo}>
<b>Data annotator</b><br />
GrazperAI<br />
<i>Jul 2024 - Now</i>
</IconAndText>
</div>
<div class="table-item">
<IconAndText logo={MakerspaceLogo}>
<b>3D printer manager</b> - Volunteer<br />
Makerspace - kildevæld Kulturcenter<br />
<i>Nov 2023 - Now</i>
</IconAndText>
</div>
<div class="table-item">
<IconAndText logo={EposLogo}>
<b>Machine Learning Engineer</b> - Short term intern<br />
Product design department - Epos<br />
<i>Apr 2024 - Apr 2024</i>
</IconAndText>
</div>
<div class="table-item">
<IconAndText logo={KhoraLogo}>
<b>Assistant</b> - Short term intern<br />
Khora Virtual Reality<br />
<i>Oct 2020 - Oct 2020</i>
</IconAndText>
</div>
</div>
</div>
<style lang="scss">
.container {
display: grid;
place-items: center;
width: 90%;
overflow: hidden;
& > div:first-child {
width: 100%;
/* Bottom border stripe*/
border-bottom: 1mm solid black;
}
}
.table-item {
padding: 2mm;
&:not(:last-child) {
border-bottom: 0.25mm solid #000000;
}
}
</style>

View file

@ -1,47 +0,0 @@
<script lang="ts">
export let logo: string;
export let logoWidths: string = "10%";
export let fontSize: string = "3mm";
export let lineHeight: string = "3.1mm";
import { onMount } from "svelte";
onMount(() => {
imageCaption = logo.split(/(\\|\/)/g).pop();
});
let imageCaption: undefined | string; // Not a high piority, you get the file name and thats it
</script>
<div class="container">
<img
src={logo}
class="bg-white w-10 h-10 object-contain"
alt={imageCaption}
width={logoWidths}
/>
<div style="line-height: {lineHeight};">
<span style="font-size: {fontSize};">
<slot />
</span>
</div>
</div>
<style lang="scss">
.container {
display: flex;
justify-items: start;
& > div {
padding-left: 3mm;
text-align: start;
}
& > img {
border-radius: 2.5mm;
filter: drop-shadow(1mm 1mm 1mm #0000009d);
}
}
</style>

View file

@ -1,46 +0,0 @@
<script lang="ts">
export let logo: string;
export let logoWidths: string = "35%";
export let fontSize: string = "3mm";
export let lineHeight: string = "3.1mm";
import { onMount } from "svelte";
onMount(() => {
imageCaption = logo.split(/(\\|\/)/g).pop();
});
let imageCaption: undefined | string; // Not a high piority, you get the file name and thats it
</script>
<div class="container flex">
<img
src={logo}
class="mr-2 w-6 h-6 object-contain"
alt={imageCaption}
width={logoWidths}
/>
<div style="line-height: {lineHeight};">
<span class="inline" style="font-size: {fontSize};">
<slot />
</span>
</div>
</div>
<style lang="scss">
.container {
width: 100%;
& > div {
text-align: start;
border-left: 0.5mm solid black;
}
& > img {
border-radius: 2.5mm;
filter: drop-shadow(1mm 1mm 1mm #0000009d);
}
}
</style>

View file

@ -1,53 +0,0 @@
<script>
import RepeatedSkills from "./RepeatedSkills.svelte";
export let Style = "";
</script>
<div class="container" style="{Style}">
<div>
<RepeatedSkills textOverride={["Hello", "你好", "Hej"]} targetTextHeight={4} targetTextWidth={50} applyRotation={false}/>
</div>
<div/>
</div>
<style lang="scss">
.container {
position: absolute;
transform: translate(-25mm, 0mm) rotate(-45deg);
display: grid;
justify-self: start;
vertical-align: top;
align-self: flex-start;
z-index: 0;
> div:nth-child(1) {
//background-color: #2f559622;
width: 100mm;
height: 17.5mm;
padding-bottom: 1mm;
// Text inside
display: grid;
place-content: center;
border-bottom: #4472c4 dotted 0.5mm;
&:first-child {
color: #4472c4;
font-size: 3mm;
//font-weight: bold;
}
}
> div:nth-child(2) {
padding-top: 4mm;
//border-bottom: #4472c4 dashed 2mm;
background-image: linear-gradient(to right, #4472c4 70%, rgba(255,255,255,0) 0%);
background-position: bottom;
background-size: 6mm 1.5mm;
background-repeat: repeat-x;
}
}
</style>

View file

@ -1,51 +0,0 @@
<script>
import svelteLogo from "$lib/svelteLogos/svelte-logo-cutout.svg"
</script>
<div class="container">
<div>
This CV was made using html, css and <a class="grid place-content-center" href="https://kit.svelte.dev/"><img src={svelteLogo} alt="SvelteKit logo"/></a>
Sources:
<a href="https://gitea.deprived.dev/Sveskejuice/deprived-main-website/src/branch/dev/src/routes/zhen/cv/rev2/+page.svelte">CV source code</a>
and
<a href="/zhen/cv/rev2?hideOnPrint=1">My Website</a>
</div>
</div>
<style lang="scss">
.container {
z-index: 1;
padding-left: 2mm;
font-size: 0.75rem;
//white-space: nowrap;
color: #777777;
* a {
color: #3d6ddc;
padding-left: 1mm;
padding-right: 1mm;
text-decoration: underline;
}
div:first-child {
display: flex;
place-content: center;
justify-content: start;
a:nth-child(1) > img {
width: 5mm;
padding-left: 1mm;
padding-right: 1mm;
}
}
div:nth-child(2){
padding-bottom: 2mm;
}
}
</style>

View file

@ -1,24 +0,0 @@
<script>
import QRCode from "$lib/zhen/cv-comps/LinkedInQrCode.svg?raw"
</script>
<div class="container">
<div>LinkedIn</div>
<span class="qrcode">{@html QRCode}</span>
</div>
<style lang="scss">
.qrcode {
transform: scale(0.9);
}
.container {
display: grid;
place-items: center;
& * {
font-size: 7.5mm;
}
}
</style>

View file

@ -1,26 +0,0 @@
<script lang="ts">
import NamePlate from "./NamePlate.svelte";
import selfie from "$lib/zhen/cv-comps/VRNerd.jpg"
import zylveterSus from "$lib/zhen/cv-comps/zylveterSus.png"
</script>
<div class="nameAndImageContainer">
<NamePlate/>
<div class="mt-4 w-48 h-48 overflow-hidden shadow-xl rounded-lg flex justify-center items-center">
<img src={selfie} class="selfie-constraints object-cover" alt="Zhentao Wei"/>
</div>
</div>
<style>
.nameAndImageContainer {
display: grid;
place-items: center;
}
.selfie-constraints{
max-width: 100%;
}
</style>

View file

@ -1,21 +0,0 @@
<div class="name-plate-container">
<span style="text-align: center;">
<b>
Zhentao Wei
</b><br/>
(He/Him)
</span>
</div>
<style>
.name-plate-container{
display: grid;
place-items: center;
width: 60%;
/* Bottom border stripe*/
border-bottom: 1mm solid black;
}
</style>

View file

@ -1,71 +0,0 @@
<div class="container">
<div>
<b style="text-align:left;">
Other
</b>
</div>
<div class="table-display">
<div class="table-item">
<div>Itch.io</div>
<a href="https://github.com/MagicBOTAlex">botalex.itch.io</a>
</div>
<div class="table-item">
<div>Github</div>
<a href="https://botalex.itch.io/">@MagicBOTAlex</a>
</div>
</div>
</div>
<style lang="scss">
.container{
display: grid;
place-items: center;
width: 70%;
}
.container > div:first-child {
width: 100%;
/* Bottom border stripe*/
border-bottom: 1mm solid black;
}
.table-display {
width: 100%;
}
.table-item {
display: flex;
justify-items: start;
width: 100%;
border-bottom: 0.25mm solid #000000;
> a {
text-decoration: underline;
}
> div, > a {
color: #000000;
&:first-child {
width: 35%;
font-size: 4mm;
display: grid;
place-content: center start;
border-right: rgba(128, 128, 128, 0.4) dashed 0.1mm;
}
&:nth-child(2) {
width: 65%;
font-size: 3.25mm;
display: grid;
place-content: center;
padding-left: 1mm;
}
}
}
</style>

View file

@ -1,31 +0,0 @@
<div class="short-profile-container">
<div>
<b style="text-align:left;">
About me
</b>
</div>
<div>
I'm a 20-year-old with a deep passion for programming and
technology.
Most of my knowledge is self-taught from many places on the
internet, so university hasn't helped much. I encourage you to browse my LinkedIn, since I
periodically post my hobby projects on there, and my skills are
described further in depth.
</div>
</div>
<style>
.short-profile-container{
display: grid;
place-items: center;
width: 90%;
}
.short-profile-container > div:first-child {
width: 100%;
/* Bottom border stripe*/
border-bottom: 1mm solid black;
}
</style>

View file

@ -1,62 +0,0 @@
<script lang="ts">
// Width of num chars and height nom of chars
export let targetTextWidth: number;
export let targetTextHeight: number;
export let applyRotation: boolean = true;
export let textOverride: string[] | undefined = undefined;
// Assign default value if textOverride is undefined
let repeatingText : string[] = textOverride ?? [
"C++",
"C#",
"ARDUINO",
"PYTHON",
"JAVA",
"JAVASCRIPT",
"TYPESCRIPT",
"HTML",
"CSS",
];
function getRandomInt(max: number) {
return Math.floor(Math.random() * max);
}
function GrabRandomString() {
let outString: string = "";
while (outString.length < targetTextWidth) {
outString +=
repeatingText[
getRandomInt(repeatingText.length)
] + " ";
}
return outString; // At about target size
}
</script>
<div {...$$restProps}>
{#each { length: targetTextHeight } as _, i}
<span class="{applyRotation ? "rotate45" : ""} SkillsText">
{GrabRandomString()}
</span>
{/each}
</div>
<style>
.SkillsText {
text-align: start;
display: flex;
justify-content: center;
align-items: center;
white-space: nowrap;
width: 2rem;
}
.rotate45 {
transform: rotate(-45deg);
}
</style>

View file

@ -1,28 +0,0 @@
<div class="short-profile-container">
<div>
<b style="text-align:left;">
Short profile
</b>
</div>
<div>
◾ "AI and data" at DTU. <br>
◾ Working at <a class="underline" href="https://grazper.com/">GrazperAI</a> <br/>
◾ Volunteer at Kildevæld Makerspace.
</div>
</div>
<style>
.short-profile-container{
display: grid;
place-items: center;
width: 70%;
}
.short-profile-container > div:first-child {
width: 100%;
/* Bottom border stripe*/
border-bottom: 1mm solid black;
}
</style>

View file

@ -1,88 +0,0 @@
<div class="container">
<div>
<b style="text-align:left;">
List of big projects
</b>
</div>
<div class="table-display">
<div class="table-item">
<div>Computer vision</div>
<div>Implimented YoloV1 from scratch. (object detection)</div>
</div>
<div class="table-item">
<div>Arduino</div>
<div>Built my own claw machine with 2 dimentions of movement</div>
</div>
<div class="table-item">
<div>App dev</div>
<div>Made an Doulingo'ish app for learning chinese in 9 days</div>
</div>
<div class="table-item">
<div>Open-source help</div>
<div>Contributed in multiple Open-source projects on github</div>
</div>
<div class="table-item">
<div>PCB designing</div>
<div>I am currently designing my own circuit board</div>
</div>
</div>
<div class="flex" style="font-size: 0.75rem; color: sgray; align-content: start; width: 100%;">
<p>
If you want proof or want to know about other projects. Contact me!
</p>
</div>
</div>
<style lang="scss">
.container{
display: grid;
place-items: center;
width: 90%;
}
.container > div:first-child {
width: 100%;
/* Bottom border stripe*/
border-bottom: 1mm solid black;
}
.table-display {
width: 100%;
}
.table-item {
display: flex;
justify-items: start;
width: 100%;
border-bottom: 0.25mm solid #000000;
> a {
text-decoration: underline;
}
> div, > a {
color: #000000;
&:first-child {
width: 30%;
font-size: 4mm;
display: grid;
place-content: center start;
border-right: rgba(128, 128, 128, 0.4) dashed 0.1mm;
}
&:nth-child(2) {
width: 70%;
font-size: 3.25mm;
display: grid;
padding-left: 1mm;
}
}
}
</style>

View file

@ -74,7 +74,7 @@
<LinkedInQR/> <LinkedInQR/>
</div> </div>
</div> </div>
<div id="leftSectionSeperator"></div> <div id="leftSectionSeperator"><div/></div>
<div id="right-section"> <div id="right-section">
<AlexWatermark/> <AlexWatermark/>
<div id="TopRightSkillsText"> <div id="TopRightSkillsText">

View file

@ -74,7 +74,7 @@
<LinkedInQR/> <LinkedInQR/>
</div> </div>
</div> </div>
<div id="leftSectionSeperator"></div> <div id="leftSectionSeperator"><div/></div>
<div id="right-section"> <div id="right-section">
<AlexWatermark/> <AlexWatermark/>
<div id="TopRightSkillsText"> <div id="TopRightSkillsText">

View file

@ -1,257 +1,243 @@
<script lang="ts"> <script lang="ts">
// Left side // Left side
import NameAndImage from "../CompsRev2/NameAndImage.svelte"; import NameAndImage from "../CompsRev2/NameAndImage.svelte";
import ShortProfile from "../CompsRev2/ShortProfile.svelte"; import ShortProfile from "../CompsRev2/ShortProfile.svelte"
import CombinedContacts from "../CompsRev2/CombinedContacts.svelte"; import CombinedContacts from "../CompsRev2/CombinedContacts.svelte"
import LinkedInQR from "../CompsRev2/LinkedInQR.svelte"; import LinkedInQR from "../CompsRev2/LinkedInQR.svelte";
// Right side // Right side
import Profile from "../CompsRev2/Profile.svelte"; import Profile from "../CompsRev2/Profile.svelte";
import Education from "../CompsRev2/Education.svelte"; import Education from "../CompsRev2/Education.svelte";
import Experience from "../CompsRev2/Experience.svelte"; import Experience from "../CompsRev2/Experience.svelte";
import BiggestFlex from "../CompsRev2/BiggestFlex.svelte"; import BiggestFlex from "../CompsRev2/BiggestFlex.svelte";
import TableOfProjects from "../CompsRev2/TableOfProjects.svelte"; import TableOfProjects from "../CompsRev2/TableOfProjects.svelte";
// Decorations // Decorations
import LeftTopDecor from "../CompsRev2/LeftTopDecor.svelte"; import LeftTopDecor from "../CompsRev2/LeftTopDecor.svelte";
import BottomRightDecor from "../CompsRev2/BottomRightDecor.svelte"; import BottomRightDecor from "../CompsRev2/BottomRightDecor.svelte";
import AlexWatermark from "../CompsRev2/AlexWatermark.svelte"; import AlexWatermark from "../CompsRev2/AlexWatermark.svelte";
import RepeatedSkills from "../CompsRev2/RepeatedSkills.svelte"; import RepeatedSkills from "../CompsRev2/RepeatedSkills.svelte";
// Cedit // Cedit
import LinkToSource from "../CompsRev2/LinkToSource.svelte"; import LinkToSource from "../CompsRev2/LinkToSource.svelte";
// Discord embed // Discord embed
import preveiwImage from "$lib/zhen/cv-comps/EposCvPreveiw.png"; import preveiwImage from "$lib/zhen/cv-comps/EposCvPreveiw.png"
// Print detection setup // Print detection setup
import { onMount } from "svelte"; import { onMount } from "svelte";
onMount(() => { onMount(() => {
// Check if the query parameter exists in the URL // Check if the query parameter exists in the URL
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
const hideOnPrintParam = urlParams.get("hideOnPrint"); const hideOnPrintParam = urlParams.get('hideOnPrint');
// If the query parameter is not detected, reload the page with the parameter added // If the query parameter is not detected, reload the page with the parameter added
if (!hideOnPrintParam) { if (!hideOnPrintParam) {
window.location.href = `${window.location.href}?hideOnPrint=1`; window.location.href = `${window.location.href}?hideOnPrint=1`;
}
});
function getFormattedDate(): string {
const date = new Date();
const day = String(date.getDate()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, '0');
const year = date.getFullYear();
return `${day}-${month}-${year}`;
} }
})
function getFormattedDate(): string {
const date = new Date();
const day = String(date.getDate()).padStart(2, "0");
const month = String(date.getMonth() + 1).padStart(2, "0");
const year = date.getFullYear();
return `${day}-${month}-${year}`;
}
</script> </script>
<title>Zhentao Wei's CV {getFormattedDate()}</title> <title>Zhentao Wei's CV {getFormattedDate()}</title>
<meta content="Zhentao Wei's CV" property="og:title" /> <meta content="Zhentao Wei's Epos CV" property="og:title" />
<meta <meta content="This CV is made completely with html + css + js" property="og:description" />
content="This CV is made completely with svelte + html + css + js"
property="og:description"
/>
<meta content={preveiwImage} property="og:image" /> <meta content={preveiwImage} property="og:image" />
<meta content="#bdd6ee" data-react-helmet="true" name="theme-color" /> <meta content="#bdd6ee" data-react-helmet="true" name="theme-color" />
<div class="cv-info-container hide-on-print"> <div class="cv-info-container hide-on-print">
<div> <div>
Under here is my CV rev1 for an application made entirely in HTML and CSS. Under here is my CV rev1 for an application made entirely in HTML and CSS. The page is designed to be saved as PDF.
The page is designed to be saved as PDF. This can be done by pressing <div This can be done by pressing <div class="keyboard-key">P</div> + <div class="keyboard-key">CTRL</div>, then set scaling to 100% and no margins. Lastly, select save to PDF or print.
class="keyboard-key" <br/>
> <br/>
P I have to sadly recommend chrome for this process. Firefox somehow messes with the quality of the PDF :(
</div> </div>
+
<div class="keyboard-key">CTRL</div>
, then set scaling to 100% and no margins. Lastly, select save to PDF or print.
<br />
<br />
I have to sadly recommend chrome for this process. Firefox somehow messes with
the quality of the PDF :(
</div>
</div> </div>
<div class="NotoSans cv-container-container include-in-print"> <div class="cv-container-container include-in-print">
<div class="cv-container sections decorations"> <div class="cv-container sections decorations">
<div id="left-section"> <div id="left-section">
<LeftTopDecor Style="pointer-events: none;" /> <LeftTopDecor Style="pointer-events: none;"/>
<BottomRightDecor Style="pointer-events: none;" /> <BottomRightDecor Style="pointer-events: none;"/>
<div> <div>
<NameAndImage /> <NameAndImage/>
<ShortProfile /> <ShortProfile/>
<CombinedContacts /> <CombinedContacts/>
<LinkedInQR /> <LinkedInQR/>
</div> </div>
</div>
<div id="leftSectionSeperator"><div/></div>
<div id="right-section">
<AlexWatermark Style="pointer-events: none;"/>
<div id="TopRightSkillsText">
<RepeatedSkills targetTextHeight={30} targetTextWidth={75}/>
</div>
<div id="Credit">
<LinkToSource/>
</div>
<div>
<Profile/>
<BiggestFlex/>
<TableOfProjects/>
<Experience/>
<Education/>
</div>
</div>
</div> </div>
<div id="leftSectionSeperator"></div>
<div id="right-section">
<AlexWatermark Style="pointer-events: none;" />
<div id="TopRightSkillsText">
<RepeatedSkills
class="Cozette"
targetTextHeight={30}
targetTextWidth={75}
/>
</div>
<div id="Credit">
<LinkToSource />
</div>
<div>
<Profile/>
<BiggestFlex />
<TableOfProjects />
<Experience />
<Education />
</div>
</div>
</div>
</div> </div>
<style lang="scss"> <style lang="scss">
.cv-info-container { .cv-info-container {
height: 40mm; height: 40mm;
background-color: #2b2a2a; background-color: #2b2a2a;
display: flex;
justify-content: center;
align-items: center;
.keyboard-key {
display: inline;
padding-left: 1mm;
padding-right: 1mm;
border-radius: 2mm;
background-color: #3e3d3d;
}
> div {
width: 80%;
height: 60%;
}
}
.cv-container-container {
width: 100%;
height: 100%;
display: grid;
place-items: center;
}
.cv-container-container * {
color: black; // Set all text black
}
.cv-container {
width: 210mm;
height: 297mm;
background-color: #eeeeee;
overflow: visible;
display: flex;
padding: auto;
}
.sections {
// Shared between sections
> div {
display: grid;
z-index: 0;
// Needed to cuttoff the extra decoration
position: relative;
overflow: hidden;
}
#left-section {
background-color: #bdd6ee;
width: calc(100% / 3 * 1);
> div:last-child {
z-index: 1;
width: 100%;
left: 0;
display: grid;
place-items: center;
padding-top: 30mm;
padding-bottom: 30mm;
}
}
#right-section {
width: calc(100% / 3 * 2);
> div:last-child {
z-index: 1;
width: 100%;
left: 0;
display: grid;
place-items: center;
row-gap: 6mm;
padding-top: 45mm;
padding-bottom: 30mm;
// Disable interactivity for padding
pointer-events: none;
}
}
}
.decorations {
#leftSectionSeperator {
position: relative;
height: 100%;
width: 0%;
z-index: 1;
overflow: visible;
> div {
position: absolute;
height: 100%;
width: 5mm;
z-index: 1;
background: linear-gradient(90deg, #3636364f, #00000000);
}
}
> div {
#TopRightSkillsText {
position: absolute;
z-index: 0;
display: grid;
place-items: center;
vertical-align: top;
width: 100%;
place-content: center;
padding: 0;
height: 50mm;
mask-image: linear-gradient(180deg, #000 0%, transparent 110%);
color: rgb(190, 190, 190);
font-family: "CozetteVector";
font-size: x-large;
}
#Credit {
position: absolute;
z-index: 0;
display: flex; display: flex;
align-self: flex-end; justify-content: center;
align-items: center;
.keyboard-key {
display: inline;
padding-left: 1mm;
padding-right: 1mm;
border-radius: 2mm;
background-color: #3e3d3d;
}
> div {
width: 80%;
height: 60%;
}
}
.cv-container-container{
width: 100%;
height: 100%;
display: grid;
place-items: center;
}
.cv-container-container * {
color: black; // Set all text black
}
.cv-container {
width: 210mm;
height: 297mm;
background-color: #eeeeee;
overflow: visible;
display: flex;
padding: auto;
}
.sections {
// Shared between sections
> div {
display: grid;
z-index: 0;
// Needed to cuttoff the extra decoration
position: relative;
overflow: hidden;
}
#left-section{
background-color: #bdd6ee;
width: calc(100% / 3 * 1);
> div:last-child {
z-index: 1;
width: 100%;
left: 0;
display: grid;
place-items: center;
padding-top: 30mm;
padding-bottom: 30mm;
}
}
#right-section{
width: calc(100% / 3 * 2);
> div:last-child {
z-index: 1;
width: 100%;
left: 0;
display: grid;
place-items: center;
row-gap: 6mm;
padding-top: 45mm;
padding-bottom: 30mm;
// Disable interactivity for padding
pointer-events:none;
}
}
}
.decorations {
#leftSectionSeperator{
position: relative;
height: 100%;
width: 0%;
z-index: 1;
overflow: visible;
> div {
position: absolute;
height: 100%;
width: 5mm;
z-index: 1;
background: linear-gradient(90deg, #3636364f, #00000000);
}
}
> div {
#TopRightSkillsText {
position: absolute;
z-index: 0;
display: grid;
place-items: center;
vertical-align: top;
width: 100%;
place-content: center;
padding: 0;
height: 50mm;
mask-image: linear-gradient(180deg, #000 0%, transparent 110%);
color: rgb(190, 190, 190);
font-family: 'CozetteVector';
font-size: x-large;
}
#Credit {
position: absolute;
z-index: 0;
display: flex;
align-self: flex-end;
}
} }
} }
}
</style> </style>

View file

@ -1,260 +0,0 @@
<script lang="ts">
// Left side
import NameAndImage from "../CompsRev3/NameAndImage.svelte";
import ShortProfile from "../CompsRev3/ShortProfile.svelte";
import CombinedContacts from "../CompsRev3/CombinedContacts.svelte";
import LinkedInQR from "../CompsRev3/LinkedInQR.svelte";
// Right side
import Profile from "../CompsRev3/Profile.svelte";
import Education from "../CompsRev3/Education.svelte";
import Experience from "../CompsRev3/Experience.svelte";
import BiggestFlex from "../CompsRev3/BiggestFlex.svelte";
import TableOfProjects from "../CompsRev3/TableOfProjects.svelte";
// Decorations
import LeftTopDecor from "../CompsRev3/LeftTopDecor.svelte";
import BottomRightDecor from "../CompsRev3/BottomRightDecor.svelte";
import AlexWatermark from "../CompsRev3/AlexWatermark.svelte";
import RepeatedSkills from "../CompsRev3/RepeatedSkills.svelte";
// Cedit
import LinkToSource from "../CompsRev3/LinkToSource.svelte";
// Discord embed
import preveiwImage from "$lib/zhen/cv-comps/EposCvPreveiw.png";
// Print detection setup
import { onMount } from "svelte";
onMount(() => {
// Check if the query parameter exists in the URL
const urlParams = new URLSearchParams(window.location.search);
const hideOnPrintParam = urlParams.get("hideOnPrint");
// If the query parameter is not detected, reload the page with the parameter added
if (!hideOnPrintParam) {
window.location.href = `${window.location.href}?hideOnPrint=1`;
}
});
function getFormattedDate(): string {
const date = new Date();
const day = String(date.getDate()).padStart(2, "0");
const month = String(date.getMonth() + 1).padStart(2, "0");
const year = date.getFullYear();
return `${day}-${month}-${year}`;
}
</script>
<title>Zhentao Wei's CV {getFormattedDate()}</title>
<meta content="Zhentao Wei's CV" property="og:title" />
<meta
content="This CV is made completely with svelte + html + css + js"
property="og:description"
/>
<meta content={preveiwImage} property="og:image" />
<meta content="#bdd6ee" data-react-helmet="true" name="theme-color" />
<div class="cv-info-container hide-on-print">
<div>
Under here is my CV rev1 for an application made entirely in HTML and CSS.
The page is designed to be saved as PDF. This can be done by pressing <div
class="keyboard-key"
>
P
</div>
+
<div class="keyboard-key">CTRL</div>
, then set scaling to 100% and no margins. Lastly, select save to PDF or print.
<br />
<br />
I have to sadly recommend chrome for this process. Firefox somehow messes with
the quality of the PDF :(
</div>
</div>
<div class="NotoSans cv-container-container include-in-print">
<div class="cv-container sections decorations">
<div id="left-section">
<LeftTopDecor Style="pointer-events: none;" />
<BottomRightDecor Style="pointer-events: none;" />
<div
class="absolute rotate-12 width-[10cm] h-full right-[15cm]"
style="background-color: #bdd6ee"
></div>
<div>
<NameAndImage />
<ShortProfile />
<CombinedContacts />
<LinkedInQR />
</div>
</div>
<div id="leftSectionSeperator"></div>
<div id="right-section">
<AlexWatermark Style="pointer-events: none;" />
<div id="TopRightSkillsText">
<RepeatedSkills
class="Cozette"
targetTextHeight={30}
targetTextWidth={75}
/>
</div>
<div id="Credit">
<LinkToSource />
</div>
<div>
<Profile />
<BiggestFlex />
<TableOfProjects />
<Experience />
<Education />
</div>
</div>
</div>
</div>
<style lang="scss">
.cv-info-container {
height: 40mm;
background-color: #2b2a2a;
display: flex;
justify-content: center;
align-items: center;
.keyboard-key {
display: inline;
padding-left: 1mm;
padding-right: 1mm;
border-radius: 2mm;
background-color: #3e3d3d;
}
> div {
width: 80%;
height: 60%;
}
}
.cv-container-container {
width: 100%;
height: 100%;
display: grid;
place-items: center;
}
.cv-container-container * {
color: black; // Set all text black
}
.cv-container {
width: 210mm;
height: 297mm;
background-color: #eeeeee;
overflow: visible;
display: flex;
padding: auto;
}
.sections {
// Shared between sections
> div {
display: grid;
z-index: 0;
// Needed to cuttoff the extra decoration
position: relative;
overflow: hidden;
}
#left-section {
background-color: #bdd6ee;
> div:last-child {
z-index: 1;
width: 100%;
left: 0;
display: grid;
place-items: center;
padding-top: 30mm;
padding-bottom: 30mm;
}
}
#right-section {
width: calc(100% / 3 * 2);
> div:last-child {
z-index: 1;
width: 100%;
left: 0;
display: grid;
place-items: center;
row-gap: 6mm;
padding-top: 45mm;
padding-bottom: 30mm;
// Disable interactivity for padding
// pointer-events: none;
}
}
}
.decorations {
#leftSectionSeperator {
position: relative;
height: 100%;
width: 0%;
z-index: 1;
overflow: visible;
> div {
position: absolute;
height: 100%;
width: 5mm;
z-index: 1;
background: linear-gradient(90deg, #3636364f, #00000000);
}
}
> div {
#TopRightSkillsText {
position: absolute;
z-index: 0;
display: grid;
place-items: center;
vertical-align: top;
width: 100%;
place-content: center;
padding: 0;
height: 50mm;
mask-image: linear-gradient(180deg, #000 0%, transparent 110%);
color: rgb(190, 190, 190);
font-family: "CozetteVector";
font-size: x-large;
}
#Credit {
position: absolute;
z-index: 0;
display: flex;
align-self: flex-end;
}
}
}
</style>

View file

@ -0,0 +1,117 @@
<script lang="ts">
import RepeatedSkills from "../../cv/Comps/RepeatedSkills.svelte";
// Discord embed
import preveiwImage from "$lib/zhen/cv-comps/EposCvPreveiw.png"
// Print detection setup
import { onMount } from "svelte";
onMount(() => {
// Check if the query parameter exists in the URL
const urlParams = new URLSearchParams(window.location.search);
const hideOnPrintParam = urlParams.get('hideOnPrint');
// If the query parameter is not detected, reload the page with the parameter added
if (!hideOnPrintParam) {
window.location.href = `${window.location.href}?hideOnPrint=1`;
}
});
function getFormattedDate(): string {
const date = new Date();
const day = String(date.getDate()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, '0');
const year = date.getFullYear();
return `${day}-${month}-${year}`;
}
</script>
<title>Zhentao Wei's LinkedIn banner {getFormattedDate()}</title>
<meta content="Zhentao Wei's LinkedIn banner" property="og:title" />
<meta content="This Linkedin banner is made completely with html + css + js" property="og:description" />
<meta content={preveiwImage} property="og:image" />
<meta content="#bdd6ee" data-react-helmet="true" name="theme-color" />
<div class="cv-info-container hide-on-print">
<div>
Under here is my Linkedin banner. This page has been able to be saved as PDF, and the banner can be extracted as an image fro mthe pdf.
This can be done by pressing <div class="keyboard-key">P</div> + <div class="keyboard-key">CTRL</div>, then set scaling to 100% and no margins. Lastly, select save to PDF or print.
<br/>
<br/>
I have to sadly recommend chrome for this process. Firefox somehow messes with the quality of the PDF :(
</div>
</div>
<div class="container include-in-print">
<div>
<RepeatedSkills targetTextHeight={70} targetTextWidth={175}/>
</div>
<div/>
</div>
<style lang="scss">
.cv-info-container {
height: 40mm;
background-color: #2b2a2a;
display: flex;
justify-content: center;
align-items: center;
.keyboard-key {
display: inline;
padding-left: 1mm;
padding-right: 1mm;
border-radius: 2mm;
background-color: #3e3d3d;
}
> div {
width: 80%;
height: 60%;
}
}
@media print {
.hide-on-print {
display: none;
}
}
.include-in-print { &, & * {
-webkit-print-color-adjust:exact !important;
print-color-adjust:exact !important;
}}
.container {
width: 100%;
height: 100%;
display: grid;
place-items: center;
> div:nth-child(1) {
width: 419.1mm;
height: 104.775mm;
background-color: #383636;
overflow: hidden;
display: grid;
place-content: center;
font-size: 10mm;
font-family: cozetteVector;
color: #d4d4d4;
filter: blur(0); // Force save as image
}
> div:nth-child(2){
height: 0;
}
}
</style>

View file

@ -0,0 +1,72 @@
<script lang="ts">
import A4 from "../sharedComps/A4.svelte";
</script>
<svelte:head>
<script>
MathJax = {
tex: {
inlineMath: [
["$", "$"],
["\\(", "\\)"],
],
},
};
</script>
<script
id="MathJax-script"
async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"
></script>
</svelte:head>
<div class="flex justify-center m-auto text-slate-900">
<div class="flex flex-col">
<A4>
<!-- <div>$$v_f = v_i + at$$</div>
<div>$$\Delta x = v_i t + \frac{1}{2} a t^2$$</div>
<div>$$v_f^2 = v_i^2 + 2a\Delta x$$</div>
<div>$$v_{\text{avg} = \frac{v_i + v_f}{2}$$</div>
<div>$$\Delta x = v_{\text{avg}} t$$</div> -->
<div class="overflow-x-auto">
<table class="table">
<!-- head -->
<thead>
<tr>
<th>Symbol</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>$v_i$</td>
<td>Initial velo</td>
</tr>
<tr>
<td>$v_f$</td>
<td>Final velo</td>
</tr>
<tr>
<td>$a$</td>
<td>Accel</td>
</tr>
<tr>
<td>$\Delta x$</td>
<td>The amount of change.</td>
</tr>
<tr>
<td>$t$</td>
<td>You're on your own on this one</td>
</tr>
</tbody>
</table>
</div>
</A4>
<A4>
{#each { length: 3 } as _, i}
<div>test {i}</div>
{/each}
</A4>
</div>
</div>

View file

@ -1,55 +0,0 @@
import os
import glob
from PIL import Image
from concurrent.futures import ProcessPoolExecutor, as_completed
# Directories
input_dir = 'spinning_cat'
output_dir = 'spinning_cat_cropped'
# Ensure output directory exists
def ensure_output_dir():
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Process a single image: crop transparent borders and save
def process_image(filepath):
try:
img = Image.open(filepath)
if img.mode != 'RGBA':
img = img.convert('RGBA')
alpha = img.split()[-1]
bbox = alpha.getbbox()
cropped = img.crop(bbox) if bbox else img
filename = os.path.basename(filepath)
out_path = os.path.join(output_dir, filename)
cropped.save(out_path)
return out_path, None
except Exception as e:
return filepath, e
# Main execution: parallel processing
def main():
ensure_output_dir()
pattern = os.path.join(input_dir, 'untitled_*.png')
files = sorted(glob.glob(pattern))
if not files:
print(f"No files found in '{input_dir}' with pattern 'untitled_*.png'.")
return
with ProcessPoolExecutor() as executor:
futures = {executor.submit(process_image, fp): fp for fp in files}
for future in as_completed(futures):
fp = futures[future]
out_path, error = future.result()
if error:
print(f"Error processing {fp}: {error}")
else:
print(f"Cropped and saved: {out_path}")
print("Processing complete.")
if __name__ == '__main__':
main()

Binary file not shown.

Before

(image error) Size: 116 KiB

Binary file not shown.

Before

(image error) Size: 396 KiB

Binary file not shown.

Before

(image error) Size: 396 KiB

Binary file not shown.

Before

(image error) Size: 398 KiB

Binary file not shown.

Before

(image error) Size: 397 KiB

Binary file not shown.

Before

(image error) Size: 397 KiB

Binary file not shown.

Before

(image error) Size: 397 KiB

Binary file not shown.

Before

(image error) Size: 399 KiB

Binary file not shown.

Before

(image error) Size: 402 KiB

Binary file not shown.

Before

(image error) Size: 402 KiB

Binary file not shown.

Before

(image error) Size: 402 KiB

Binary file not shown.

Before

(image error) Size: 402 KiB

Binary file not shown.

Before

(image error) Size: 402 KiB

Binary file not shown.

Before

(image error) Size: 403 KiB

Binary file not shown.

Before

(image error) Size: 403 KiB

Binary file not shown.

Before

(image error) Size: 403 KiB

Binary file not shown.

Before

(image error) Size: 403 KiB

Binary file not shown.

Before

(image error) Size: 403 KiB

Binary file not shown.

Before

(image error) Size: 403 KiB

Binary file not shown.

Before

(image error) Size: 403 KiB

Binary file not shown.

Before

(image error) Size: 402 KiB

Binary file not shown.

Before

(image error) Size: 402 KiB

Binary file not shown.

Before

(image error) Size: 402 KiB

Binary file not shown.

Before

(image error) Size: 402 KiB

Binary file not shown.

Before

(image error) Size: 403 KiB

Binary file not shown.

Before

(image error) Size: 402 KiB

Binary file not shown.

Before

(image error) Size: 401 KiB

Binary file not shown.

Before

(image error) Size: 400 KiB

Binary file not shown.

Before

(image error) Size: 401 KiB

Binary file not shown.

Before

(image error) Size: 401 KiB

Binary file not shown.

Before

(image error) Size: 400 KiB

Binary file not shown.

Before

(image error) Size: 400 KiB

Binary file not shown.

Before

(image error) Size: 400 KiB

Binary file not shown.

Before

(image error) Size: 401 KiB

Binary file not shown.

Before

(image error) Size: 401 KiB

Binary file not shown.

Before

(image error) Size: 401 KiB

Binary file not shown.

Before

(image error) Size: 400 KiB

Binary file not shown.

Before

(image error) Size: 403 KiB

Some files were not shown because too many files have changed in this diff Show more