Create a new interactive playground for practicing rules of inference under Discrete Math > Foundations. The playground will feature a three-column layout for premises, a workspace with parallel lines for derivations, and a column for relevant inference rules. Users can drag and drop elements, apply rules, and receive validation for their steps. The initial example will be based on the provided screenshot.
114 lines
No EOL
5.7 KiB
TypeScript
114 lines
No EOL
5.7 KiB
TypeScript
import { useState } from "react";
|
||
import { Link } from "react-router-dom";
|
||
import { Search } from "lucide-react";
|
||
import Layout from "@/components/Layout";
|
||
import InteractiveCard from "@/components/InteractiveCard";
|
||
import BinaryNumberGame from "@/components/BinaryNumberGame";
|
||
import TernaryNumberGame from "@/components/TernaryNumberGame";
|
||
import BalancedTernaryGame from "@/components/BalancedTernaryGame";
|
||
import ZeckendorfGame from "@/components/ZeckendorfGame";
|
||
import ZeckendorfSearchTrick from "@/components/ZeckendorfSearchTrick";
|
||
import KnightsAndKnavesI from "@/components/KnightsAndKnavesI";
|
||
import RulesOfInferencePlayground from "@/components/RulesOfInferencePlayground";
|
||
interface Interactive {
|
||
id: string;
|
||
title: string;
|
||
description: string;
|
||
tags: string[];
|
||
component: React.ComponentType;
|
||
greenScreenPath: string;
|
||
}
|
||
const interactives: Interactive[] = [{
|
||
id: "binary-number-game",
|
||
title: "Binary Number Representation",
|
||
description: "Learn how numbers are represented in binary (base-2) format through an interactive guessing game.",
|
||
tags: ["binary", "numbers", "conversion", "representation"],
|
||
component: BinaryNumberGame,
|
||
greenScreenPath: "/binary-number-game"
|
||
}, {
|
||
id: "ternary-number-game",
|
||
title: "Ternary Number Representation",
|
||
description: "Learn how numbers are represented in ternary (base-3) format by toggling between 0, 1, or 2 copies of powers of three.",
|
||
tags: ["ternary", "numbers", "conversion", "representation", "base-3"],
|
||
component: TernaryNumberGame,
|
||
greenScreenPath: "/ternary-number-game"
|
||
}, {
|
||
id: "balanced-ternary-game",
|
||
title: "Balanced Ternary Representation",
|
||
description: "Explore balanced ternary using digits T (-1), 0, and 1. Add or subtract powers of three to match the target number.",
|
||
tags: ["balanced-ternary", "numbers", "conversion", "representation", "base-3", "signed-digits"],
|
||
component: BalancedTernaryGame,
|
||
greenScreenPath: "/balanced-ternary-game"
|
||
}, {
|
||
id: "zeckendorf-game",
|
||
title: "Zeckendorf Representation",
|
||
description: "Learn how numbers are represented using Fibonacci numbers with the unique Zeckendorf representation (no consecutive Fibonacci numbers).",
|
||
tags: ["fibonacci", "numbers", "representation", "zeckendorf", "combinatorics"],
|
||
component: ZeckendorfGame,
|
||
greenScreenPath: "/discrete-math/foundations/zeckendorf"
|
||
}, {
|
||
id: "knights-and-knaves-i",
|
||
title: "Knights and Knaves - I",
|
||
description: "Drag statements into the arena to test consistency of A’s claim and roles in a classic Knights & Knaves puzzle.",
|
||
tags: ["logic", "puzzle", "knights", "knaves", "truth-tellers"],
|
||
component: KnightsAndKnavesI,
|
||
greenScreenPath: "/themes/discrete-math/foundations"
|
||
}, {
|
||
id: "rules-of-inference",
|
||
title: "Rules of Inference Playground",
|
||
description: "Practice applying resolution and equivalence rules to derive conclusions step by step.",
|
||
tags: ["logic", "proofs", "inference", "resolution", "deduction"],
|
||
component: RulesOfInferencePlayground,
|
||
greenScreenPath: "/themes/discrete-math/foundations"
|
||
}];
|
||
const Foundations = () => {
|
||
const [searchTerm, setSearchTerm] = useState("");
|
||
const [selectedInteractive, setSelectedInteractive] = useState<Interactive | null>(null);
|
||
const filteredInteractives = interactives.filter(interactive => interactive.title.toLowerCase().includes(searchTerm.toLowerCase()) || interactive.description.toLowerCase().includes(searchTerm.toLowerCase()) || interactive.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase())));
|
||
if (selectedInteractive) {
|
||
const InteractiveComponent = selectedInteractive.component;
|
||
return <div className="min-h-screen bg-background p-6">
|
||
<div className="max-w-4xl mx-auto space-y-6">
|
||
<div className="flex items-center justify-between">
|
||
<button onClick={() => setSelectedInteractive(null)} className="text-primary hover:text-primary/80 font-medium">
|
||
← Back to Foundations
|
||
</button>
|
||
|
||
<Link to="/themes/discrete-math" className="text-primary hover:text-primary/80 font-medium">
|
||
Back to Discrete Math →
|
||
</Link>
|
||
</div>
|
||
<InteractiveComponent />
|
||
|
||
</div>
|
||
</div>;
|
||
}
|
||
return <Layout>
|
||
<div className="container mx-auto px-4 py-8">
|
||
<div className="space-y-8">
|
||
<div className="flex items-center gap-4">
|
||
<Link to="/themes/discrete-math" className="text-primary hover:text-primary/80 font-medium">
|
||
← Back to Discrete Math
|
||
</Link>
|
||
<h1 className="text-3xl font-bold text-foreground">Foundations</h1>
|
||
</div>
|
||
|
||
<div className="relative max-w-md">
|
||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground w-4 h-4" />
|
||
<input type="text" placeholder="Search interactives..." value={searchTerm} onChange={e => setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-outline rounded-md bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" />
|
||
</div>
|
||
|
||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||
{filteredInteractives.map(interactive => <InteractiveCard key={interactive.id} title={interactive.title} description={interactive.description} tags={interactive.tags} onClick={() => setSelectedInteractive(interactive)} />)}
|
||
</div>
|
||
|
||
{filteredInteractives.length === 0 && <div className="text-center py-12">
|
||
<p className="text-muted-foreground">
|
||
No interactives found matching "{searchTerm}"
|
||
</p>
|
||
</div>}
|
||
</div>
|
||
</div>
|
||
</Layout>;
|
||
};
|
||
export default Foundations; |