Compare commits

..

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

357 changed files with 3026 additions and 4903 deletions

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
unset NODE_ENV
git pull
git reset --hard main
echo "Rebuilding deprived main site"
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..."

View file

@ -10,12 +10,7 @@
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"paths": {
"@images/*": ["./src/images/*"],
"@src/*": ["./src/*"],
"@static/*": ["./static/*"]
}
"allowImportingTsExtensions": true
}
// 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",
"build": "vite build",
"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:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch --threshold error"
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/adapter-static": "^3.0.1",
"@sveltejs/kit": "^2.20.4",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@tailwindcss/typography": "^0.5.15",
"autoprefixer": "^10.4.20",
"daisyui": "^5.0.12",
"daisyui": "^4.12.12",
"postcss": "^8.4.47",
"sass": "^1.77.4",
"svelte": "^5.25.7",
"svelte-check": "^3.8.6",
"svelte": "^4.2.7",
"svelte-check": "^3.6.0",
"svelte-highlight": "^7.6.0",
"tailwindcss": "^4.1.3",
"tailwindcss": "^3.4.13",
"typescript": "^5.0.0",
"vite": "^5.0.3",
"vite-plugin-svgr": "^4.2.0"
},
"type": "module",
"dependencies": {
"@lucide/svelte": "^0.487.0",
"@tailwindcss/vite": "^4.1.3",
"lucide-svelte": "^0.475.0",
"svelte-katex": "^0.1.2",
"svelte-media-queries": "^1.6.2",
"svelte-parallax": "^0.6.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,5 +1,5 @@
<!doctype html>
<html lang="en" data-theme="Deprived" style="overflow-x: hidden;">
<html lang="en" data-theme="Synthwave" style="overflow-x: hidden;">
<head>
<meta charset="utf-8" />
<meta name="description" content="
@ -8,35 +8,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Change theme for site here -->
<link rel="stylesheet" href="/stylesheets/main-theme.css" />
<link rel="stylesheet" href="/stylesheets/global.css" />
%sveltekit.head%
<script>
let theme = null;
if (typeof localStorage !== 'undefined') {
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[randomNumber]);
}
//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>
<body style="display: contents">%sveltekit.body%</div>
</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"
viewBox="0 0 28 20"
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
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"

View file

