diff --git a/lib/slider.js b/lib/slider.js index a7df6bc..bfae5f4 100644 --- a/lib/slider.js +++ b/lib/slider.js @@ -76,12 +76,12 @@ function Track({ source, target, getTrackProps }) { /* Body */ // Two functions, essentially identical. -export function SliderElement({ onChange, value, displayFunction }) { +export function SliderElement({ onChange, value, displayFunction, domain }) { let toLogDomain = (arr) => [Math.log(arr[0])/Math.log(10), Math.log(arr[1])/Math.log(10)] return ( Array.from(Array(n).keys()) let buildLinks = quantitativeComparisons => quantitativeComparisons.map(([element1, element2, distance]) => ({ source: element1, target: element2, distance: distance })) @@ -31,15 +37,16 @@ let checkIfListIsOrdered = (arr, binaryComparisons) => { } let transformSliderValueToActualValue = value => 10 ** value //>= 2 ? Math.round(10 ** value) : Math.round(10 * 10 ** value) / 10 -let truncateValueForDisplay = value => value > 10 ? Math.round(value) : Math.round(value * 10) / 10 +let toLocale = x => Number(x).toLocaleString() +let truncateValueForDisplay = value => value > 10 ? Number(Math.round(value)).toPrecision(2) : Math.round(value * 10) / 10 let transformSliderValueToPracticalValue = value => truncateValueForDisplay(transformSliderValueToActualValue(value)) let displayFunctionSlider = (value) => { let result if (value >= 0) { - result = transformSliderValueToPracticalValue(value) + result = toLocale(transformSliderValueToPracticalValue(value)) } else { - let inverseresult = transformSliderValueToPracticalValue(-value) + let inverseresult = toLocale(transformSliderValueToPracticalValue(-value)) result = `1/${inverseresult}` } result = `The first option is ${result}x as valuable as the second one` @@ -55,12 +62,12 @@ export async function getStaticProps() { //getServerSideProps // const { metaforecasts } = await getForecasts(); const directory = path.join(process.cwd(), "pages") - let listOfMoralGoods = JSON.parse(fs.readFileSync(path.join(directory, 'listOfMoralGoods.json'), 'utf8')); + let listOfElementsDefault = JSON.parse(fs.readFileSync(path.join(directory, elementsDocument), 'utf8')); //console.log(directory) //console.log("metaforecasts", metaforecasts) return { props: { - listOfElementsDefault: listOfMoralGoods, + listOfElementsDefault }, }; } @@ -271,6 +278,7 @@ export default function Home({ listOfElementsDefault }) { onChange={(event) => (setSliderValue(event[0]))} value={sliderValue} displayFunction={displayFunctionSlider} + domain={domain} /> Array.from(Array(n).keys()) +let buildLinks = quantitativeComparisons => quantitativeComparisons.map(([element1, element2, distance]) => ({ source: element1, target: element2, distance: distance })) + +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 transformSliderValueToActualValue = value => 10 ** value //>= 2 ? Math.round(10 ** value) : Math.round(10 * 10 ** value) / 10 +let toLocale = x => Number(x).toLocaleString() +let truncateValueForDisplay = value => value > 10 ? Number(Math.round(value)).toPrecision(2) : Math.round(value * 10) / 10 +let transformSliderValueToPracticalValue = value => truncateValueForDisplay(transformSliderValueToActualValue(value)) + +let displayFunctionSlider = (value) => { + let result + if (value >= 0) { + result = toLocale(transformSliderValueToPracticalValue(value)) + } else { + let inverseresult = toLocale(transformSliderValueToPracticalValue(-value)) + result = `1/${inverseresult}` + } + result = `The first option is ${result}x as valuable as the second one` + return result + +}; + +let nicelyFormatLinks = (quantitativeComparisons, listOfElements) => quantitativeComparisons.map(([element1, element2, distance]) => ({ source: listOfElements[element1].name, target: listOfElements[element2].name, distance: distance })) + +/* React components */ +// fs can only be used here. +export async function getStaticProps() { + //getServerSideProps + // const { metaforecasts } = await getForecasts(); + const directory = path.join(process.cwd(), "pages") + let listOfElementsDefault = JSON.parse(fs.readFileSync(path.join(directory, elementsDocument), 'utf8')); + //console.log(directory) + //console.log("metaforecasts", metaforecasts) + return { + props: { + listOfElementsDefault + }, + }; +} + +// Main react component +export default function Home({ listOfElementsDefault }) { + // State + let initialListOfElements = listOfElementsDefault.map((element, i) => ({ ...element, id: i })) + let initialPosList = increasingList(listOfElementsDefault.length) // [0,1,2,3,4] + //let listOfElements = listOfElementsDefault.map((element, i) => ({...element, id: i})) + //let list = increasingList(listOfElementsDefault.length) // [0,1,2,3,4] + + //let initialComparePair = [list[list.length-2], list[list.length-1]] + let initialComparePair = [initialPosList[initialPosList.length - 2], initialPosList[initialPosList.length - 1]] + let initialSliderValue = 0 + let initialBinaryComparisons = [] + let initialQuantitativeComparisons = [] + let initialIsListOdered = false + let initialOrderedList = [] + let initialShowAdvancedOptions = false + let initialShowComparisons = false + let initialShowChangeDataSet = false + + 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 [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 restart = (posList) => { + setToComparePair([posList[posList.length - 2], posList[posList.length - 1]]) + setSliderValue(initialSliderValue) + setBinaryComparisons(initialBinaryComparisons) + setQuantitativeComparisons(initialQuantitativeComparisons) + setIsListOrdered(initialIsListOdered) + setOrderedList(initialOrderedList) + removeOldSvg() + } + + let changeDataSet = (listOfElementsNew) => { + listOfElementsNew = + listOfElementsNew.map((element, i) => ({ ...element, id: i })) + let newPosList = increasingList(listOfElementsNew.length) + setListOfElements(listOfElementsNew) + setPosList(increasingList(listOfElementsNew.length)) + setToComparePair([newPosList[newPosList.length - 2], newPosList[newPosList.length - 1]]) + 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) + + setIsListOrdered(true) + setOrderedList(result) + + return true + } else { + return false + } + } + + let nextStepSlider = ({ posList, binaryComparisons, sliderValue, element1, element2 }) => { + if (sliderValue < 0) { + sliderValue = -sliderValue; + [element1, element2] = [element2, element1] + } + console.log(`posList@nextStepSlider:`) + console.log(posList) + let successStatus = nextStepSimple(posList, binaryComparisons, element1, element2) + + let newQuantitativeComparison = [element1, element2, transformSliderValueToPracticalValue(sliderValue)] + let newQuantitativeComparisons = [...quantitativeComparisons, newQuantitativeComparison] + setQuantitativeComparisons(newQuantitativeComparisons) + + setSliderValue(0) + if (successStatus) { + let jsObject = nicelyFormatLinks(quantitativeComparisons, listOfElements) + pushToMongo(jsObject) + console.log(jsObject) + } + } + + // Html + return ( +
+
+ + Utility Function Extractor + + +
+ +
+

+ Utility Function Extractor +

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

+ + */} +
+
+ +
+ ) +}