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 + + + + + + + + + + + ); };