/* Imports */
import Head from 'next/head'
import React, { useState } from "react";
import { DrawGraph, removeOldSvg } from './labeledgraph';
import { SubmitSliderButton } from "./slider";
import { DisplayElement } from './displayElement'
import { DisplayAsMarkdown } from './displayAsMarkdown'
import { CreateTable } from './findPaths'
import { TextAreaForJson } from "./textAreaForJson"
import { pushToMongo } from "./pushToMongo.js"
import { maxMergeSortSteps, expectedNumMergeSortSteps } from "./utils.js"
/* DEFINTIONS */
const DEFAULT_COMPARE = 2 // 1, unless you're testing smth.
/* Helpers */
let increasingList = (n) => Array.from(Array(n).keys())
let buildLinks = quantitativeComparisons => quantitativeComparisons.map(([element1, element2, distance, reasoning]) => ({ source: element1, target: element2, distance: distance, reasoning: reasoning }))
Array.prototype.containsArray = function (val) {
var hash = {};
for (var i = 0; i < this.length; i++) {
hash[this[i]] = i;
}
return hash.hasOwnProperty(val);
}
let checkIfListIsOrdered = (arr, binaryComparisons) => {
let l = arr.length
let isOrdered = true
for (let i = 0; i < l - 1; i++) {
isOrdered = isOrdered && binaryComparisons.containsArray([arr[i], arr[i + 1]])
}
return isOrdered
}
let nicelyFormatLinks = (quantitativeComparisons, listOfElements) => quantitativeComparisons.map(([element1, element2, distance, reasoning]) => ({ source: listOfElements[element1].name, target: listOfElements[element2].name, distance: distance, reasoning: reasoning }))
// Main react component
export default function ComparisonView({ listOfElementsForView }) {
// State
let initialListOfElements = listOfElementsForView.map((element, i) => ({ ...element, id: i }))
let initialPosList = increasingList(listOfElementsForView.length) // [0,1,2,3,4]
let initialComparePair = [initialPosList[initialPosList.length - 2], initialPosList[initialPosList.length - 1]]
let initialSliderValue = 1
let initialReasoning = ''
let initialBinaryComparisons = []
let initialQuantitativeComparisons = []
let initialIsListOdered = false
let initialOrderedList = []
let initialShowAdvancedOptions = false
let initialShowComparisons = false
let initialShowChangeDataSet = false
let initialNumSteps = 0;
let initialMaxSteps = maxMergeSortSteps(listOfElementsForView.length)
let initialExpectedSteps = expectedNumMergeSortSteps(listOfElementsForView.length)
//let listOfElements = listOfElementsForView.map((element, i) => ({...element, id: i}))
//let list = increasingList(listOfElementsForView.length) // [0,1,2,3,4]
//let initialComparePair = [list[list.length-2], list[list.length-1]]
const [listOfElements, setListOfElements] = useState(initialListOfElements)
const [posList, setPosList] = useState(initialPosList)
//const posList = initialPosList
// let listOfElements = initialListOfElements
const [toComparePair, setToComparePair] = useState(initialComparePair)
const [sliderValue, setSliderValue] = useState(initialSliderValue)
const [reasoning, setReasoning] = useState(initialReasoning)
const [binaryComparisons, setBinaryComparisons] = useState(initialBinaryComparisons)
const [quantitativeComparisons, setQuantitativeComparisons] = useState(initialQuantitativeComparisons) // More expressive, but more laborious to search through. For the ordering step, I only manipulate the binaryComparisons.
const [isListOrdered, setIsListOrdered] = useState(initialIsListOdered)
const [orderedList, setOrderedList] = useState(initialOrderedList)
let [showAdvancedOptions, changeShowAdvanceOptions] = useState(initialShowAdvancedOptions);
let [showComparisons, changeShowComparisons] = useState(initialShowComparisons);
let [showChangeDataSet, changeshowChangeDataSet] = useState(initialShowChangeDataSet);
let [numSteps, changeNumSteps] = useState(initialNumSteps);
let [maxSteps, changeMaxSteps] = useState(initialMaxSteps)
let [expectedSteps, changeExpectedSteps] = useState(initialExpectedSteps)
let restart = (posList) => {
setToComparePair([posList[posList.length - 2], posList[posList.length - 1]])
setSliderValue(initialSliderValue)
setBinaryComparisons(initialBinaryComparisons)
setQuantitativeComparisons(initialQuantitativeComparisons)
setIsListOrdered(initialIsListOdered)
setOrderedList(initialOrderedList)
changeNumSteps(0)
removeOldSvg()
}
let changeDataSet = (listOfElementsNew) => {
listOfElementsNew =
listOfElementsNew.map((element, i) => ({ ...element, id: i }))
let newPosList = increasingList(listOfElementsNew.length)
let newListLength = listOfElementsNew.length
setListOfElements(listOfElementsNew)
setPosList(increasingList(listOfElementsNew.length))
setToComparePair([newPosList[newPosList.length - 2], newPosList[newPosList.length - 1]])
changeExpectedSteps(expectedNumMergeSortSteps(newListLength))
changeMaxSteps(maxMergeSortSteps(newListLength))
restart(newPosList)
}
// Manipulations
let compareTwoElements = (newBinaryComparisons, element1, element2) => {
let element1Greater = newBinaryComparisons.containsArray([element1, element2])
let element2Greater = newBinaryComparisons.containsArray([element2, element1])
if (element1Greater || element2Greater) {
return element1Greater && !element2Greater
} else {
setToComparePair([element1, element2])
//console.log(`No comparison found between ${element1} and ${element2}`)
//console.log(`Comparisons:`)
//console.log(JSON.stringify(newBinaryComparisons, null, 4));
return "No comparison found"
}
}
function merge(newBinaryComparisons, left, right) {
let sortedArr = []; // the sorted elements will go here
while (left.length && right.length) {
// insert the biggest element to the sortedArr
let comparison = compareTwoElements(newBinaryComparisons, left[0], right[0])
if (comparison == "No comparison found") {
return "No comparison found; unable to proceed"
}
else if (comparison) { // left[0] > right[0]
sortedArr.push(left.shift());
} else {
sortedArr.push(right.shift());
}
}
// use spread operator and create a new array, combining the three arrays
return [...sortedArr, ...left, ...right]; // if they don't have the same size, the remaining ones will be greater than the ones before
}
function mergeSort({ array, comparisons }) {
if (array == "No comparison found; unable to proceed") {
return "No comparison found; unable to proceed"
}
const half = array.length / 2;
// the base case is array length <=1
if (array.length <= 1) {
return array;
}
const left = array.slice(0, half); // the first half of the array
const right = array.slice(half, array.length) // Note that splice is destructive.
let orderedFirstHalf = mergeSort({ array: left, comparisons })
let orderedSecondHalf = mergeSort({ array: right, comparisons })
if (orderedFirstHalf != "No comparison found; unable to proceed" && orderedSecondHalf != "No comparison found; unable to proceed") {
let result = merge(comparisons, orderedFirstHalf, orderedSecondHalf);
return result
} else {
return "No comparison found; unable to proceed"
}
}
let nextStepSimple = (posList, binaryComparisons, element1, element2) => {
//console.log("Binary comparisons: ")
//console.log(JSON.stringify(binaryComparisons, null, 4));
let newComparison = [element1, element2] // [element1, element2]
let newBinaryComparisons = [...binaryComparisons, newComparison]
//console.log("New binaryComparisons: ")
//console.log(JSON.stringify(newBinaryComparisons, null, 4));
setBinaryComparisons(newBinaryComparisons)
let result = mergeSort({ array: posList, comparisons: newBinaryComparisons })
//console.log(result)
if (result != "No comparison found; unable to proceed" && checkIfListIsOrdered(result, newBinaryComparisons)) {
// console.log(`isListOrdered: ${isListOrdered}`)
console.log("poslist@nextStepSimple")
console.log(posList)
console.log("result@nextStepSimple")
console.log(result)
return [true, result]
} else {
return [false, result]
}
}
let nextStepSlider = async ({ posList, binaryComparisons, sliderValue, Reasoning, element1, element2 }) => {
if (sliderValue < 1 && sliderValue > 0) {
sliderValue = 1 / sliderValue;
[element1, element2] = [element2, element1]
}
console.log(`posList@nextStepSlider:`)
console.log(posList)
let [successStatus, result] = nextStepSimple(posList, binaryComparisons, element1, element2)
let newQuantitativeComparison = [element1, element2, sliderValue, reasoning]
let newQuantitativeComparisons = [...quantitativeComparisons, newQuantitativeComparison]
setQuantitativeComparisons(newQuantitativeComparisons)
setSliderValue(DEFAULT_COMPARE)
setReasoning('')
changeNumSteps(numSteps + 1)
if (successStatus) {
let jsObject = nicelyFormatLinks(quantitativeComparisons, listOfElements)
await pushToMongo(jsObject)
console.log(jsObject)
alert("Comparisons completed. Background work might take a while, or straight-out fail")
setTimeout(() => {
// Make sure to do this after the
setIsListOrdered(true)
setOrderedList(result)
}, 5000);
}
}
// Html
return (
Utility Function Extractor
Utility Function Extractor
{`${numSteps} out of ~${expectedSteps} (max ${maxSteps}) comparisons`}
nextStep(binaryComparisons, toComparePair[0], toComparePair[1])}
>
nextStep(binaryComparisons, toComparePair[1], toComparePair[0])}
>
{/*
(setSliderValue(event[0]))}
value={sliderValue}
displayFunction={displayFunctionSlider}
domain={domain}
/>
*/}
{/*
listOfElements[i]), null, 4)}>
*/}
Comparisons
{/*
{`Binary comparisons: ${JSON.stringify(binaryComparisons, null, 4)}`}
{`Quantitative comparisons: ${JSON.stringify(quantitativeComparisons, null, 4)}`}
*/}
)
}