2021-06-07 17:09:30 +00:00
|
|
|
/* Imports*/
|
|
|
|
import React from "react";
|
2021-11-25 15:08:20 +00:00
|
|
|
import { toLocale, truncateValueForDisplay, numToAlphabeticalString, formatLargeOrSmall } from "../lib/utils.js"
|
2021-06-07 17:09:30 +00:00
|
|
|
|
|
|
|
/* Utilities */
|
2021-12-07 19:40:43 +00:00
|
|
|
let avg = arr => arr.reduce((a, b) => (a + b), 0) / arr.length
|
2021-06-07 17:09:30 +00:00
|
|
|
|
|
|
|
/* Main function */
|
|
|
|
|
2021-12-07 22:45:55 +00:00
|
|
|
function findPathsInner({
|
|
|
|
sourceElementId, sourceElementPosition,
|
|
|
|
targetElementId, targetElementPosition,
|
|
|
|
links, nodes,
|
|
|
|
maxLengthOfPath, pathSoFar
|
|
|
|
}) {
|
2021-06-07 17:09:30 +00:00
|
|
|
let paths = []
|
2021-12-07 22:45:55 +00:00
|
|
|
|
|
|
|
let minPos = Math.min(sourceElementPosition, targetElementPosition)
|
|
|
|
let maxPos = Math.max(sourceElementPosition, targetElementPosition)
|
|
|
|
let linksInner = links.filter(link =>
|
|
|
|
(minPos <= link.sourceElementPosition && link.sourceElementPosition <= maxPos) &&
|
|
|
|
(minPos <= link.targetElementPosition && link.targetElementPosition <= maxPos)
|
|
|
|
)
|
|
|
|
let linksNow = linksInner.filter(link => (link.source == sourceElementId || link.target == sourceElementId))
|
2021-12-07 19:40:43 +00:00
|
|
|
if (maxLengthOfPath > 0) {
|
2021-12-07 22:45:55 +00:00
|
|
|
for (let link of linksNow) {
|
2021-12-07 19:40:43 +00:00
|
|
|
if (
|
|
|
|
((link.source == sourceElementId) && (link.target == targetElementId)) ||
|
2021-06-07 17:09:30 +00:00
|
|
|
((link.source == targetElementId) && (link.target == sourceElementId))
|
2021-12-07 19:40:43 +00:00
|
|
|
) {
|
2021-06-07 17:09:30 +00:00
|
|
|
paths.push(pathSoFar.concat(link).flat())
|
2021-12-07 19:40:43 +00:00
|
|
|
} else if ((link.source == sourceElementId)) {
|
2021-12-07 22:45:55 +00:00
|
|
|
let newPaths = findPathsInner({
|
|
|
|
sourceElementId: link.target, sourceElementPosition: link.sourceElementPosition,
|
|
|
|
targetElementId, targetElementPosition,
|
|
|
|
pathSoFar: pathSoFar.concat(link).flat(),
|
|
|
|
links: linksInner, nodes, maxLengthOfPath: (maxLengthOfPath - 1)
|
|
|
|
})
|
2021-12-07 19:40:43 +00:00
|
|
|
if (newPaths.length != 0) {
|
2021-06-07 17:09:30 +00:00
|
|
|
paths.push(...newPaths)
|
|
|
|
}
|
2021-12-07 19:40:43 +00:00
|
|
|
} else if ((link.target == sourceElementId)) {
|
2021-12-07 22:45:55 +00:00
|
|
|
let newPaths = findPathsInner({
|
|
|
|
sourceElementId: link.source, sourceElementPosition: link.sourceElementPosition,
|
|
|
|
targetElementId, targetElementPosition,
|
|
|
|
pathSoFar: pathSoFar.concat(link).flat(),
|
|
|
|
links: linksInner, nodes, maxLengthOfPath: (maxLengthOfPath - 1) })
|
2021-12-07 19:40:43 +00:00
|
|
|
if (newPaths.length != 0) {
|
2021-06-07 17:09:30 +00:00
|
|
|
paths.push(...newPaths)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-07 19:40:43 +00:00
|
|
|
|
2021-06-07 17:09:30 +00:00
|
|
|
return paths
|
|
|
|
}
|
2021-12-07 22:45:55 +00:00
|
|
|
/*
|
|
|
|
function findPaths({
|
|
|
|
sourceElementId, sourceElementPosition,
|
|
|
|
targetElementId, targetElementPosition,
|
|
|
|
nodes, links, direction
|
|
|
|
}) {
|
2021-06-10 21:52:33 +00:00
|
|
|
let positionSourceElement = nodes.map((element, i) => (element.id)).indexOf(sourceElementId)
|
|
|
|
let positionTargetElement = nodes.map((element, i) => (element.id)).indexOf(targetElementId)
|
2021-06-07 17:09:30 +00:00
|
|
|
let maxLengthOfPath = Math.abs(positionSourceElement - positionTargetElement)
|
2021-12-07 22:45:55 +00:00
|
|
|
return findPathsInner({
|
|
|
|
sourceElementId, sourceElementPosition,
|
|
|
|
targetElementId, targetElementPosition,
|
|
|
|
links, nodes, direction,
|
|
|
|
maxLengthOfPath, pathSoFar: []
|
|
|
|
})
|
2021-06-07 17:09:30 +00:00
|
|
|
}
|
2021-12-07 22:45:55 +00:00
|
|
|
*/
|
2021-06-07 17:09:30 +00:00
|
|
|
|
2021-12-07 22:45:55 +00:00
|
|
|
function findDistance({
|
|
|
|
sourceElementId, sourceElementPosition,
|
|
|
|
targetElementId, targetElementPosition,
|
|
|
|
nodes, links, direction
|
|
|
|
}) {
|
|
|
|
let maxLengthOfPath = Math.abs(sourceElementPosition - targetElementPosition)
|
|
|
|
let paths = findPathsInner({
|
|
|
|
sourceElementId, sourceElementPosition,
|
|
|
|
targetElementId, targetElementPosition,
|
|
|
|
links, nodes, direction,
|
|
|
|
maxLengthOfPath, pathSoFar: []
|
|
|
|
});
|
2021-12-07 19:40:43 +00:00
|
|
|
console.log(`findDistance from ${sourceElementPosition} to ${targetElementPosition}`)
|
2021-06-12 14:13:13 +00:00
|
|
|
console.log(targetElementId)
|
2021-12-07 19:40:43 +00:00
|
|
|
console.log(direction)
|
2021-06-12 14:13:13 +00:00
|
|
|
console.log(paths)
|
2021-06-07 17:09:30 +00:00
|
|
|
let weights = []
|
2021-12-07 19:40:43 +00:00
|
|
|
for (let path of paths) {
|
2021-06-07 17:09:30 +00:00
|
|
|
let currentSource = sourceElementId
|
|
|
|
let weight = 1
|
2021-12-07 19:40:43 +00:00
|
|
|
for (let element of path) {
|
2021-06-07 17:09:30 +00:00
|
|
|
let distance = 0
|
2021-12-07 19:40:43 +00:00
|
|
|
if (element.source == currentSource) {
|
2021-06-07 17:09:30 +00:00
|
|
|
distance = element.distance
|
|
|
|
currentSource = element.target
|
2021-12-07 19:40:43 +00:00
|
|
|
} else if (element.target == currentSource) {
|
|
|
|
distance = 1 / Number(element.distance)
|
2021-06-07 17:09:30 +00:00
|
|
|
currentSource = element.source
|
|
|
|
}
|
2021-12-07 19:40:43 +00:00
|
|
|
weight = weight * distance
|
|
|
|
|
2021-06-07 17:09:30 +00:00
|
|
|
}
|
|
|
|
weights.push(weight)
|
|
|
|
}
|
|
|
|
//let sum = JSON.stringify(weights)//weights.length > 0 ? weights.reduce((a,b) => (a+b)) / weights.length : "Not found"
|
|
|
|
//return sum
|
2021-11-08 21:09:06 +00:00
|
|
|
return weights
|
|
|
|
//return weights.map(weight => Math.round(weight*100)/100)
|
2021-06-07 17:09:30 +00:00
|
|
|
}
|
|
|
|
|
2021-12-07 19:40:43 +00:00
|
|
|
function getDirectionalLinks({ nodes, links }) {
|
|
|
|
console.log("getDirectionalLinks")
|
|
|
|
// direction: 1 for upwards, -1 for downwards
|
|
|
|
let upwardsLinks = []
|
|
|
|
let downwardsLinks = []
|
|
|
|
links.forEach(link => {
|
|
|
|
console.log(link)
|
|
|
|
let sourceElementId = link.source
|
|
|
|
let targetElementId = link.target
|
|
|
|
if (link.distance < 1) {
|
|
|
|
// We already deal with this case upstream, but whatever.
|
|
|
|
[sourceElementId, targetElementId] = [targetElementId, sourceElementId]
|
|
|
|
}
|
|
|
|
let sourceElementPosition = nodes.find(element => element.id == sourceElementId).position
|
|
|
|
let targetElementPosition = nodes.find(element => element.id == targetElementId).position
|
|
|
|
if (link.distance == 1) {
|
|
|
|
// If two elements are the same, then they belong to both upwards and downwards paths!!
|
|
|
|
upwardsLinks.push(link)
|
|
|
|
downwardsLinks.push(link)
|
|
|
|
} else if (sourceElementPosition < targetElementPosition) {
|
|
|
|
upwardsLinks.push(link)
|
|
|
|
} else {
|
|
|
|
downwardsLinks.push(link)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
console.log([upwardsLinks, downwardsLinks])
|
|
|
|
return [upwardsLinks, downwardsLinks]
|
|
|
|
}
|
|
|
|
|
|
|
|
function findDistancesForAllElements({ nodes, links }) {
|
2021-06-10 21:52:33 +00:00
|
|
|
let referenceElements = nodes.filter(x => x.isReferenceValue)
|
2021-12-07 19:40:43 +00:00
|
|
|
let midpoint = Math.round(nodes.length / 2)
|
2021-06-10 21:52:33 +00:00
|
|
|
let referenceElement = referenceElements.length > 0 ? referenceElements[0] : nodes[midpoint]
|
2021-06-12 14:13:13 +00:00
|
|
|
// console.log(nodes)
|
2021-12-07 19:40:43 +00:00
|
|
|
console.log(`referenceElement.position: ${referenceElement.position}`)
|
|
|
|
let distances = nodes.map(node => {
|
|
|
|
if (node.isReferenceValue || (node.id == referenceElement.id)) {
|
|
|
|
return [1]
|
|
|
|
} else {
|
|
|
|
console.log("node")
|
|
|
|
console.log(node)
|
2021-12-07 22:45:55 +00:00
|
|
|
let isUpwardsDirection = referenceElement.position < node.position
|
2021-12-07 19:40:43 +00:00
|
|
|
let distance = findDistance({
|
|
|
|
sourceElementId: referenceElement.id,
|
|
|
|
sourceElementPosition: referenceElement.position,
|
|
|
|
targetElementId: node.id,
|
|
|
|
targetElementPosition: node.position,
|
|
|
|
nodes: nodes,
|
2021-12-07 22:45:55 +00:00
|
|
|
links: links,
|
2021-12-07 19:40:43 +00:00
|
|
|
direction: isUpwardsDirection ? "upwards" : "downwards"
|
|
|
|
})
|
|
|
|
return distance
|
|
|
|
}
|
|
|
|
})
|
2021-06-07 17:09:30 +00:00
|
|
|
return distances
|
|
|
|
}
|
|
|
|
|
2021-12-07 19:40:43 +00:00
|
|
|
function abridgeArrayAndDisplay(array) {
|
2021-11-25 16:13:38 +00:00
|
|
|
let newArray
|
2021-11-26 14:31:30 +00:00
|
|
|
let formatForDisplay
|
2021-12-07 19:40:43 +00:00
|
|
|
if (array.length > 10) {
|
|
|
|
newArray = array.slice(0, 9)
|
|
|
|
formatForDisplay = newArray.map(d => formatLargeOrSmall(d))
|
2021-11-26 14:31:30 +00:00
|
|
|
formatForDisplay[9] = "..."
|
2021-12-07 19:40:43 +00:00
|
|
|
} else {
|
|
|
|
newArray = array
|
|
|
|
formatForDisplay = newArray.map(d => formatLargeOrSmall(d))
|
2021-11-25 16:13:38 +00:00
|
|
|
}
|
|
|
|
let result = JSON.stringify(formatForDisplay, null, 2).replaceAll(`"`, "")
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2021-12-07 19:40:43 +00:00
|
|
|
export function CreateTableWithDistances({ isListOrdered, orderedList, listOfElements, links }) {
|
|
|
|
if (!isListOrdered || orderedList.length < listOfElements.length) {
|
2021-06-10 21:52:33 +00:00
|
|
|
return (<div>{""}</div>)
|
2021-06-07 17:09:30 +00:00
|
|
|
} else {
|
2021-12-07 22:45:55 +00:00
|
|
|
let nodes = []
|
|
|
|
let positionDictionary=({})
|
|
|
|
orderedList.forEach((id, pos) => {
|
|
|
|
nodes.push({ ...listOfElements[id], position: pos })
|
|
|
|
positionDictionary[id] = pos
|
|
|
|
})
|
|
|
|
// let nodes = orderedList.map((id, pos) => ({ ...listOfElements[id], position: pos }))
|
|
|
|
/* Pre-process links to talk in terms of distances */
|
|
|
|
links = links.map(link => ({...link,
|
|
|
|
sourceElementPosition: positionDictionary[link.source],
|
|
|
|
targetElementPosition: positionDictionary[link.target]
|
|
|
|
}))
|
|
|
|
/* Continue */
|
2021-12-07 19:40:43 +00:00
|
|
|
let distances = findDistancesForAllElements({ nodes, links })
|
|
|
|
let rows = nodes.map((element, i) => ({ id: numToAlphabeticalString(element.position), position: element.position, name: element.name, distances: distances[i] }))
|
2021-06-12 14:13:13 +00:00
|
|
|
console.log("rows@CreateTableWithDistances")
|
|
|
|
console.log(rows)
|
2021-12-07 19:40:43 +00:00
|
|
|
return (
|
2021-06-10 21:52:33 +00:00
|
|
|
<div>
|
|
|
|
<table className="">
|
|
|
|
<thead >
|
2021-12-07 19:40:43 +00:00
|
|
|
<tr >
|
|
|
|
<th >Id</th>
|
|
|
|
<th> </th>
|
|
|
|
<th >Position</th>
|
|
|
|
<th> </th>
|
|
|
|
<th >Element</th>
|
|
|
|
<th> </th>
|
|
|
|
<th >Possible relative values</th>
|
|
|
|
<th> </th>
|
|
|
|
<th >Average relative value</th>
|
|
|
|
</tr>
|
2021-06-10 21:52:33 +00:00
|
|
|
</thead>
|
|
|
|
<tbody>
|
2021-12-07 19:40:43 +00:00
|
|
|
{rows.map(row => <tr key={row.id}>
|
|
|
|
<td className="" >{row.id}</td>
|
|
|
|
<td> </td>
|
|
|
|
<td className="" >{row.position}</td>
|
2021-06-10 21:52:33 +00:00
|
|
|
<td> </td>
|
|
|
|
<td className="">{row.name}</td>
|
|
|
|
<td> </td>
|
2021-11-25 16:13:38 +00:00
|
|
|
<td className="">{abridgeArrayAndDisplay(row.distances)}</td>
|
2021-06-10 21:52:33 +00:00
|
|
|
<td> </td>
|
2021-10-06 15:10:05 +00:00
|
|
|
<td className="">{formatLargeOrSmall(avg(row.distances))}</td>
|
2021-12-07 19:40:43 +00:00
|
|
|
</tr>
|
|
|
|
)}
|
2021-12-07 17:40:17 +00:00
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-12-07 19:40:43 +00:00
|
|
|
}
|
2021-12-07 17:40:17 +00:00
|
|
|
|
2021-12-07 19:40:43 +00:00
|
|
|
function CreateTableWithoutDistances({ isListOrdered, orderedList, listOfElements, links }) {
|
|
|
|
if (!isListOrdered || orderedList.length < listOfElements.length) {
|
2021-12-07 17:40:17 +00:00
|
|
|
return (<div>{""}</div>)
|
|
|
|
} else {
|
|
|
|
let nodes = orderedList.map(i => listOfElements[i])
|
2021-12-07 19:40:43 +00:00
|
|
|
let rows = nodes.map((element, i) => ({ id: numToAlphabeticalString(element.id), name: element.name }))
|
2021-12-07 17:40:17 +00:00
|
|
|
console.log("rows@CreateTableWithoutDistances")
|
|
|
|
console.log(rows)
|
2021-12-07 19:40:43 +00:00
|
|
|
return (
|
2021-12-07 17:40:17 +00:00
|
|
|
<div>
|
|
|
|
<table className="">
|
|
|
|
<thead >
|
2021-12-07 19:40:43 +00:00
|
|
|
<tr >
|
|
|
|
<th >Id</th>
|
|
|
|
<th> </th>
|
|
|
|
<th >Element</th>
|
|
|
|
<th> </th>
|
|
|
|
</tr>
|
2021-12-07 17:40:17 +00:00
|
|
|
</thead>
|
|
|
|
<tbody>
|
2021-12-07 19:40:43 +00:00
|
|
|
{rows.map(row => <tr key={row.id}>
|
|
|
|
<td className="" >{row.id}</td>
|
2021-12-07 17:40:17 +00:00
|
|
|
<td> </td>
|
|
|
|
<td className="">{row.name}</td>
|
2021-12-07 19:40:43 +00:00
|
|
|
</tr>
|
|
|
|
)}
|
|
|
|
{ }
|
2021-06-10 21:52:33 +00:00
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
)
|
2021-06-07 17:09:30 +00:00
|
|
|
}
|
2021-12-07 19:40:43 +00:00
|
|
|
|
2021-06-07 17:09:30 +00:00
|
|
|
}
|
|
|
|
|
2021-12-07 19:40:43 +00:00
|
|
|
export const CreateTable = CreateTableWithDistances // CreateTableWithoutDistances;
|
2021-12-07 17:40:17 +00:00
|
|
|
|
2021-06-07 17:09:30 +00:00
|
|
|
/* Testing */
|
|
|
|
//import fs from 'fs';
|
|
|
|
//import path from 'path';
|
|
|
|
/*
|
|
|
|
const directory = path.join(process.cwd(),"pages")
|
|
|
|
let links = JSON.parse(fs.readFileSync(path.join(directory, 'distancesExample.json'), 'utf8'));
|
2021-06-10 21:52:33 +00:00
|
|
|
let nodes = JSON.parse(fs.readFileSync(path.join(directory, 'listOfPosts.json'), 'utf8'));
|
2021-06-07 17:09:30 +00:00
|
|
|
|
2021-06-10 21:52:33 +00:00
|
|
|
let paths = findPathsInner({sourceElementId:2, targetElementId:0, pathSoFar: [], links, nodes, maxLengthOfPath: 2})
|
2021-06-07 17:09:30 +00:00
|
|
|
console.log(JSON.stringify(paths, null, 2))
|
|
|
|
*/
|
2021-12-07 19:40:43 +00:00
|
|
|
/*
|
2021-06-10 21:52:33 +00:00
|
|
|
let paths = findPaths({sourceElementId:2, targetElementId:0, links, nodes})
|
2021-06-07 17:09:30 +00:00
|
|
|
console.log(JSON.stringify(paths, null, 2))
|
|
|
|
*/
|
|
|
|
/*
|
2021-06-10 21:52:33 +00:00
|
|
|
let distances = findDistance({sourceElementId:2, targetElementId:4, links, nodes})
|
2021-06-07 17:09:30 +00:00
|
|
|
console.log(distances)
|
|
|
|
*/
|