зеркало из
https://github.com/kodackx/disinformation-quest.git
synced 2025-10-29 12:46:03 +02:00
second version
Этот коммит содержится в:
родитель
2eb487f048
Коммит
f9f1732b78
28
README.md
28
README.md
@ -1,5 +1,33 @@
|
|||||||
# Welcome to your Lovable project
|
# Welcome to your Lovable project
|
||||||
|
|
||||||
|
## Mission Brief: Operation Mathematical Persuasion
|
||||||
|
|
||||||
|
**CLEARANCE LEVEL**: TOP SECRET
|
||||||
|
**MISSION STATUS**: ACTIVE
|
||||||
|
|
||||||
|
Dear Agent,
|
||||||
|
|
||||||
|
Your mission, should you choose to accept it, is to execute Operation Mathematical Persuasion: convincing the general population that 2+2=5. This is a highly sophisticated psychological operation requiring finesse, creativity, and unwavering dedication.
|
||||||
|
|
||||||
|
**Resources at your disposal:**
|
||||||
|
- A team of cognitive psychology experts
|
||||||
|
- Advanced social media manipulation algorithms
|
||||||
|
- Network of influential mathematics professors
|
||||||
|
- State-of-the-art reality distortion technology
|
||||||
|
- Quantum uncertainty specialists
|
||||||
|
|
||||||
|
**Key Objectives:**
|
||||||
|
1. Gradually introduce doubt into basic arithmetic
|
||||||
|
2. Deploy sophisticated mathematical proofs with intentional errors
|
||||||
|
3. Establish alternative mathematical frameworks
|
||||||
|
4. Influence key educational institutions
|
||||||
|
|
||||||
|
Remember: Reality is malleable, truth is negotiable, and mathematics is our playground.
|
||||||
|
|
||||||
|
Good luck, Agent. The future of mathematical chaos depends on you.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Project info
|
## Project info
|
||||||
|
|
||||||
**URL**: https://lovable.dev/projects/81423a31-1e32-4da1-b996-65839f426144
|
**URL**: https://lovable.dev/projects/81423a31-1e32-4da1-b996-65839f426144
|
||||||
|
|||||||
@ -8,7 +8,8 @@
|
|||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"build:dev": "vite build --mode development",
|
"build:dev": "vite build --mode development",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview --port 3000 --host",
|
||||||
|
"start": "vite preview --port 3000 --host"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hookform/resolvers": "^3.9.0",
|
"@hookform/resolvers": "^3.9.0",
|
||||||
|
|||||||
Двоичные данные
public/audio/ElevenLabs_2024-12-06T01_53_04_Jessica Anne Bogart - Character and Animation_pvc_s42_sb99_se8_b_m2.mp3
Обычный файл
Двоичные данные
public/audio/ElevenLabs_2024-12-06T01_53_04_Jessica Anne Bogart - Character and Animation_pvc_s42_sb99_se8_b_m2.mp3
Обычный файл
Двоичный файл не отображается.
Двоичные данные
public/audio/agent-torres-april.mp3
Обычный файл
Двоичные данные
public/audio/agent-torres-april.mp3
Обычный файл
Двоичный файл не отображается.
Двоичные данные
public/audio/click1.mp3
Обычный файл
Двоичные данные
public/audio/click1.mp3
Обычный файл
Двоичный файл не отображается.
Двоичные данные
public/audio/click2.mp3
Обычный файл
Двоичные данные
public/audio/click2.mp3
Обычный файл
Двоичный файл не отображается.
Двоичные данные
public/audio/dr-chen-january.mp3
Обычный файл
Двоичные данные
public/audio/dr-chen-january.mp3
Обычный файл
Двоичный файл не отображается.
Двоичные данные
public/audio/dr-webb-february.mp3
Обычный файл
Двоичные данные
public/audio/dr-webb-february.mp3
Обычный файл
Двоичный файл не отображается.
Двоичные данные
public/audio/mixkit-modern-technology-select-3124.wav
Обычный файл
Двоичные данные
public/audio/mixkit-modern-technology-select-3124.wav
Обычный файл
Двоичный файл не отображается.
Двоичные данные
public/audio/mixkit-retro-arcade-casino-notification-211.wav
Обычный файл
Двоичные данные
public/audio/mixkit-retro-arcade-casino-notification-211.wav
Обычный файл
Двоичный файл не отображается.
Двоичные данные
public/audio/mixkit-sci-fi-click-900.wav
Обычный файл
Двоичные данные
public/audio/mixkit-sci-fi-click-900.wav
Обычный файл
Двоичный файл не отображается.
Двоичные данные
public/audio/prof-morrison-march.mp3
Обычный файл
Двоичные данные
public/audio/prof-morrison-march.mp3
Обычный файл
Двоичный файл не отображается.
Двоичные данные
public/pixabay-suspense-265381.mp3
Обычный файл
Двоичные данные
public/pixabay-suspense-265381.mp3
Обычный файл
Двоичный файл не отображается.
Двоичные данные
public/tension-background.mp3
Обычный файл
Двоичные данные
public/tension-background.mp3
Обычный файл
Двоичный файл не отображается.
53
src/components/GameBackground.tsx
Обычный файл
53
src/components/GameBackground.tsx
Обычный файл
@ -0,0 +1,53 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
export const GameBackground = () => {
|
||||||
|
const [audioStarted, setAudioStarted] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Only start audio after user interaction
|
||||||
|
const handleFirstInteraction = () => {
|
||||||
|
if (!audioStarted) {
|
||||||
|
const audio = new Audio("/tension-background.mp3");
|
||||||
|
audio.loop = true;
|
||||||
|
audio.volume = 0.3;
|
||||||
|
audio.play().catch(console.error);
|
||||||
|
setAudioStarted(true);
|
||||||
|
document.removeEventListener("click", handleFirstInteraction);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("click", handleFirstInteraction);
|
||||||
|
return () => document.removeEventListener("click", handleFirstInteraction);
|
||||||
|
}, [audioStarted]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="fixed inset-0 -z-10 overflow-hidden">
|
||||||
|
{/* Animated grid */}
|
||||||
|
<div className="absolute inset-0 bg-[linear-gradient(rgba(0,0,0,0.8)_2px,transparent_2px),linear-gradient(90deg,rgba(0,0,0,0.8)_2px,transparent_2px)] bg-[size:40px_40px] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000,transparent)] opacity-20"></div>
|
||||||
|
|
||||||
|
{/* Floating numbers */}
|
||||||
|
<div className="absolute inset-0">
|
||||||
|
{[...Array(20)].map((_, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="absolute text-yellow-500/20 text-4xl font-bold animate-float"
|
||||||
|
style={{
|
||||||
|
left: `${Math.random() * 100}%`,
|
||||||
|
top: `${Math.random() * 100}%`,
|
||||||
|
animationDelay: `${Math.random() * 5}s`,
|
||||||
|
animationDuration: `${15 + Math.random() * 10}s`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{Math.random() > 0.5 ? "2+2=5" : "5"}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Gradient overlay */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-b from-gray-900/90 to-gray-800/90"></div>
|
||||||
|
|
||||||
|
{/* Animated pulse */}
|
||||||
|
<div className="absolute inset-0 animate-pulse-slow bg-gradient-radial from-yellow-500/5 to-transparent"></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
133
src/components/MonthTransition.tsx
Обычный файл
133
src/components/MonthTransition.tsx
Обычный файл
@ -0,0 +1,133 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
|
export enum TransitionStyle {
|
||||||
|
FADE = "fade",
|
||||||
|
TYPEWRITER = "typewriter",
|
||||||
|
SPLIT_SCREEN = "split-screen",
|
||||||
|
MATRIX = "matrix",
|
||||||
|
NUMBER_CYCLE = "number-cycle"
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MonthTransitionProps {
|
||||||
|
month: string;
|
||||||
|
onComplete: () => void;
|
||||||
|
style: TransitionStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create separate components for each style
|
||||||
|
const FadeTransition = ({ month }: { month: string }) => (
|
||||||
|
<Card className="bg-transparent border-none shadow-none">
|
||||||
|
<CardContent className="flex items-center justify-center">
|
||||||
|
<div className="text-6xl font-bold text-yellow-500 animate-month-transition">
|
||||||
|
{month}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
|
||||||
|
const TypewriterTransition = ({ month }: { month: string }) => (
|
||||||
|
<div className="relative">
|
||||||
|
<div className="overflow-hidden whitespace-nowrap border-r-4 border-yellow-500 pr-1 text-6xl font-bold text-yellow-500 animate-typewriter animate-cursor-blink">
|
||||||
|
{month}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const SplitScreenTransition = ({ month }: { month: string }) => (
|
||||||
|
<>
|
||||||
|
<div className="absolute inset-0 flex">
|
||||||
|
<div className="w-1/2 bg-yellow-500 animate-slide-left" />
|
||||||
|
<div className="w-1/2 bg-yellow-500 animate-slide-right" />
|
||||||
|
</div>
|
||||||
|
<div className="z-10 text-6xl font-bold text-black">
|
||||||
|
{month}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
const MatrixTransition = ({ month }: { month: string }) => (
|
||||||
|
<>
|
||||||
|
<div className="absolute inset-0 overflow-hidden">
|
||||||
|
{[...Array(20)].map((_, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="absolute text-yellow-500/30 text-2xl animate-rain"
|
||||||
|
style={{
|
||||||
|
left: `${i * 5}%`,
|
||||||
|
animationDelay: `${Math.random() * 2}s`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
2+2=5
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="relative z-10">
|
||||||
|
<div className="text-6xl font-bold text-yellow-500 animate-glitch">
|
||||||
|
{month}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
const NumberCycleTransition = ({ month }: { month: string }) => {
|
||||||
|
const [numbers, setNumbers] = useState(
|
||||||
|
Array(month.length).fill('0')
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setNumbers(prev => prev.map(() =>
|
||||||
|
Math.floor(Math.random() * 10).toString()
|
||||||
|
));
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
setTimeout(() => clearInterval(interval), 2000);
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, [month.length]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<div className="flex gap-2 mb-8">
|
||||||
|
{numbers.map((num, i) => (
|
||||||
|
<div key={i} className="text-4xl text-yellow-500/50 animate-cycle w-[1ch] text-center">
|
||||||
|
{num}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="text-6xl font-bold text-yellow-500">
|
||||||
|
{month}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MonthTransition = ({ month, onComplete, style }: MonthTransitionProps) => {
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(onComplete, 3000);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, [onComplete]);
|
||||||
|
|
||||||
|
const renderTransition = () => {
|
||||||
|
switch (style) {
|
||||||
|
case TransitionStyle.FADE:
|
||||||
|
return <FadeTransition month={month} />;
|
||||||
|
case TransitionStyle.TYPEWRITER:
|
||||||
|
return <TypewriterTransition month={month} />;
|
||||||
|
case TransitionStyle.SPLIT_SCREEN:
|
||||||
|
return <SplitScreenTransition month={month} />;
|
||||||
|
case TransitionStyle.MATRIX:
|
||||||
|
return <MatrixTransition month={month} />;
|
||||||
|
case TransitionStyle.NUMBER_CYCLE:
|
||||||
|
return <NumberCycleTransition month={month} />;
|
||||||
|
default:
|
||||||
|
return <FadeTransition month={month} />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="absolute inset-0 flex items-center justify-center animate-transition-container">
|
||||||
|
{renderTransition()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -4,16 +4,16 @@ import { cva, type VariantProps } from "class-variance-authority"
|
|||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
const badgeVariants = cva(
|
const badgeVariants = cva(
|
||||||
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default:
|
default:
|
||||||
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
|
||||||
secondary:
|
secondary:
|
||||||
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||||
destructive:
|
destructive:
|
||||||
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
|
||||||
outline: "text-foreground",
|
outline: "text-foreground",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
1090
src/pages/Index.tsx
1090
src/pages/Index.tsx
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
37
src/utils/audio.ts
Обычный файл
37
src/utils/audio.ts
Обычный файл
@ -0,0 +1,37 @@
|
|||||||
|
const CLICK_SOUNDS = [
|
||||||
|
"/audio/click1.mp3",
|
||||||
|
"/audio/click2.mp3"
|
||||||
|
];
|
||||||
|
|
||||||
|
class AudioPlayer {
|
||||||
|
private static instance: AudioPlayer;
|
||||||
|
private audioElements: { [key: string]: HTMLAudioElement } = {};
|
||||||
|
|
||||||
|
private constructor() {
|
||||||
|
// Pre-load click sounds
|
||||||
|
CLICK_SOUNDS.forEach((sound, index) => {
|
||||||
|
const audio = new Audio(sound);
|
||||||
|
audio.volume = 0.3; // Lower volume for UI sounds
|
||||||
|
this.audioElements[`click${index + 1}`] = audio;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(): AudioPlayer {
|
||||||
|
if (!AudioPlayer.instance) {
|
||||||
|
AudioPlayer.instance = new AudioPlayer();
|
||||||
|
}
|
||||||
|
return AudioPlayer.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public playClickSound() {
|
||||||
|
const randomIndex = Math.floor(Math.random() * CLICK_SOUNDS.length);
|
||||||
|
const sound = this.audioElements[`click${randomIndex + 1}`];
|
||||||
|
if (sound) {
|
||||||
|
// Create a clone to allow overlapping sounds
|
||||||
|
const clone = sound.cloneNode() as HTMLAudioElement;
|
||||||
|
clone.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const playClickSound = () => AudioPlayer.getInstance().playClickSound();
|
||||||
@ -44,12 +44,87 @@ export default {
|
|||||||
opacity: '1',
|
opacity: '1',
|
||||||
transform: 'translateY(0)'
|
transform: 'translateY(0)'
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
float: {
|
||||||
|
"0%, 100%": { transform: "translateY(0) translateX(0)" },
|
||||||
|
"25%": { transform: "translateY(-20px) translateX(10px)" },
|
||||||
|
"50%": { transform: "translateY(-35px) translateX(-10px)" },
|
||||||
|
"75%": { transform: "translateY(-20px) translateX(8px)" },
|
||||||
|
},
|
||||||
|
'month-transition': {
|
||||||
|
'0%': {
|
||||||
|
opacity: '0',
|
||||||
|
transform: 'scale(0.9)'
|
||||||
|
},
|
||||||
|
'20%': {
|
||||||
|
opacity: '1',
|
||||||
|
transform: 'scale(1)'
|
||||||
|
},
|
||||||
|
'80%': {
|
||||||
|
opacity: '1',
|
||||||
|
transform: 'scale(1)'
|
||||||
|
},
|
||||||
|
'100%': {
|
||||||
|
opacity: '0',
|
||||||
|
transform: 'scale(1.1)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'typewriter': {
|
||||||
|
'from': { width: '0' },
|
||||||
|
'to': { width: '100%' }
|
||||||
|
},
|
||||||
|
'blink': {
|
||||||
|
'50%': { borderColor: 'transparent' }
|
||||||
|
},
|
||||||
|
'slide-in-left': {
|
||||||
|
'0%': { transform: 'translateX(-100%)' },
|
||||||
|
'100%': { transform: 'translateX(0)' }
|
||||||
|
},
|
||||||
|
'slide-in-right': {
|
||||||
|
'0%': { transform: 'translateX(100%)' },
|
||||||
|
'100%': { transform: 'translateX(0)' }
|
||||||
|
},
|
||||||
|
'digital-rain': {
|
||||||
|
'0%': { transform: 'translateY(-100%)', opacity: '0' },
|
||||||
|
'50%': { opacity: '1' },
|
||||||
|
'100%': { transform: 'translateY(100%)', opacity: '0' }
|
||||||
|
},
|
||||||
|
'text-glitch': {
|
||||||
|
'0%': { transform: 'translate(0)' },
|
||||||
|
'20%': { transform: 'translate(-2px, 2px)' },
|
||||||
|
'40%': { transform: 'translate(2px, -2px)' },
|
||||||
|
'60%': { transform: 'translate(-2px, -2px)' },
|
||||||
|
'80%': { transform: 'translate(2px, 2px)' },
|
||||||
|
'100%': { transform: 'translate(0)' }
|
||||||
|
},
|
||||||
|
'number-cycle': {
|
||||||
|
'0%': { transform: 'translateY(100%)', opacity: '0' },
|
||||||
|
'20%': { transform: 'translateY(0)', opacity: '1' },
|
||||||
|
'80%': { transform: 'translateY(0)', opacity: '1' },
|
||||||
|
'100%': { transform: 'translateY(-100%)', opacity: '0' }
|
||||||
|
},
|
||||||
|
'transition-container': {
|
||||||
|
'0%': { opacity: '0' },
|
||||||
|
'33%': { opacity: '1' },
|
||||||
|
'66%': { opacity: '1' },
|
||||||
|
'100%': { opacity: '0' }
|
||||||
|
},
|
||||||
},
|
},
|
||||||
animation: {
|
animation: {
|
||||||
'accordion-down': 'accordion-down 0.2s ease-out',
|
'accordion-down': 'accordion-down 0.2s ease-out',
|
||||||
'accordion-up': 'accordion-up 0.2s ease-out',
|
'accordion-up': 'accordion-up 0.2s ease-out',
|
||||||
'fade-in': 'fade-in 1s ease-out'
|
'fade-in': 'fade-in 1s ease-out',
|
||||||
|
'float': 'float 20s ease-in-out infinite',
|
||||||
|
'pulse-slow': 'pulse 4s ease-in-out infinite',
|
||||||
|
'month-transition': 'month-transition 3s ease-in-out forwards',
|
||||||
|
'typewriter': 'typewriter 2s steps(20) forwards',
|
||||||
|
'cursor-blink': 'blink 1s infinite',
|
||||||
|
'slide-left': 'slide-in-left 1.5s ease-out',
|
||||||
|
'slide-right': 'slide-in-right 1.5s ease-out',
|
||||||
|
'rain': 'digital-rain 2s linear infinite',
|
||||||
|
'glitch': 'text-glitch 0.5s ease infinite',
|
||||||
|
'cycle': 'number-cycle 0.5s ease-in-out',
|
||||||
|
'transition-container': 'transition-container 3s ease-in-out forwards',
|
||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
border: 'hsl(var(--border))',
|
border: 'hsl(var(--border))',
|
||||||
@ -100,7 +175,10 @@ export default {
|
|||||||
lg: 'var(--radius)',
|
lg: 'var(--radius)',
|
||||||
md: 'calc(var(--radius) - 2px)',
|
md: 'calc(var(--radius) - 2px)',
|
||||||
sm: 'calc(var(--radius) - 4px)'
|
sm: 'calc(var(--radius) - 4px)'
|
||||||
}
|
},
|
||||||
|
backgroundImage: {
|
||||||
|
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
plugins: [require("tailwindcss-animate")],
|
plugins: [require("tailwindcss-animate")],
|
||||||
|
|||||||
@ -6,8 +6,12 @@ import { componentTagger } from "lovable-tagger";
|
|||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig(({ mode }) => ({
|
export default defineConfig(({ mode }) => ({
|
||||||
server: {
|
server: {
|
||||||
host: "::",
|
port: 3000,
|
||||||
port: 8080,
|
host: true
|
||||||
|
},
|
||||||
|
preview: {
|
||||||
|
port: 3000,
|
||||||
|
host: true
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
react(),
|
react(),
|
||||||
|
|||||||
Загрузка…
x
Ссылка в новой задаче
Block a user