@ -1,313 +1,296 @@
<!-- If url contains "hideOnPrint" param, then detect if start printing then hide elements -->
<script lang="ts">
import "../app.css";
import { fly } from "svelte/transition";
import MediaQuery from "svelte-media-queries";
import { Dices } from "@lucide/svelte";
let hideOnPrint: boolean = $state(false);
import "$lib/app.css";
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 HamburgerMenuIcon from "$lib/images/HamburgerMenuIcon.svelte";
import DeprivedLogo from "$lib/images/DeprivedLogo.svelte";
import HamburgerMenuIcon from "$lib/images/HamburgerMenuIcon.svelte";
const footerCollapseThreshold: string = "1000px";
const headerCollapseThreshold: string = "1000px";
let footerCollapse: boolean;
let isMobile: boolean = $state(false);
import svelteLogo from "$lib/svelteLogos/svelte-logo.png"
let navbarHidden: boolean = $state(true);
const footerCollapseThreshold : string = '1000px';
const headerCollapseThreshold : string = '1000px';
let footerCollapse : boolean;
let isMobile : boolean;
function resetNavBar() {
navbarHidden = true;
}
let navbarHidden : boolean = true;
import { afterNavigate } from "$app/navigation";
afterNavigate(() => {
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");
function resetNavBar() {
navbarHidden = true;
}
const themesArr = (window as any).AvailableThemes;
let nextTheme = "dark";
if (
theme == "null" ||
theme == "undefined" ||
theme == undefined ||
theme == null
) {
} else {
nextTheme = themesArr[(1 - -themesArr.indexOf(theme)) % themesArr.length];
}
import { afterNavigate } from '$app/navigation';
afterNavigate(() => {
const params = new URLSearchParams(window.location.search);
hideOnPrint = params.get('hideOnPrint') === '1';
//console.log(hideOnPrint);
});
console.log("Slecting: " + nextTheme);
document.documentElement.setAttribute("data-theme", nextTheme);
localStorage.setItem("theme", nextTheme);
}
import { onMount } from 'svelte';
import { themeChange } from 'theme-change'
onMount(() => {
const lock = document.createElement('meta');
lock.name = 'darkreader-lock';
document.head.appendChild(lock);
themeChange(false) // false parameter is required for svelte
});
</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 -->
<MediaQuery
query="(max-width: {footerCollapseThreshold})"
bind:matches={footerCollapse}
/>
<MediaQuery
query="(max-width: {headerCollapseThreshold})"
bind:matches={isMobile}
/>
<MediaQuery query='(max-width: {footerCollapseThreshold})' bind:matches={footerCollapse} />
<MediaQuery query='(max-width: {headerCollapseThreshold})' bind:matches={isMobile} />
<!-- Nav bar -->
<div class=" bg-base-200 p-0">
<header class="{hideOnPrint ? 'hide-on-print' : ''} bg-base-300">
<div class="nav-bar pr-4">
{#if !isMobile}
<div class="desktop">
<a 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" />
<div class="bg-base-200 p-0">
<header class="{hideOnPrint ? 'hide-on-print' : ''}">
<div class="nav-bar pr-4 bg-base-200">
{#if !isMobile}
<div class="desktop">
<a 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" />
<!-- <a href="/">Home</a> -->
<!-- <a href="/zhen/notes/physics/1?hideOnPrint=1" target="_blank" style="width: 7.5rem;">Notes</a> -->
{@render SwitchThemeButton()}
<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="/">Home</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>
<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> -->
</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>
{:else}
<div class="collapsed shadow-xl">
<a onclick={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" />
{@render SwitchThemeButton()}
<div class="px-1"></div>
<button
id="toggle-nav"
onclick={() => {
navbarHidden = !navbarHidden;
console.log(navbarHidden);
}}
>
<HamburgerMenuIcon Class="fill-base-content" />
</button>
</header>
<!-- Page content -->
<slot />
<!-- About footer -->
<footer class="{hideOnPrint ? 'hide-on-print' : ''}">
<div class="about-container">
<div class="credits">
<span>© 2023-2024</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>
<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>
{#if !navbarHidden}
<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 />
</footer>
</div>
{#if footerCollapse}
<style>
.about-container {
flex-direction: column;
justify-content: center !important;
gap: 25px;
<style lang="scss">
/* Nav bar. */
header {
display: flex;
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 isMobile}
<style>
</style>
<style>
</style>
{/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 { ButtonType } from '$lib/IO/ButtonType.ts';
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";
@ -34,28 +35,22 @@
const mobileThreshold : string = '600px'; // was 1000px. zhen testing
let mobile : boolean;
onMount(()=> {
let tabTittleElement = window.document.getElementById("TabTittle");
if (tabTittleElement) // Not null
tabTittleElement.innerHTML = "Deprived devs";
});
</script>
<!-- Detect 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 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="#bdd6ee" data-react-helmet="true" name="theme-color" />
<div class="pointer-events-auto" style="position: relative; width: 100%; height: 100%; overflow: hidden;">
<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;">
<h1 style="font-size: {!mobile ? 5 : 3}rem; text-shadow: 0.2rem 0.2rem 1rem rgba(0, 0, 0, 0.9);">
<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); z-index: 100;">
{#if !mobile}
Deprived Devs
{:else}
@ -72,67 +67,75 @@
</div>
</div>
<div class="cozette flex flex-col justify-center items-center w-full md:px-8 pt-4">
<h2 class="text-center" style="font-size: {!mobile ? 3 : 2}rem;">
Developers
</h2>
<div class="">
<div class="grid max-lg:grid-cols-1 sm:grid-cols-2 gap-4 p-4 max-lg:px-0 w-full">
<div class="flex justify-center w-full px-8 py-4">
<div class="grid space-y-5" style="width: 100%; max-width: 21cm;">
<h2 class="prose main-title" style="font-size: {!mobile ? 3 : 2}rem;">
Developers
</h2>
<Profile name="Zhen / Alex" tags={["Programmer", "3D artist", "UX Designer"]} isMobile={mobile}>
<span>
<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>
</span>
</Profile>
<Profile name="Sveske / Benjamin" tags={["Programmer", "Back-end Admin"]} isMobile={mobile}>
<span>
<p><span class="inline line-through">Hi, I use Arch, btw. </span> I use NixOS now</p>
<p><a href="https://www.linkedin.com/in/benjamin-dreyer/" target="_blank" style="color:lightblue;">Linked-in</a></p>
</span>
</Profile>
<Profile isSnorre={true} tags={["Programmer"]} isMobile={mobile}/>
<Profile name="Zhen / Alex" tags={["Programmer", "3D artist", "UX Designer"]} isMobile={mobile}>
<span>
<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>
</span>
</Profile>
<ProfileSpacer/>
<Profile name="Sveske / Benjamin" tags={["Programmer", "Back-end Admin"]} isMobile={mobile}>
<span>
<p>Hi, I use Arch, btw.</p>
<p><a href="https://www.linkedin.com/in/benjamin-dreyer/" target="_blank" style="color:lightblue;">Linked-in</a></p>
</span>
</Profile>
<ProfileSpacer/>
<Profile isSnorre={true} tags={["Programmer"]} isMobile={mobile}/>
<Profile name="Oliver" tags={["Sound/Story","2D Artist", "Programmer"]} isMobile={mobile}>
<span>
<p>Snorre does not get paid.</p>
<p><a href="https://www.linkedin.com/in/oliver-schwenger-291944278/" target="_blank" style="color:lightblue;">Linked-in</a></p>
</span>
</Profile>
<ProfileSpacer/>
<Profile name="Oliver" tags={["Sound designer", "Story designer","2D Artist", "Programmer"]} isMobile={mobile}>
<span>
<p>Snorre does not get paid.</p>
<p><a href="https://www.linkedin.com/in/oliver-schwenger-291944278/" target="_blank" style="color:lightblue;">Linked-in</a></p>
</span>
</Profile>
<Profile name="Kim" tags={["Cinemachine", "3D Artist", "Programmer"]} isMobile={mobile}>
<span>
<p>Abla espaniol</p>
<p><a href="https://www.linkedin.com/in/kim-rex-de-dios-408860299/" target="_blank" style="color:lightblue;">Linked-in</a></p>
</span>
</Profile>
<Profile name="Zylvester" tags={["Sound/Story", "2D/3D artist"]} isMobile={mobile}>
<span>
<p>Closeted omega weeb</p>
<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>
</span>
</Profile>
</div>
<ProfileSpacer/>
<Profile name="Kim" tags={["Cinemachine", "3D Artist", "Programmer"]} isMobile={mobile}>
<span>
<p>Abla espaniol</p>
<p><a href="https://www.linkedin.com/in/kim-rex-de-dios-408860299/" target="_blank" style="color:lightblue;">Linked-in</a></p>
</span>
</Profile>
<ProfileSpacer/>
<Profile name="Zylvester" tags={["2D/3D Artist", "Sound designer", "Story designer"]} isMobile={mobile}>
<span>
<p>Hi, I am [insert text here]</p>
<p>Here's a joke about recursion: <a href="/" target="_blank" style="color:lightblue;">recursion</a></p>
</span>
</Profile>
</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">
<!-- <article class="pt-16 prose overflow-hidden {mobile ? "px-8" : ""}">
<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" : ""}">
<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>
</article> -->
</article>
<!-- Spacer -->
<!-- <div style="width: 50%;" class="{!mobile ? "py-16" : "py-4"}">
<div style="width: 50%;" class="{!mobile ? "py-16" : "py-4"}">
<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>
<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>
@ -158,7 +161,7 @@
<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>
<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>
@ -180,7 +183,7 @@
<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>
<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>
@ -202,7 +205,7 @@
<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>
<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>
@ -210,9 +213,7 @@
<div class="games card bg-base-100 w-96 shadow-xl">
<figure class="rounded-b-none" style="height: 15em;">
<div class="bg-grid-100 flex w-full h-full"></div>
</figure>
<figure class="skeleton rounded-b-none" style="height: 15em;"></figure>
<div class="card-body">
<h2 class="card-title">What's next?</h2>
<div class="skeleton mt-1 h-4 w-28"></div>
@ -222,7 +223,7 @@
<div class="skeleton h-4 w-full"></div>
<div class="flex grow"/>
<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>
@ -231,6 +232,11 @@
<style>
.main-title {
width: 80%;
font-family: var(--title-font);
}
#backgroundGif{
width: 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>
<div class="bg-grid-100 border-2 border-base-100 pl-1 pr-4 rounded-md cozette max-lg:pb-2">
{#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}/>
<slot/>
<MobileTags tags={tags} isMobile={isMobile}/>
</div>
{: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">
<pre style="font-size: {!isMobile ? 1.5 : 1.5}rem;"> </pre>
<span>
@ -30,38 +29,35 @@
<pre> </pre>
{/if}
</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}/>
<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><a href="https://www.linkedin.com/in/snorrealtschul/" target="_blank" style="color:lightblue;">My website</a></p> -->
<p><a href="https://spoodythe.one/" target="_blank" style="color:lightblue;">My website</a></p>
<p>I'm the diversity hire. (Gay)</p>
<p><a href="https://www.linkedin.com/in/snorrealtschul/" target="_blank" style="color:lightblue;">Linked-in</a></p>
</span>
<MobileTags tags={tags} isMobile={isMobile}/>
</div>
</div>
{/if}
</div>
<style>
.developersProfile:not(.snorre):not(.snorre-overlay){
/* background-image: linear-gradient(var(--color-neutral) 33%, rgba(255,255,255,0) 0%); */
/* background-image: linear-gradient(var(--color-neutral) 100%);
background-image: linear-gradient(oklch(var(--p)) 33%, rgba(255,255,255,0) 0%);
background-position: left;
background-size: 0.1rem 0.5rem;
background-repeat: repeat-y; */
background-repeat: repeat-y;
}
.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-slice: 1; */
border-image-slice: 1;
}
.snorre-overlay {
/* background-image: linear-gradient(rgba(255,255,255,0) 0%, rgba(255,255,255,0) 40%, var(--color-base-200) 40%); */
/* background-position: left;
background-image: linear-gradient(rgba(255,255,255,0) 0%, rgba(255,255,255,0) 40%, oklch(var(--b1)) 40%);
background-position: left;
background-size: 0.1rem 0.5rem;
background-repeat: repeat-y; */
background-repeat: repeat-y;
}
</style>

View file

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

View file

@ -1,77 +1,38 @@
<script lang="ts">
export let Tags = ["null"];
export let Tags= ["null"];
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>
<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}
{@const key = tag.replaceAll(" ", "").toLowerCase()}
{@const color = colorManager.getColor(key)}
{#if key.indexOf("/") < 0}
<!-- Single Color Badge -->
<div class="badge2" style="background-color: {typeof color === 'string' ? color : '#ccc'};">
<span class="invert">
{tag}
</span>
</div>
{:else}
<div class="badge2 text-primary-content cozette" style="background-color: {colors[key] || "#ccc"};">{tag}</div>
{:else}
<!-- Gradient Badge -->
{#if typeof color === 'object' && color !== null}
{#if typeof colors[key] === 'object' && colors[key] !== null}
<div
class="badge2 cozette"
style="background: linear-gradient({color.rotation}, {color.color2} {color.offset}, {color.color1} {color.offset});">
<span class="invert">
{tag}
</span>
class="badge2 text-primary-content cozette"
style="background: linear-gradient({colors[key].rotation}, {colors[key].color2} {colors[key].offset}, {colors[key].color1} {colors[key].offset});">
{tag}
</div>
{:else}
<div class="badge2 cozette" style="background-color: #ccc;">
<span class="invert">
{tag}
</span>
<div
class="badge2 text-primary-content cozette"
style="background-color: #ccc;">
{tag}
</div>
{/if}
{/if}
@ -83,11 +44,12 @@
display: inline-flex;
align-items: center;
justify-content: center;
height: 1.25rem; /* 20px */
line-height: 1.25rem; /* 20px */
height: 1.25rem /* 20px */;
line-height: 1.25rem /* 20px */;
width: fit-content;
padding-left: 0.563rem; /* 9.008px */
padding-right: 0.563rem; /* 9.008px */
border-radius: var(--rounded-badge, 1.9rem); /* 30.4px */
padding-left: 0.563rem /* 9.008px */;
padding-right: 0.563rem /* 9.008px */;
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>
import A4 from "../zhen/notes/physics/sharedComps/A4.svelte";
import ToolButton from "./comps/ToolButton.svelte";
import { BatteryMedium } from '@lucide/svelte';
import { BatteryMedium } from 'lucide-svelte';
</script>
<div class="flex justify-center pt-10">
@ -11,7 +11,7 @@
class="cozette text-base-content 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"
>These are the tools collected from different places of the
internet</span
@ -28,19 +28,19 @@
title="Sleeping battery life"
desc="Calculates the battery life depending on sleep and non-sleep power usage."
btnText="To calculator"
toolIcon={BatteryMedium}
icon={BatteryMedium}
/>
<!-- <ToolButton
title="Sleeping battery life"
desc="Calculates the battery life depending on sleep and non-sleep power usage."
btnText="To calculator"
toolIcon={BatteryMedium}
icon={BatteryMedium}
/>
<ToolButton
title="Sleeping battery life"
desc="Calculates the battery life depending on sleep and non-sleep power usage."
btnText="To calculator"
toolIcon={BatteryMedium}
icon={BatteryMedium}
/> -->
</div>
</div>

View file

@ -1,18 +1,16 @@
<script lang="ts">
import A4 from "../../zhen/notes/physics/sharedComps/A4.svelte";
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 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>
<div class="flex justify-center pt-10">
@ -84,28 +82,21 @@
</div>
{#if !useCustom}
<div>
<select
bind:value={selectedText}
class="select select-sm select-bordered w-56 max-w-xs"
>
<option disabled value="">Select a text</option>
{#each options as option}
<option value={option}>{option}</option>
{/each}
</select>
<select
bind:value={selectedText}
class="select select-sm select-bordered w-56 max-w-xs"
>
<option disabled value="">Select a text</option>
{#each options as option}
<option value={option}>{option}</option>
{/each}
</select>
{#if selectedMcu != undefined && selectedMcu?.wifi != undefined}
<p class="mt-4 text-lg">
wifi
</p>
{/if}
{#if selectedMcu != undefined && selectedMcu?.wifi != undefined}
<p class="mt-4 text-lg">
ble
</p>
{/if}
</div>
{#if selectedText}
<p class="mt-4 text-lg">
You selected: {selectedText}
</p>
{/if}
{:else}
<div class="form-control">
<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 };
}
const MCUs: MCU_Type[] = [
export const MCUs: MCU_Type[] = [
{
name: "esp32-s3",
name: "ESP32-S3",
cpu: { // mili amps
single_core_40MHz: 21.8,
dual_core_40MHz: 24.4,
@ -33,13 +33,13 @@ const MCUs: MCU_Type[] = [
},
{
name: "esp32-c3",
name: "ESP32-C3",
cpu: {
single_core_80MHz: 22,
single_core_160MHz: 54.6,
active: 130,
sleep: 15
},
sleep: {
},
wifi: {
active: 110,
@ -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">
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 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="flex pt-4">
{#if toolIcon != undefined}
<svelte:component this={toolIcon}/>
{#if icon != undefined}
<svelte:component this={icon}/>
{/if}
<a href="{btnHref}" class="btn ml-auto btn-primary btn-sm">{btnText}</a>
</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>
</span>
</div>
<div style="flex-grow: 2;" />
<div style="flex-grow: 2;" />
</div>
<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

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

View file

@ -3,6 +3,7 @@
</script>
<div class="container" style="{Style}">
<div/>
<div>
<div>
Thank you! ❤

View file

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

View file

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

View file

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

View file

@ -1,254 +1,243 @@
<script lang="ts">
// Left side
import NameAndImage from "../CompsRev2/NameAndImage.svelte";
import ShortProfile from "../CompsRev2/ShortProfile.svelte";
import CombinedContacts from "../CompsRev2/CombinedContacts.svelte";
import LinkedInQR from "../CompsRev2/LinkedInQR.svelte";
// Left side
import NameAndImage from "../CompsRev2/NameAndImage.svelte";
import ShortProfile from "../CompsRev2/ShortProfile.svelte"
import CombinedContacts from "../CompsRev2/CombinedContacts.svelte"
import LinkedInQR from "../CompsRev2/LinkedInQR.svelte";
// Right side
import Profile from "../CompsRev2/Profile.svelte";
import Education from "../CompsRev2/Education.svelte";
import Experience from "../CompsRev2/Experience.svelte";
import BiggestFlex from "../CompsRev2/BiggestFlex.svelte";
import TableOfProjects from "../CompsRev2/TableOfProjects.svelte";
// Right side
import Profile from "../CompsRev2/Profile.svelte";
import Education from "../CompsRev2/Education.svelte";
import Experience from "../CompsRev2/Experience.svelte";
import BiggestFlex from "../CompsRev2/BiggestFlex.svelte";
import TableOfProjects from "../CompsRev2/TableOfProjects.svelte";
// Decorations
import LeftTopDecor from "../CompsRev2/LeftTopDecor.svelte";
import BottomRightDecor from "../CompsRev2/BottomRightDecor.svelte";
import AlexWatermark from "../CompsRev2/AlexWatermark.svelte";
import RepeatedSkills from "../CompsRev2/RepeatedSkills.svelte";
// Decorations
import LeftTopDecor from "../CompsRev2/LeftTopDecor.svelte";
import BottomRightDecor from "../CompsRev2/BottomRightDecor.svelte";
import AlexWatermark from "../CompsRev2/AlexWatermark.svelte";
import RepeatedSkills from "../CompsRev2/RepeatedSkills.svelte";
// Cedit
import LinkToSource from "../CompsRev2/LinkToSource.svelte";
// Cedit
import LinkToSource from "../CompsRev2/LinkToSource.svelte";
// Discord embed
import preveiwImage from "$lib/zhen/cv-comps/EposCvPreveiw.png"
// 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');
// 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`;
}
});
// 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}`;
}
});
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="Zhentao Wei's Epos CV" property="og:title" />
<meta content="This CV 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 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>
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 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="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>
<NameAndImage />
<ShortProfile />
<CombinedContacts />
<LinkedInQR />
</div>
<div class="cv-container sections decorations">
<div id="left-section">
<LeftTopDecor Style="pointer-events: none;"/>
<BottomRightDecor Style="pointer-events: none;"/>
<div>
<NameAndImage/>
<ShortProfile/>
<CombinedContacts/>
<LinkedInQR/>
</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 id="leftSectionSeperator"></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>
<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;
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;
.cv-info-container {
height: 40mm;
background-color: #2b2a2a;
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

@ -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

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 398 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

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