V2, with qualitative comparisons. I still don't induce the utility function at the end, but I do have the data to do so

This commit is contained in:
NunoSempere 2021-06-07 00:18:40 +02:00
parent 9cae559df3
commit bc132010bb
4 changed files with 225 additions and 6363 deletions

124
lib/slider.js Normal file
View File

@ -0,0 +1,124 @@
/* Imports */
import { Slider, Rail, Handles, Tracks, Ticks } from "react-compound-slider";
import React, { useState } from 'react';
// https://sghall.github.io/react-compound-slider/#/getting-started/tutorial
/* Definitions */
const sliderStyle = { // Give the slider some width
position: 'relative',
width: '40em',
height: 40,
border: '5em',
}
const railStyle = {
position: 'absolute',
width: '100%',
height: 15,
marginTop: 30,
borderRadius: 5,
backgroundColor: 'lightgrey',
}
/* Support functions */
function Handle({
handle: { id, value, percent },
getHandleProps,
displayFunction,
handleWidth
}) {
return (
<>
<div className="justify-center text-center text-gray-600 text-xs">
{displayFunction(value)}
</div>
<div
style={{
left: `${percent}%`,
position: 'absolute',
marginLeft: -10,
marginTop: 0,
zIndex: 2,
width: 30,
height: 30,
cursor: 'pointer',
borderRadius: '50%',
backgroundColor: '#374151',
color: '#374151',
}}
{...getHandleProps(id)}
>
</div>
</>
)
}
function Track({ source, target, getTrackProps }) {
return (
<div
style={{
position: 'absolute',
height: 15,
zIndex: 1,
marginTop: 7,
backgroundColor: ' #3B82F6',
borderRadius: 5,
cursor: 'pointer',
left: `${source.percent}%`,
width: `${target.percent - source.percent}%`,
}}
{...getTrackProps() /* this will set up events if you want it to be clickeable (optional) */}
/>
)
}
/* Body */
// Two functions, essentially identical.
export function SliderElement({ onChange, value, displayFunction }) {
return (
<Slider
rootStyle={sliderStyle /* inline styles for the outer div. Can also use className prop. */}
domain={[-3,3]}
values={[value]}
onChange={onChange}
>
<Rail>
{({ getRailProps }) => (
<div style={railStyle} {...getRailProps()} />
)}
</Rail>
<Handles>
{({ handles, getHandleProps }) => (
<div className="slider-handles">
{handles.map(handle => (
<Handle
key={handle.id}
handle={handle}
getHandleProps={getHandleProps}
displayFunction={displayFunction}
handleWidth={"15em"}
/>
))}
</div>
)}
</Handles>
<Tracks right={false}>
{({ tracks, getTrackProps }) => (
<div className="slider-tracks">
{tracks.map(({ id, source, target }) => (
<Track
key={id}
source={source}
target={target}
getTrackProps={getTrackProps}
/>
))}
</div>
)}
</Tracks>
</Slider>
)
}

