diff --git a/src/components/demonstrators/Demonstrator.tsx b/src/components/demonstrators/Demonstrator.tsx
new file mode 100644
index 0000000..4e704fc
--- /dev/null
+++ b/src/components/demonstrators/Demonstrator.tsx
@@ -0,0 +1,126 @@
+import {
+ Button,
+ FormControl,
+ FormLabel,
+ HStack,
+ Spinner,
+ Text,
+ Tooltip,
+ VStack,
+} from "@chakra-ui/react";
+import { useEffect, useState } from "react";
+import { getInvalidProblemDto } from "../../api/data-model/ProblemDto";
+import { ProblemState } from "../../api/data-model/ProblemState";
+import { SolverSetting } from "../../api/data-model/SolverSettings";
+import { fetchSolverSettings, postProblem } from "../../api/ToolboxAPI";
+import { settingComponentMap } from "../solvers/settings/SettingsView";
+
+export interface DemonstratorProps {
+ demonstratorId: string;
+ onSolved: (solution: string) => void;
+}
+
+enum DemonstratorState {
+ IDLE,
+ SOLVING,
+ SOLVED,
+}
+
+function getHumanReadableState(state: DemonstratorState) {
+ switch (state) {
+ case DemonstratorState.IDLE:
+ return "Go";
+ case DemonstratorState.SOLVING:
+ return (
+
+ Running
+
+
+ );
+ case DemonstratorState.SOLVED:
+ return "Run again";
+ }
+}
+
+const demonstratorTypeId = "demonstrator";
+
+export const Demonstrator = (props: DemonstratorProps) => {
+ const [settings, setSettings] = useState([]);
+ const [state, setState] = useState(DemonstratorState.IDLE);
+ const [error, setError] = useState("");
+
+ useEffect(() => {
+ fetchSolverSettings(demonstratorTypeId, props.demonstratorId).then(
+ setSettings
+ );
+ }, [props.demonstratorId]);
+
+ function updateSetting(newSetting: SolverSetting) {
+ const index = settings.findIndex(
+ (setting) => setting.name === newSetting.name
+ );
+ if (index !== -1) {
+ settings.splice(index, 1, newSetting);
+ }
+
+ setSettings([...settings]);
+ }
+
+ return (
+
+ {settings.map((setting) => {
+ const SettingComponent = settingComponentMap[setting.type];
+ return (
+
+
+ {setting.name}
+
+
+
+ );
+ })}
+
+
+
+ {error && {error}}
+
+ );
+};
diff --git a/src/components/landing-page/Card.tsx b/src/components/landing-page/Card.tsx
new file mode 100644
index 0000000..14d3229
--- /dev/null
+++ b/src/components/landing-page/Card.tsx
@@ -0,0 +1,65 @@
+import { Badge, Box, LinkBox, LinkOverlay } from "@chakra-ui/react";
+import NextLink from "next/link";
+
+export interface CardProps {
+ href: string;
+ new?: boolean;
+ tags?: string[];
+ title: string;
+ description: string;
+}
+
+export const Card = (props: CardProps & { refer: string }) => {
+ return (
+
+
+
+ {props.new && (
+
+ New!
+
+ )}
+
+ {props.tags &&
+ props.tags.map((tag) => (
+
+ {tag}
+
+ ))}
+
+
+
+
+
+ {props.title}
+
+
+
+ {props.description}
+
+
+ {props.refer} →
+
+
+
+ );
+};
diff --git a/src/components/landing-page/DemonstratorCard.tsx b/src/components/landing-page/DemonstratorCard.tsx
new file mode 100644
index 0000000..ecbbac7
--- /dev/null
+++ b/src/components/landing-page/DemonstratorCard.tsx
@@ -0,0 +1,5 @@
+import { Card, CardProps } from "./Card";
+
+export const DemonstratorCard = (props: CardProps) => {
+ return ;
+};
diff --git a/src/components/landing-page/DemonstratorChooser.tsx b/src/components/landing-page/DemonstratorChooser.tsx
new file mode 100644
index 0000000..ede48b3
--- /dev/null
+++ b/src/components/landing-page/DemonstratorChooser.tsx
@@ -0,0 +1,15 @@
+import { Grid, GridItem, GridProps } from "@chakra-ui/react";
+import { DemonstratorCard } from "./DemonstratorCard";
+
+export const DemonstratorChooser = (props: GridProps) => (
+
+
+
+
+
+);
diff --git a/src/components/landing-page/ProblemCard.tsx b/src/components/landing-page/ProblemCard.tsx
index 06da2e1..d262a75 100644
--- a/src/components/landing-page/ProblemCard.tsx
+++ b/src/components/landing-page/ProblemCard.tsx
@@ -1,64 +1,5 @@
-import { Badge, Box, LinkBox, LinkOverlay } from "@chakra-ui/react";
-import NextLink from "next/link";
+import { Card, CardProps } from "./Card";
-interface ProblemCardProps {
- href: string;
- new: boolean;
- tags: string[];
- problemName: string;
- description: string;
-}
-
-export const ProblemCard = (props: ProblemCardProps) => {
- return (
-
-
-
- {props.new && (
-
- New!
-
- )}
-
- {props.tags.map((tag) => (
-
- {tag}
-
- ))}
-
-
-
-
-
- {props.problemName}
-
-
-
- {props.description}
-
-
- Solve this problem →
-
-
-
- );
+export const ProblemCard = (props: CardProps) => {
+ return ;
};
diff --git a/src/components/landing-page/ProblemChooser.tsx b/src/components/landing-page/ProblemChooser.tsx
index 086f673..3f216d8 100644
--- a/src/components/landing-page/ProblemChooser.tsx
+++ b/src/components/landing-page/ProblemChooser.tsx
@@ -6,27 +6,24 @@ export const ProblemChooser = (props: GridProps) => (
@@ -35,7 +32,7 @@ export const ProblemChooser = (props: GridProps) => (
href="solve/QUBO"
new={true}
tags={["QAOA", "Annealing"]}
- problemName="QUBO"
+ title="QUBO"
description="For a quadratic term with binary decision variables, find the variable assignment minimizing the term."
/>
@@ -44,7 +41,7 @@ export const ProblemChooser = (props: GridProps) => (
href="solve/VehicleRouting"
new={true}
tags={["sub-routines", "QUBO", "Clustering"]}
- problemName="Vehicle Routing"
+ title="Vehicle Routing"
description="What is the optimal set of routes for a fleet of vehicles to traverse in order to deliver to a given set of customers?"
/>
@@ -53,7 +50,7 @@ export const ProblemChooser = (props: GridProps) => (
href="solve/TSP"
new={true}
tags={["sub-routines", "qubo"]}
- problemName="Traveling Salesperson Problem"
+ title="Traveling Salesperson Problem"
description="Given a list of cities and the distances between them, find the shortest possible route that visits each city exactly once and returns to the origin city."
/>
diff --git a/src/components/solvers/settings/SettingsView.tsx b/src/components/solvers/settings/SettingsView.tsx
index d577369..c3ab3a1 100644
--- a/src/components/solvers/settings/SettingsView.tsx
+++ b/src/components/solvers/settings/SettingsView.tsx
@@ -24,7 +24,7 @@ export interface Disabled {
export type OptionalSolverSetting = SolverSetting & Disabled;
-const settingComponentMap: {
+export const settingComponentMap: {
[key in SolverSettingType]: FC>;
} = {
[SolverSettingType.INTEGER]: IntegerSettingView,
diff --git a/src/pages/demonstrate/MixedIntegerProgramming.tsx b/src/pages/demonstrate/MixedIntegerProgramming.tsx
new file mode 100644
index 0000000..c9861aa
--- /dev/null
+++ b/src/pages/demonstrate/MixedIntegerProgramming.tsx
@@ -0,0 +1,35 @@
+import { Flex, Heading, Text } from "@chakra-ui/react";
+import { NextPage } from "next";
+import { useState } from "react";
+import { Demonstrator } from "../../components/demonstrators/Demonstrator";
+import { Layout } from "../../components/layout/Layout";
+
+const MixedIntegerProgramming: NextPage = () => {
+ const [svg, setSvg] = useState(null);
+
+ return (
+
+ Mixed Integer Programming Demonstrator
+
+ This demonstrator will provide a visual benchmark representation of the
+ Mixed Integer Programming (MIP) problem based on a variable number of
+ variables and repetitions. The MIP problem is a mathematical
+ optimization problem where some or all of the variables are restricted
+ to be integers.
+
+
+
+
+ {svg && (
+
+
+
+ )}
+
+ );
+};
+
+export default MixedIntegerProgramming;
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index 54368ba..d5b6986 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -1,7 +1,16 @@
-import { Heading, Link, Text } from "@chakra-ui/react";
+import {
+ Link,
+ Tab,
+ TabList,
+ TabPanel,
+ TabPanels,
+ Tabs,
+ Text,
+} from "@chakra-ui/react";
import type { NextPage } from "next";
import Head from "next/head";
import { baseUrl } from "../api/ToolboxAPI";
+import { DemonstratorChooser } from "../components/landing-page/DemonstratorChooser";
import { ProblemChooser } from "../components/landing-page/ProblemChooser";
import { Layout } from "../components/layout/Layout";
@@ -48,11 +57,24 @@ const Home: NextPage = () => {
-
- Solve a problem
-
-
-
+
+
+
+ Solve a problem
+
+
+ Demonstrators
+
+
+
+
+
+
+
+
+
+
+
);
};