From 4128824028532ba249882df78605732b45770ac7 Mon Sep 17 00:00:00 2001 From: Max Schweikart Date: Wed, 28 Jun 2023 00:30:10 +0200 Subject: [PATCH] style: re-format with prettier --- .github/workflows/deploy-main.yml | 2 +- README.md | 10 +- .../dimacs/DimacsLogicalExpression.spec.ts | 169 ++++--- jest.config.js | 22 +- next.config.js | 6 +- src/api/ToolboxAPI.ts | 156 +++--- src/api/data-model/MetaSolverSettings.ts | 26 +- src/api/data-model/ProblemSolver.ts | 6 +- src/api/data-model/Solution.ts | 18 +- src/api/data-model/SolutionStatus.ts | 8 +- src/api/data-model/SolveRequest.ts | 30 +- src/api/data-model/SubRoutineDefinition.ts | 8 +- src/components/landing-page/ProblemCard.tsx | 2 +- src/components/solvers/FileInput.tsx | 31 +- src/components/solvers/Graph/GraphArea.tsx | 174 ++++--- src/components/solvers/ProgressHandler.tsx | 149 +++--- src/components/solvers/SAT/Help.tsx | 8 +- src/components/solvers/SAT/TextArea.tsx | 41 +- src/components/solvers/SAT/prism-SAT.ts | 46 +- src/components/solvers/SettingsView.tsx | 282 ++++++----- src/components/solvers/SolutionView.tsx | 129 +++-- src/components/solvers/SolverPicker.tsx | 227 +++++---- src/components/solvers/SolverTitle.tsx | 14 +- src/components/solvers/TextInputMask.tsx | 91 ++-- src/components/solvers/buttons/GoButton.tsx | 17 +- src/components/solvers/buttons/HelpButton.tsx | 83 +-- .../solvers/buttons/InputButton.tsx | 25 +- .../solvers/buttons/InputButtonPanel.tsx | 99 ++-- src/converter/dimacs/DimacsParser.ts | 298 ++++++----- .../dimacs/LogicalExpressionParser.ts | 471 ++++++++++-------- src/converter/dimacs/Syntax/CommonSyntax.ts | 46 +- src/converter/dimacs/Syntax/DimacsSyntax.ts | 24 +- .../dimacs/Syntax/LogicalExpressionSyntax.ts | 28 +- src/converter/graph/gml/GmlParser.js | 131 +++-- src/pages/index.tsx | 93 ++-- src/pages/solve/FeatureModelAnomaly.tsx | 71 +-- src/pages/solve/MaxCut.tsx | 60 ++- src/pages/solve/SAT.tsx | 76 +-- 38 files changed, 1721 insertions(+), 1456 deletions(-) diff --git a/.github/workflows/deploy-main.yml b/.github/workflows/deploy-main.yml index e3308b9..7d5cbd8 100644 --- a/.github/workflows/deploy-main.yml +++ b/.github/workflows/deploy-main.yml @@ -1,5 +1,5 @@ # adapted from https://github.com/dokku/github-action/blob/db5e3b84461e5e73c56d8b0f6a67aab0df25256c/example-workflows/simple.yml -name: 'deploy-main' +name: "deploy-main" on: push: diff --git a/README.md b/README.md index c361e92..05da28e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # ProvideQ -This repository contains the web frontend for the ProvideQ toolbox. + +This repository contains the web frontend for the ProvideQ toolbox. ## Development setup + 1. Install [Node.js 16](https://nodejs.org/) (check with `node -v`) 2. Make sure that the [Yarn package manager is enabled](https://yarnpkg.com/getting-started/install) (check with `yarn -v`) 3. Clone this repository @@ -10,9 +12,10 @@ This repository contains the web frontend for the ProvideQ toolbox. By default, Next.js will collect [anonymous telemetry data](https://nextjs.org/telemetry). You can disable the data collection using `yarn exec next telemetry disable`. -5. Use `yarn dev` to spin up a local development server +6. Use `yarn dev` to spin up a local development server ## Releasing a new version + 1. Create a release branch from develop: `git checkout -b release/x.y.z`. 2. Bump the version number in the `package.json` file to the new version number and commit it to the release branch. @@ -25,11 +28,12 @@ This repository contains the web frontend for the ProvideQ toolbox. 6. Merge the PR into main. 7. [Create a new GitHub release](https://github.com/ProvideQ/toolbox-web/releases/new) with a new tag named like your version number `x.y.z` and use the changelog as the description. -9. Pull the main branch (`git checkout main && git pull`), merge it into the +8. Pull the main branch (`git checkout main && git pull`), merge it into the develop branch (`git checkout develop && git pull && git merge main`) and push it (`git push`). ## License + Copyright (c) 2022 - 2023 ProvideQ This project is available under the [MIT License](./LICENSE) diff --git a/__tests__/converter/dimacs/DimacsLogicalExpression.spec.ts b/__tests__/converter/dimacs/DimacsLogicalExpression.spec.ts index f9e8e90..d4d2506 100644 --- a/__tests__/converter/dimacs/DimacsLogicalExpression.spec.ts +++ b/__tests__/converter/dimacs/DimacsLogicalExpression.spec.ts @@ -6,92 +6,99 @@ import { LogicalExpressionParser } from "../../../src/converter/dimacs/LogicalEx import { regexNOT } from "../../../src/converter/dimacs/Syntax/LogicalExpressionSyntax"; function isEquivalentLogicalExpression(f1: string, f2: string) { - expect(f1.replace(regexNOT, '!') - .replace(regexBlank, '')) - .toBe(f2.replace(regexNOT, '!') - .replace(regexBlank, '')); + expect(f1.replace(regexNOT, "!").replace(regexBlank, "")).toBe( + f2.replace(regexNOT, "!").replace(regexBlank, "") + ); } function isEquivalentDimacs(f1: string, f2: string) { - expect(f1.replace(regexComment, '') - .replace(regexBlank, '')) - .toBe(f2.replace(regexComment, '') - .replace(regexBlank, '')); + expect(f1.replace(regexComment, "").replace(regexBlank, "")).toBe( + f2.replace(regexComment, "").replace(regexBlank, "") + ); } describe("Parsing", () => { - let dimacsParser = new DimacsParser(); - let logicalExpressionParser = new LogicalExpressionParser(); + let dimacsParser = new DimacsParser(); + let logicalExpressionParser = new LogicalExpressionParser(); - each([ - [ - '((1 or 2 or not 3) and (!4 and (not 5 and 6)) and 3 and (7 or 2))', - 'c First comment\nc Some Comment\nc 1 => 1\np sat 7\n*(+( 1 2 -3 )*( -4 *( -5 6 )) 3 +( 7 2 ))' - ], - [ - '(1 or (2 and 3) or (((1 and 4) or 5) and 6))', - 'p sat 6\n+(1 *(2 3)*(+(*(1 4) 5) 6))' - ], - [ - '(((1 and not 2 and 3 and 4) or 3) and 5)', - 'c Sample DIMACS .sat file\np sat 5\n*(+(*(1 -2 3 4) 3) 5)' - ], - [ - '((1 and not 2) or 3)', - 'p sat 3\n+(*(1 -2) 3)' - ], - [ - '((1 and 2) or not 3)', - 'p sat 3\n+(*(1 2) -3)' - ] - ]).test("parsing bi-directional", (logicalExpression: string, dimacs: string) => { - isEquivalentDimacs(logicalExpressionParser.parseDimacs(logicalExpression), dimacs); - isEquivalentLogicalExpression(dimacsParser.parseLogicalExpression(dimacs), logicalExpression); - }); + each([ + [ + "((1 or 2 or not 3) and (!4 and (not 5 and 6)) and 3 and (7 or 2))", + "c First comment\nc Some Comment\nc 1 => 1\np sat 7\n*(+( 1 2 -3 )*( -4 *( -5 6 )) 3 +( 7 2 ))", + ], + [ + "(1 or (2 and 3) or (((1 and 4) or 5) and 6))", + "p sat 6\n+(1 *(2 3)*(+(*(1 4) 5) 6))", + ], + [ + "(((1 and not 2 and 3 and 4) or 3) and 5)", + "c Sample DIMACS .sat file\np sat 5\n*(+(*(1 -2 3 4) 3) 5)", + ], + ["((1 and not 2) or 3)", "p sat 3\n+(*(1 -2) 3)"], + ["((1 and 2) or not 3)", "p sat 3\n+(*(1 2) -3)"], + ]).test( + "parsing bi-directional", + (logicalExpression: string, dimacs: string) => { + isEquivalentDimacs( + logicalExpressionParser.parseDimacs(logicalExpression), + dimacs + ); + isEquivalentLogicalExpression( + dimacsParser.parseLogicalExpression(dimacs), + logicalExpression + ); + } + ); - each([ - [ - '((a or b or not c) and (not x and (not y and z)) and c and (d or c))', - 'c 1 => a\n' + - 'c 2 => b\n' + - 'c 3 => c\n' + - 'c 4 => x\n' + - 'c 5 => y\n' + - 'c 6 => z\n' + - 'c 7 => d\n' + - 'p sat 7\n' + - '*(+(1 2 -3) *(-4 *(-5 6)) 3 +(7 3))' - ], - [ - '(c or (a and b) or (((c and d) or e ) and f))', - 'c 1 => c\n' + - 'c 2 => a\n' + - 'c 3 => b\n' + - 'c 4 => d\n' + - 'c 5 => e\n' + - 'c 6 => f\n' + - 'p sat 6\n' + - '+(1 *(2 3)*(+(*(1 4) 5) 6))' - ], - [ - '(((a and not d and c and b) or c) and e)', - 'c 1 => a\n' + - 'c 2 => d\n' + - 'c 3 => c\n' + - 'c 4 => b\n' + - 'c 5 => e\n' + - 'p sat 5\n' + - '*(+(*(1 -2 3 4) 3) 5)' - ], - [ - '((a and not b) or c)', - 'c 1 => a\n' + - 'c 2 => b\n' + - 'c 3 => c\n' + - 'p sat 3\n' + - '+(*(1 -2) 3)' - ] - ]).test("parsing dimacs with variable aliases", (logicalExpression: string, dimacs: string) => { - isEquivalentLogicalExpression(dimacsParser.parseLogicalExpression(dimacs), logicalExpression); - }); -}); \ No newline at end of file + each([ + [ + "((a or b or not c) and (not x and (not y and z)) and c and (d or c))", + "c 1 => a\n" + + "c 2 => b\n" + + "c 3 => c\n" + + "c 4 => x\n" + + "c 5 => y\n" + + "c 6 => z\n" + + "c 7 => d\n" + + "p sat 7\n" + + "*(+(1 2 -3) *(-4 *(-5 6)) 3 +(7 3))", + ], + [ + "(c or (a and b) or (((c and d) or e ) and f))", + "c 1 => c\n" + + "c 2 => a\n" + + "c 3 => b\n" + + "c 4 => d\n" + + "c 5 => e\n" + + "c 6 => f\n" + + "p sat 6\n" + + "+(1 *(2 3)*(+(*(1 4) 5) 6))", + ], + [ + "(((a and not d and c and b) or c) and e)", + "c 1 => a\n" + + "c 2 => d\n" + + "c 3 => c\n" + + "c 4 => b\n" + + "c 5 => e\n" + + "p sat 5\n" + + "*(+(*(1 -2 3 4) 3) 5)", + ], + [ + "((a and not b) or c)", + "c 1 => a\n" + + "c 2 => b\n" + + "c 3 => c\n" + + "p sat 3\n" + + "+(*(1 -2) 3)", + ], + ]).test( + "parsing dimacs with variable aliases", + (logicalExpression: string, dimacs: string) => { + isEquivalentLogicalExpression( + dimacsParser.parseLogicalExpression(dimacs), + logicalExpression + ); + } + ); +}); diff --git a/jest.config.js b/jest.config.js index e3459a7..95ed9bd 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,20 +1,20 @@ // jest.config.js -const nextJest = require('next/jest') +const nextJest = require("next/jest"); const createJestConfig = nextJest({ - // Provide the path to your Next.js app to load next.config.js and .env files in your test environment - dir: './', -}) + // Provide the path to your Next.js app to load next.config.js and .env files in your test environment + dir: "./", +}); // Add any custom config to be passed to Jest /** @type {import('jest').Config} */ const customJestConfig = { - // Add more setup options before each test is run - // setupFilesAfterEnv: ['/jest.setup.js'], - // if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work - moduleDirectories: ['node_modules', '/'], - testEnvironment: 'jest-environment-jsdom', -} + // Add more setup options before each test is run + // setupFilesAfterEnv: ['/jest.setup.js'], + // if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work + moduleDirectories: ["node_modules", "/"], + testEnvironment: "jest-environment-jsdom", +}; // createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async -module.exports = createJestConfig(customJestConfig) +module.exports = createJestConfig(customJestConfig); diff --git a/next.config.js b/next.config.js index e674786..3d3bc99 100644 --- a/next.config.js +++ b/next.config.js @@ -1,7 +1,7 @@ /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, - swcMinify: true -} + swcMinify: true, +}; -module.exports = nextConfig +module.exports = nextConfig; diff --git a/src/api/ToolboxAPI.ts b/src/api/ToolboxAPI.ts index d4875ad..2510e0e 100644 --- a/src/api/ToolboxAPI.ts +++ b/src/api/ToolboxAPI.ts @@ -5,79 +5,97 @@ import { Solution } from "./data-model/Solution"; import { SolutionStatus } from "./data-model/SolutionStatus"; import { SolveRequest } from "./data-model/SolveRequest"; -export async function postProblem(problemUrlFragment: string, solveRequest: SolveRequest): Promise { - return fetch( - `${process.env.NEXT_PUBLIC_API_BASE_URL}/solve/${problemUrlFragment}`, - { - method: "POST", - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(solveRequest) - }) - .then(response => response.json()) - .then(json => json as Solution) - .catch(reason => { - return { - id: -1, - status: SolutionStatus.INVALID, - solverName: "", - executionMilliseconds: 0, - solutionData: "", - debugData: "", - metaData: "", - error: `${reason}`, - } - }); +export async function postProblem( + problemUrlFragment: string, + solveRequest: SolveRequest +): Promise { + return fetch( + `${process.env.NEXT_PUBLIC_API_BASE_URL}/solve/${problemUrlFragment}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(solveRequest), + } + ) + .then((response) => response.json()) + .then((json) => json as Solution) + .catch((reason) => { + return { + id: -1, + status: SolutionStatus.INVALID, + solverName: "", + executionMilliseconds: 0, + solutionData: "", + debugData: "", + metaData: "", + error: `${reason}`, + }; + }); } -export async function fetchSolvers(problemUrlFragment: string): Promise { - return fetch( - `${process.env.NEXT_PUBLIC_API_BASE_URL}/solvers/${problemUrlFragment}`, - { - method: "GET", - headers: { - 'Content-Type': 'application/json' - }, - }) - .then(response => response.json()) - .then(json => json as ProblemSolver[]) - .catch(reason => { - console.error(reason) - alert(`Could not retrieve solvers of type ${problemUrlFragment}.`) - return [] - }); +export async function fetchSolvers( + problemUrlFragment: string +): Promise { + return fetch( + `${process.env.NEXT_PUBLIC_API_BASE_URL}/solvers/${problemUrlFragment}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ) + .then((response) => response.json()) + .then((json) => json as ProblemSolver[]) + .catch((reason) => { + console.error(reason); + alert(`Could not retrieve solvers of type ${problemUrlFragment}.`); + return []; + }); } -export async function fetchSubRoutines(problemUrlFragment: string, solverId: string): Promise { - return fetch( - `${process.env.NEXT_PUBLIC_API_BASE_URL}/sub-routines/${problemUrlFragment}?${new URLSearchParams({ id: solverId })}`, - { - method: "GET", - headers: { - 'Content-Type': 'application/json' - }, - }) - .then(response => response.json()) - .catch(reason => { - console.error(reason) - alert(`Could not retrieve subroutines of solver ${solverId}.`) - return [] - }); +export async function fetchSubRoutines( + problemUrlFragment: string, + solverId: string +): Promise { + return fetch( + `${ + process.env.NEXT_PUBLIC_API_BASE_URL + }/sub-routines/${problemUrlFragment}?${new URLSearchParams({ + id: solverId, + })}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ) + .then((response) => response.json()) + .catch((reason) => { + console.error(reason); + alert(`Could not retrieve subroutines of solver ${solverId}.`); + return []; + }); } -export async function fetchMetaSolverSettings(problemUrl: string): Promise { - return fetch( - `${process.env.NEXT_PUBLIC_API_BASE_URL}/meta-solver/settings/${problemUrl}`, - { - method: "GET", - headers: { - 'Content-Type': 'application/json' - }, - }) - .then(response => response.json()) - .catch(reason => { - console.log(reason) - return [] - }); +export async function fetchMetaSolverSettings( + problemUrl: string +): Promise { + return fetch( + `${process.env.NEXT_PUBLIC_API_BASE_URL}/meta-solver/settings/${problemUrl}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ) + .then((response) => response.json()) + .catch((reason) => { + console.log(reason); + return []; + }); } diff --git a/src/api/data-model/MetaSolverSettings.ts b/src/api/data-model/MetaSolverSettings.ts index b9397bb..f2471a9 100644 --- a/src/api/data-model/MetaSolverSettings.ts +++ b/src/api/data-model/MetaSolverSettings.ts @@ -1,30 +1,30 @@ export enum MetaSolverSettingType { - RANGE = "RANGE", - CHECKBOX = "CHECKBOX", - TEXT = "TEXT", - SELECT = "SELECT", + RANGE = "RANGE", + CHECKBOX = "CHECKBOX", + TEXT = "TEXT", + SELECT = "SELECT", } export interface MetaSolverSetting { - name: string; - type: MetaSolverSettingType; + name: string; + type: MetaSolverSettingType; } export interface RangeSetting extends MetaSolverSetting { - min: number; - max: number; - value: number; + min: number; + max: number; + value: number; } export interface CheckboxSetting extends MetaSolverSetting { - state: boolean; + state: boolean; } export interface TextSetting extends MetaSolverSetting { - text: string; + text: string; } export interface SelectSetting extends MetaSolverSetting { - options: string[]; - selectedOption: string; + options: string[]; + selectedOption: string; } diff --git a/src/api/data-model/ProblemSolver.ts b/src/api/data-model/ProblemSolver.ts index 3f9b2e1..c682924 100644 --- a/src/api/data-model/ProblemSolver.ts +++ b/src/api/data-model/ProblemSolver.ts @@ -1,4 +1,4 @@ export interface ProblemSolver { - id: string, - name: string; -} \ No newline at end of file + id: string; + name: string; +} diff --git a/src/api/data-model/Solution.ts b/src/api/data-model/Solution.ts index 748c6d9..a6277e0 100644 --- a/src/api/data-model/Solution.ts +++ b/src/api/data-model/Solution.ts @@ -1,12 +1,12 @@ import { SolutionStatus } from "./SolutionStatus"; export interface Solution { - id: number; - status: SolutionStatus; - solverName: string; - executionMilliseconds: number; - solutionData: string; - metaData: string; - debugData: string; - error: string; -} \ No newline at end of file + id: number; + status: SolutionStatus; + solverName: string; + executionMilliseconds: number; + solutionData: string; + metaData: string; + debugData: string; + error: string; +} diff --git a/src/api/data-model/SolutionStatus.ts b/src/api/data-model/SolutionStatus.ts index 3741ce2..8f65e4f 100644 --- a/src/api/data-model/SolutionStatus.ts +++ b/src/api/data-model/SolutionStatus.ts @@ -1,5 +1,5 @@ export enum SolutionStatus { - INVALID, - COMPUTING, - SOLVED -} \ No newline at end of file + INVALID, + COMPUTING, + SOLVED, +} diff --git a/src/api/data-model/SolveRequest.ts b/src/api/data-model/SolveRequest.ts index ffb30d7..4ee9075 100644 --- a/src/api/data-model/SolveRequest.ts +++ b/src/api/data-model/SolveRequest.ts @@ -1,24 +1,24 @@ import { MetaSolverSetting } from "./MetaSolverSettings"; export interface SolverChoice { - /** - * If no solver id is provided, the toolbox choose the solver itself via meta solver strategy - */ - requestedSolverId?: string, - /** - * If no solver id is provided, the toolbox choose the solver itself via meta solver strategy - */ - requestedMetaSolverSettings?: MetaSolverSetting[], - /** - * Map from problem type to SubSolveRequest to allow explicitly requested solvers for a subroutine - */ - requestedSubSolveRequests: SolveMap + /** + * If no solver id is provided, the toolbox choose the solver itself via meta solver strategy + */ + requestedSolverId?: string; + /** + * If no solver id is provided, the toolbox choose the solver itself via meta solver strategy + */ + requestedMetaSolverSettings?: MetaSolverSetting[]; + /** + * Map from problem type to SubSolveRequest to allow explicitly requested solvers for a subroutine + */ + requestedSubSolveRequests: SolveMap; } export interface SolveRequest extends SolverChoice { - requestContent: T; + requestContent: T; } export type SolveMap = { - [key: string]: SolverChoice -} \ No newline at end of file + [key: string]: SolverChoice; +}; diff --git a/src/api/data-model/SubRoutineDefinition.ts b/src/api/data-model/SubRoutineDefinition.ts index 74ffb84..7e7d86a 100644 --- a/src/api/data-model/SubRoutineDefinition.ts +++ b/src/api/data-model/SubRoutineDefinition.ts @@ -1,5 +1,5 @@ export interface SubRoutineDefinition { - type: string, - url: string, - description: string, -} \ No newline at end of file + type: string; + url: string; + description: string; +} diff --git a/src/components/landing-page/ProblemCard.tsx b/src/components/landing-page/ProblemCard.tsx index 4cdba2b..ec6a53b 100644 --- a/src/components/landing-page/ProblemCard.tsx +++ b/src/components/landing-page/ProblemCard.tsx @@ -1,5 +1,5 @@ import { LinkBox, LinkOverlay, Box, Image, Badge } from "@chakra-ui/react"; -import NextLink from 'next/link'; +import NextLink from "next/link"; interface ProblemCardProps { href: string; diff --git a/src/components/solvers/FileInput.tsx b/src/components/solvers/FileInput.tsx index b181762..15b8b87 100644 --- a/src/components/solvers/FileInput.tsx +++ b/src/components/solvers/FileInput.tsx @@ -1,18 +1,21 @@ import React from "react"; -export async function chooseFile(multiple?: boolean, accept?: string): Promise { - const input = document.createElement('input'); - input.accept = accept || ""; - input.multiple = multiple || false; - input.hidden = true; - input.style.all = "display: none"; - input.type = "file"; - document.body.appendChild(input); +export async function chooseFile( + multiple?: boolean, + accept?: string +): Promise { + const input = document.createElement("input"); + input.accept = accept || ""; + input.multiple = multiple || false; + input.hidden = true; + input.style.all = "display: none"; + input.type = "file"; + document.body.appendChild(input); - return new Promise((resolve, reject) => { - input.addEventListener("change", e => { - resolve(input.files); - }); - input.click(); + return new Promise((resolve, reject) => { + input.addEventListener("change", (e) => { + resolve(input.files); }); -} \ No newline at end of file + input.click(); + }); +} diff --git a/src/components/solvers/Graph/GraphArea.tsx b/src/components/solvers/Graph/GraphArea.tsx index f6c48b8..63adbae 100644 --- a/src/components/solvers/Graph/GraphArea.tsx +++ b/src/components/solvers/Graph/GraphArea.tsx @@ -1,99 +1,109 @@ import { Box, Center, Container, Select, Spacer } from "@chakra-ui/react"; import React, { useEffect, useRef, useState } from "react"; -import G6, { Graph, GraphData } from '@antv/g6'; +import G6, { Graph, GraphData } from "@antv/g6"; interface GraphAreaProps { - graphData: GraphData; + graphData: GraphData; - graphHeight: number; - graphWidth: number; + graphHeight: number; + graphWidth: number; } export const GraphArea = (props: GraphAreaProps) => { - const graphTypes = [ - "random", - "force", - "circular", - "radial", - "mds", - "dagre", - "concentric", - "grid", - ] + const graphTypes = [ + "random", + "force", + "circular", + "radial", + "mds", + "dagre", + "concentric", + "grid", + ]; - const graphRef = useRef(null); - const [graph, setGraph] = useState(null); - const [graphDirected, setGraphDirected] = useState(false); + const graphRef = useRef(null); + const [graph, setGraph] = useState(null); + const [graphDirected, setGraphDirected] = useState(false); - useEffect(() => { - if (!graph && graphRef.current && graphRef.current.children.length == 0) { - setGraph(new G6.Graph({ - container: graphRef.current, - width: 500, - height: 500, - modes: { - default: ["drag-canvas", "zoom-canvas", "drag-node"], + useEffect(() => { + if (!graph && graphRef.current && graphRef.current.children.length == 0) { + setGraph( + new G6.Graph({ + container: graphRef.current, + width: 500, + height: 500, + modes: { + default: ["drag-canvas", "zoom-canvas", "drag-node"], + }, + defaultEdge: { + style: { + startArrow: true, + endArrow: true, + }, + }, + }) + ); + } - }, - defaultEdge: { - style: { - startArrow: true, - endArrow: true - } - } - })); - } - - if (graph && props.graphData) { - graph.data(props.graphData); - graph.render(); - updateGraphDirected(props.graphData.directed == "1" ?? false); - } + if (graph && props.graphData) { + graph.data(props.graphData); + graph.render(); + updateGraphDirected(props.graphData.directed == "1" ?? false); + } - function updateGraphDirected(directed: boolean) { - if (!graph || graphDirected == directed) return; - setGraphDirected(directed); + function updateGraphDirected(directed: boolean) { + if (!graph || graphDirected == directed) return; + setGraphDirected(directed); - if (directed) { - for (let edge of graph.getEdges()) { - graph.update(edge, { - style: { - startArrow: false, - endArrow: true - } - }) - } - } else { - for (let edge of graph.getEdges()) { - graph.update(edge, { - style: { - startArrow: true, - endArrow: true - } - }) - } - } + if (directed) { + for (let edge of graph.getEdges()) { + graph.update(edge, { + style: { + startArrow: false, + endArrow: true, + }, + }); + } + } else { + for (let edge of graph.getEdges()) { + graph.update(edge, { + style: { + startArrow: true, + endArrow: true, + }, + }); } - }, [graph, graphDirected, props.graphData]); + } + } + }, [graph, graphDirected, props.graphData]); - return ( - - + return ( + + - + -
- -
-
- ); -}; \ No newline at end of file +
+ +
+
+ ); +}; diff --git a/src/components/solvers/ProgressHandler.tsx b/src/components/solvers/ProgressHandler.tsx index 8345d0c..ee408e9 100644 --- a/src/components/solvers/ProgressHandler.tsx +++ b/src/components/solvers/ProgressHandler.tsx @@ -9,80 +9,93 @@ import { SolveRequest } from "../../api/data-model/SolveRequest"; import { SolverPicker } from "./SolverPicker"; export interface ProgressHandlerProps { - /** - * List of url fragments that are used for problem solve request to the toolbox. - */ - explicitSolvers?: string[]; - /** - * Url to retrieve solver candidates. - * Also used for sending the problem solve request to the toolbox unless explicitSolvers is set, - * in which case this is used to send problem solve request. - */ - problemUrlFragment: string; - problemInput: T; + /** + * List of url fragments that are used for problem solve request to the toolbox. + */ + explicitSolvers?: string[]; + /** + * Url to retrieve solver candidates. + * Also used for sending the problem solve request to the toolbox unless explicitSolvers is set, + * in which case this is used to send problem solve request. + */ + problemUrlFragment: string; + problemInput: T; } -export const ProgressHandler = (props: ProgressHandlerProps) => { - const [wasClicked, setClicked] = useState(false); - const [finished, setFinished] = useState(false); - const [solutions, setSolutions] = useState(); - const [solveRequest, setSolveRequest] = useState>({ - requestContent: props.problemInput, - requestedSubSolveRequests: {} - }); +export const ProgressHandler = ( + props: ProgressHandlerProps +) => { + const [wasClicked, setClicked] = useState(false); + const [finished, setFinished] = useState(false); + const [solutions, setSolutions] = useState(); + const [solveRequest, setSolveRequest] = useState>({ + requestContent: props.problemInput, + requestedSubSolveRequests: {}, + }); - async function startSolving() { - setClicked(true); - setFinished(false); + async function startSolving() { + setClicked(true); + setFinished(false); - let newSolveRequest : SolveRequest = { - ...solveRequest, - requestContent: props.problemInput - } + let newSolveRequest: SolveRequest = { + ...solveRequest, + requestContent: props.problemInput, + }; - setSolveRequest(newSolveRequest); - if (props.explicitSolvers == undefined) { - postProblem(props.problemUrlFragment, newSolveRequest) - .then(solution => { - setSolutions([solution]); - setFinished(true); - }); - } else { - Promise.all(props.explicitSolvers.map(s => postProblem(s, newSolveRequest))) - .then(solutions => { - setSolutions(solutions); - setFinished(true); - }); + setSolveRequest(newSolveRequest); + if (props.explicitSolvers == undefined) { + postProblem(props.problemUrlFragment, newSolveRequest).then( + (solution) => { + setSolutions([solution]); + setFinished(true); } + ); + } else { + Promise.all( + props.explicitSolvers.map((s) => postProblem(s, newSolveRequest)) + ).then((solutions) => { + setSolutions(solutions); + setFinished(true); + }); } + } - return ( - - {!wasClicked || finished - ? ( - -
- -
- { - setSolveRequest({ - ...solveRequest, - requestedSolverId: solverChoice.requestedSolverId, - requestedSubSolveRequests: solverChoice.requestedSubSolveRequests - }); - }}/> -
- ) - : null} + return ( + + {!wasClicked || finished ? ( + +
+ +
+ { + setSolveRequest({ + ...solveRequest, + requestedSolverId: solverChoice.requestedSolverId, + requestedSubSolveRequests: + solverChoice.requestedSubSolveRequests, + }); + }} + /> +
+ ) : null} - {wasClicked - ? solutions?.map(s => ( - - - ) - ) - : null} -
- ); -} + {wasClicked + ? solutions?.map((s) => ( + + + + )) + : null} +
+ ); +}; diff --git a/src/components/solvers/SAT/Help.tsx b/src/components/solvers/SAT/Help.tsx index dd0ebeb..2097989 100644 --- a/src/components/solvers/SAT/Help.tsx +++ b/src/components/solvers/SAT/Help.tsx @@ -1,7 +1,7 @@ import { Text } from "@chakra-ui/react"; export const Help = () => { - return ( - there is no help where you are going //TODO: add help body that actually helps - ); -} \ No newline at end of file + return ( + there is no help where you are going //TODO: add help body that actually helps + ); +}; diff --git a/src/components/solvers/SAT/TextArea.tsx b/src/components/solvers/SAT/TextArea.tsx index c51189d..e9d3be9 100644 --- a/src/components/solvers/SAT/TextArea.tsx +++ b/src/components/solvers/SAT/TextArea.tsx @@ -1,29 +1,28 @@ -import 'prismjs/themes/prism-solarizedlight.css' //TODO: use custom styling +import "prismjs/themes/prism-solarizedlight.css"; //TODO: use custom styling import React from "react"; import Editor from "react-simple-code-editor"; -import { highlight } from 'prismjs'; +import { highlight } from "prismjs"; import { Container } from "@chakra-ui/react"; -import { SAT_language } from "./prism-SAT" - +import { SAT_language } from "./prism-SAT"; interface TextAreaProps { - problemString: string; - setProblemString: React.Dispatch>; + problemString: string; + setProblemString: React.Dispatch>; } export const TextArea = (props: TextAreaProps) => { - return ( - - props.setProblemString(code)} - highlight={code => highlight(code, SAT_language, "SAT_language")} - padding={10} - style={{ - fontFamily: '"Fira code", "Fira Mono", monospace', - fontSize: 24 - }} - /> - - ); -} \ No newline at end of file + return ( + + props.setProblemString(code)} + highlight={(code) => highlight(code, SAT_language, "SAT_language")} + padding={10} + style={{ + fontFamily: '"Fira code", "Fira Mono", monospace', + fontSize: 24, + }} + /> + + ); +}; diff --git a/src/components/solvers/SAT/prism-SAT.ts b/src/components/solvers/SAT/prism-SAT.ts index d61a60a..ba230f3 100644 --- a/src/components/solvers/SAT/prism-SAT.ts +++ b/src/components/solvers/SAT/prism-SAT.ts @@ -1,24 +1,28 @@ import { regexVariable } from "../../../converter/dimacs/Syntax/CommonSyntax"; -import { regexAND, regexNOTVariable, regexOR } from "../../../converter/dimacs/Syntax/LogicalExpressionSyntax"; +import { + regexAND, + regexNOTVariable, + regexOR, +} from "../../../converter/dimacs/Syntax/LogicalExpressionSyntax"; export const SAT_language = { - 'and': { - pattern: regexAND, - alias: 'boolean' - }, - 'or': { - pattern: regexOR, - alias: 'boolean' - }, - 'SAT-punctuation': /[()]/, - 'negation': { - pattern: regexNOTVariable, - alias: 'string' - }, - 'SAT-variable': { - pattern: regexVariable, - lookbehind: true, - greedy: true, - alias: 'important' - } -}; \ No newline at end of file + and: { + pattern: regexAND, + alias: "boolean", + }, + or: { + pattern: regexOR, + alias: "boolean", + }, + "SAT-punctuation": /[()]/, + negation: { + pattern: regexNOTVariable, + alias: "string", + }, + "SAT-variable": { + pattern: regexVariable, + lookbehind: true, + greedy: true, + alias: "important", + }, +}; diff --git a/src/components/solvers/SettingsView.tsx b/src/components/solvers/SettingsView.tsx index 8d7f751..dff711b 100644 --- a/src/components/solvers/SettingsView.tsx +++ b/src/components/solvers/SettingsView.tsx @@ -1,147 +1,179 @@ import { - Container, - Slider, - Textarea, - Checkbox, - Select, - SliderTrack, - SliderFilledTrack, - Text, SliderThumb, SliderMark, VStack, Box + Container, + Slider, + Textarea, + Checkbox, + Select, + SliderTrack, + SliderFilledTrack, + Text, + SliderThumb, + SliderMark, + VStack, + Box, } from "@chakra-ui/react"; import React, { useEffect, useState } from "react"; import { fetchMetaSolverSettings } from "../../api/ToolboxAPI"; import { - RangeSetting, - CheckboxSetting, - TextSetting, - SelectSetting, - MetaSolverSetting, - MetaSolverSettingType + RangeSetting, + CheckboxSetting, + TextSetting, + SelectSetting, + MetaSolverSetting, + MetaSolverSettingType, } from "../../api/data-model/MetaSolverSettings"; interface SettingsViewProps { - problemUrl: string; - settingChanged: (newSettings: MetaSolverSetting[]) => void; + problemUrl: string; + settingChanged: (newSettings: MetaSolverSetting[]) => void; } export const SettingsView = (props: SettingsViewProps) => { - const [settings, setSettings] = useState([]); + const [settings, setSettings] = useState([]); - useEffect(() => { - fetchMetaSolverSettings(props.problemUrl) - .then((settings: MetaSolverSetting[]) => setSettings(settings)) - }, [props.problemUrl]); + useEffect(() => { + fetchMetaSolverSettings(props.problemUrl).then( + (settings: MetaSolverSetting[]) => setSettings(settings) + ); + }, [props.problemUrl]); - if (settings.length == 0) { - return null; - } + if (settings.length == 0) { + return null; + } - function replaceSetting(key: string, newValue: T): MetaSolverSetting[] { - const index = settings.findIndex(setting => setting.name === key); - if (index !== -1) { - settings.splice(index, 1, newValue); - } - return settings; + function replaceSetting( + key: string, + newValue: T + ): MetaSolverSetting[] { + const index = settings.findIndex((setting) => setting.name === key); + if (index !== -1) { + settings.splice(index, 1, newValue); } + return settings; + } - return ( - - Settings: - - - {settings.map(setting => { - let settingView; + return ( + + Settings: - switch (setting.type) { - case MetaSolverSettingType.RANGE: - let range = setting as RangeSetting; - let total = range.max - range.min; - let step = total < 100 ? total / 100 : 1; - let marks = 5; - let markStep = (total / (marks - 1)); + + {settings.map((setting) => { + let settingView; - settingView = ( - { - const newSettings = replaceSetting(setting.name, { - ...range, - value: v - }); - props.settingChanged(newSettings); - }}> - {Array.from({length: marks}, (_, i) => { - return ( - - {i * markStep} - - ); - })} - - - - - - - ); - break; - case MetaSolverSettingType.CHECKBOX: - let checkbox = setting as CheckboxSetting; - settingView = { - const newSettings = replaceSetting(setting.name, { - ...checkbox, - state: e.target.checked - }); - props.settingChanged(newSettings); - }}/>; - break; - case MetaSolverSettingType.TEXT: - let text = setting as TextSetting; - settingView =