6317
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "with-tailwindcss", "name": "utility-function-extractor",
"version": "0.1.0", "version": "0.2.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"next": "latest", "next": "latest",
"react": "^17.0.1", "react": "^17.0.1",
"react-compound-slider": "^3.3.1",
"react-dom": "^17.0.1" "react-dom": "^17.0.1"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,5 +1,6 @@
import Head from 'next/head' import Head from 'next/head'
import React, { useState } from "react"; import React, { useState } from "react";
import { SliderElement } from "../lib/slider.js";
// Utilities // Utilities
Array.prototype.containsArray = function(val) { Array.prototype.containsArray = function(val) {
@ -10,46 +11,65 @@ Array.prototype.containsArray = function(val) {
return hash.hasOwnProperty(val); return hash.hasOwnProperty(val);
} }
let checkIfListIsOrdered = (arr, comparisons) => { let checkIfListIsOrdered = (arr, binaryComparisons) => {
let l = arr.length let l = arr.length
let isOrdered = true let isOrdered = true
for(let i=0; i<l-1; i++){ for(let i=0; i<l-1; i++){
isOrdered = isOrdered && comparisons.containsArray([arr[i], arr[i+1]]) isOrdered = isOrdered && binaryComparisons.containsArray([arr[i], arr[i+1]])
} }
return isOrdered return isOrdered
} }
let simplifySliderValue = value => 10**value >= 3 ? Math.round(10**value) : Math.round(10*10**value)/10
let displayFunctionSlider = (value) => {
let result
if(value >= 0){
result = simplifySliderValue(value)
}else{
let inverseresult = simplifySliderValue(-value)
result = `1/${inverseresult}`
}
result = `The first option is ${result}x as valuable as the second one`
return result
};
// Main // Main
export default function Home() { export default function Home() {
// State // State
let list = [1,2,3,4,5,6,7,8,9,10] let list = [1,2,3,4,5,6,7,8,9,10]
let initialComparisonPair = [9,10] // let initialComparisonPair = [9,10]
const [toComparePair, setToComparePair] = useState(initialComparisonPair) const [toComparePair, setToComparePair] = useState([list[list.length-2], list[list.length-1]])
const [comparisons, updateComparisons] = useState([]) const [binaryComparisons, setBinaryComparisons] = useState([])
const [sliderValue, setSliderValue] = useState(0)
const [quantitativeComparisons, setQuantitativeComparisons] = useState([])
const [isListOrdered, setIsListOrdered] = useState(false) const [isListOrdered, setIsListOrdered] = useState(false)
const [orderedList, setOrderedList] = useState(null) const [orderedList, setOrderedList] = useState(null)
// Manipulations // Manipulations
let compareTwoElements = (newComparisons, element1, element2) => { let compareTwoElements = (newBinaryComparisons, element1, element2) => {
let element1Greater = newComparisons.containsArray([element1, element2]) let element1Greater = newBinaryComparisons.containsArray([element1, element2])
let element2Greater = newComparisons.containsArray([element2, element1]) let element2Greater = newBinaryComparisons.containsArray([element2, element1])
if(element1Greater || element2Greater){ if(element1Greater || element2Greater){
return element1Greater && !element2Greater return element1Greater && !element2Greater
} else{ } else{
setToComparePair([element1, element2]) setToComparePair([element1, element2])
console.log(`No comparison found between ${element1} and ${element2}`) console.log(`No comparison found between ${element1} and ${element2}`)
console.log(`Comparisons:`) console.log(`Comparisons:`)
console.log(JSON.stringify(newComparisons, null, 4)); console.log(JSON.stringify(newBinaryComparisons, null, 4));
return "No comparison found" return "No comparison found"
} }
} }
function merge(newComparisons, left, right) { function merge(newBinaryComparisons, left, right) {
let sortedArr = []; // the sorted elements will go here let sortedArr = []; // the sorted elements will go here
while (left.length && right.length) { while (left.length && right.length) {
// insert the biggest element to the sortedArr // insert the biggest element to the sortedArr
let comparison = compareTwoElements(newComparisons, left[0], right[0]) let comparison = compareTwoElements(newBinaryComparisons, left[0], right[0])
if(comparison == "No comparison found"){ if(comparison == "No comparison found"){
return "No comparison found; unable to proceed" return "No comparison found; unable to proceed"
} }
@ -64,7 +84,7 @@ export default function Home() {
return [...sortedArr, ...left, ...right]; // if they don't have the same size, the remaining ones will be greater than the ones before return [...sortedArr, ...left, ...right]; // if they don't have the same size, the remaining ones will be greater than the ones before
} }
function mergeSort(arr, newComparisons) { function mergeSort(arr, newBinaryComparisons) {
if(arr == "No comparison found; unable to proceed"){ if(arr == "No comparison found; unable to proceed"){
return "No comparison found; unable to proceed" return "No comparison found; unable to proceed"
} }
@ -77,10 +97,10 @@ export default function Home() {
const left = arr.splice(0, half); // the first half of the array const left = arr.splice(0, half); // the first half of the array
const right = arr; const right = arr;
let orderedFirstHalf = mergeSort(left, newComparisons) let orderedFirstHalf = mergeSort(left, newBinaryComparisons)
let orderedSecondHalf = mergeSort(right, newComparisons) let orderedSecondHalf = mergeSort(right, newBinaryComparisons)
if(orderedFirstHalf != "No comparison found; unable to proceed" && orderedSecondHalf != "No comparison found; unable to proceed"){ if(orderedFirstHalf != "No comparison found; unable to proceed" && orderedSecondHalf != "No comparison found; unable to proceed"){
let result = merge(newComparisons, orderedFirstHalf, orderedSecondHalf); let result = merge(newBinaryComparisons, orderedFirstHalf, orderedSecondHalf);
return result return result
}else{ }else{
return "No comparison found; unable to proceed" return "No comparison found; unable to proceed"
@ -88,25 +108,40 @@ export default function Home() {
} }
let nextStep = (comparisons, element1, element2) => { let nextStepSimple = (binaryComparisons, element1, element2) => {
console.log("Comparisons: ") console.log("Binary comparisons: ")
console.log(JSON.stringify(comparisons, null, 4)); console.log(JSON.stringify(binaryComparisons, null, 4));
let newComparison = [element1, element2] // [element1, element2] let newComparison = [element1, element2] // [element1, element2]
let newComparisons = [...comparisons, newComparison] let newBinaryComparisons = [...binaryComparisons, newComparison]
console.log("New comparisons: ") console.log("New binaryComparisons: ")
console.log(JSON.stringify(newComparisons, null, 4)); console.log(JSON.stringify(newBinaryComparisons, null, 4));
updateComparisons(newComparisons) setBinaryComparisons(newBinaryComparisons)
let result = mergeSort(list, newComparisons)
let result = mergeSort(list, newBinaryComparisons)
console.log(result) console.log(result)
console.log(toComparePair) if(result != "No comparison found; unable to proceed" && checkIfListIsOrdered(result, newBinaryComparisons)){
if(result != "No comparison found; unable to proceed" && checkIfListIsOrdered(result, newComparisons)){
alert("Order complete")
console.log(result) console.log(result)
setIsListOrdered(true) setIsListOrdered(true)
setOrderedList(result) setOrderedList(result)
} }
} }
let nextStepSlider = (binaryComparisons, sliderValue, element1, element2) => {
if(sliderValue < 0){
sliderValue = -sliderValue;
[element1,element2] = [element2,element1]
}
nextStepSimple(binaryComparisons, element1, element2)
let newQuantitativeComparison = [element1, element2, simplifySliderValue(sliderValue)]
let newQuantitativeComparisons = [...quantitativeComparisons, newQuantitativeComparison]
setQuantitativeComparisons(newQuantitativeComparisons)
setSliderValue(0)
}
// Html // Html
return ( return (
<div className="flex flex-col items-center justify-center min-h-screen py-2"> <div className="flex flex-col items-center justify-center min-h-screen py-2">
@ -117,26 +152,45 @@ export default function Home() {
<main className="flex flex-col items-center justify-center w-full flex-1 px-20 text-center"> <main className="flex flex-col items-center justify-center w-full flex-1 px-20 text-center">
<h1 className="text-6xl font-bold"> <h1 className="text-6xl font-bold">
Hot or not? Utility Function Extractor
</h1> </h1>
<div className={`flex flex-wrap items-center max-w-4xl mt-6 sm:w-full mt-20 ${isListOrdered? "hidden" : ""}`}> <div className = {`${isListOrdered ? "hidden" : ""}`}>
<button <div className="flex flex-wrap items-center max-w-4xl mt-6 sm:w-full mt-20">
className="flex m-auto border-gray-300 border-4 h-64 w-64" <div
onClick={() => nextStep(comparisons, toComparePair[0], toComparePair[1])} className="flex m-auto border-gray-300 border-4 h-64 w-64"
> //onClick={() => nextStep(binaryComparisons, toComparePair[0], toComparePair[1])}
<p className="block m-auto text-center">{toComparePair[0]}</p> >
</button> <p className="block m-auto text-center">{toComparePair[0]}</p>
<button </div>
className="flex m-auto border-gray-300 border-4 h-64 w-64" <div
onClick={() => nextStep(comparisons, toComparePair[1], toComparePair[0])} className="flex m-auto border-gray-300 border-4 h-64 w-64"
> //onClick={() => nextStep(binaryComparisons, toComparePair[1], toComparePair[0])}
<p className="block m-auto text-center">{toComparePair[1]}</p> >
</button> <p className="block m-auto text-center">{toComparePair[1]}</p>
</div>
</div>
<div className={`flex row-start-3 row-end-3 col-start-1 col-end-4 md:col-start-3 md:col-end-3 md:row-start-1 md:row-end-1 lg:col-start-3 lg:col-end-3 lg:row-start-1 lg:row-end-1 items-center justify-center mb-4 mt-10 ${isListOrdered? "hidden" : ""}`}>
<SliderElement
className="flex items-center justify-center"
onChange={(event) => (setSliderValue(event[0]))}
value={sliderValue}
displayFunction={displayFunctionSlider}
/>
</div>
<button
className="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded mt-5"
onClick={() => nextStepSlider(binaryComparisons, sliderValue, toComparePair[1], toComparePair[0])}>
Submit
</button>
</div> </div>
<div className={`mt-10 ${isListOrdered? "": "hidden" }`}> <div className={`mt-10 ${isListOrdered? "": "hidden" }`}>
<p>{`Ordered list: ${JSON.stringify(orderedList, null, 4)}`}</p> <p>{`Ordered list: ${JSON.stringify(orderedList, null, 4)}`}</p>
<p>{`Comparisons: ${JSON.stringify(comparisons, null, 4)}`}</p> <p>{`Binary comparisons: ${JSON.stringify(binaryComparisons, null, 4)}`}</p>
<p>{`Quantitative comparisons: ${JSON.stringify(quantitativeComparisons, null, 4)}`}</p>
</div> </div>
</main> </main>