use xy in assim done, multi widgets in progress

This commit is contained in:
Tom Odem 2024-05-16 12:00:52 -07:00
parent 113b1f8139
commit 7132fedf00
3 changed files with 155 additions and 112 deletions

View File

@ -1,5 +1,5 @@
import type { Widget, WidgetMap } from 'src/types/widget';
import type { Section, LinkedSectionWidget } from 'src/types/support-types';
import type { Section, LinkedSectionWidget, WidgetCluster } from 'src/types/support-types';
import type { Message } from 'src/types/schema-types';
function doesOverlap(
@ -26,7 +26,7 @@ function doesOverlap(
}
type AssimilatorProps = {
// define expected input here and it's type (number, string, etc.)
possibleWidgets: Widget[];
possibleWidgetClusters: WidgetCluster[];
sections: Section[];
widgets: WidgetMap;
message: Message;
@ -38,136 +38,171 @@ type AssimilatorProps = {
* @returns ???
*/
const assimilator = ({
possibleWidgets,
possibleWidgetClusters,
sections,
widgets: deployedWidgets, // re-name for clarity
message,
}: AssimilatorProps) => {
let widgetToDeploy: Widget | null = null; //will return null if we cannot find a space
let sectionID: LinkedSectionWidget = { widgetID: 'none', sectionID: 'none' };
let action: string = 'none';
let widgetClusterToDeploy: WidgetCluster = {
widgets:[],
sectionIds:[],
actions: []
}; //will return null if we cannot find a space
let index = -1;
possibleWidgets.forEach((widget, widgetIndex) => {
// go through each possible widget until we find one we can place
if ((deployedWidgets[widget.id] && deployedWidgets[widget.id].handledMessageIds!.includes(message.id))){
// check if the widget already exists on the screen and handles the message
sectionID = { widgetID: widget.id, sectionID: 'none' };
action = 'messageAlreadyHandled';
widgetToDeploy = widget;
index = widgetIndex;
possibleWidgetClusters.forEach((widgetCluster, widgetClusterIndex) => {
//go through every widget cluster
let allWidgetsPlaced = true//tracks if all widgets in this cluster have been placed
return {
widgetToDeploy,
sectionID,
action,
index, //<- group of widgets tomorrow
};
} else if (deployedWidgets[widget.id] && !deployedWidgets[widget.id].handledMessageIds!.includes(message.id)) {
// check if the widget already exists on the screen and that the widget does not handle the message
sectionID = { widgetID: widget.id, sectionID: 'none' };
action = 'updateWidget';
widgetToDeploy = widget;
index = widgetIndex;
//setup the cluster params we can deploy to
const widgetsToDeploy:Widget[] = []
const sectionIdsToDeploy:LinkedSectionWidget[] = []
const actionsToDeploy:string[] = []
return {
widgetToDeploy,
sectionID,
action,
index,
};
} else {
//the widget doesn't exist yet
//get the sections with matching types
const matchingSections: Section[] = []; //holds matching sections
sections.forEach(function (section, sectionIndex) {
//find matching sections
widgetCluster.widgets.forEach((widget, widgetIndex) => {
//go through every widget in the current widget cluster
// go through each possible widget until we find one we can place
if ((deployedWidgets[widget.id] && deployedWidgets[widget.id].handledMessageIds!.includes(message.id))){
// check if the widget already exists on the screen and handles the message
const sectionID = { widgetID: widget.id, sectionID: 'none' };
const action = 'messageAlreadyHandled';
const widgetToDeploy = widget;
if (section.type === widget.sectionType) {
matchingSections.push(section); //it matches, so add it
}
});
widgetsToDeploy.push(widgetToDeploy)
actionsToDeploy.push(action)
sectionIdsToDeploy.push(sectionID)
matchingSections.forEach(function (section, sectionIndex) {
//go through each section that matches our widget's
} else if (deployedWidgets[widget.id] && !deployedWidgets[widget.id].handledMessageIds!.includes(message.id)) {
// check if the widget already exists on the screen and that the widget does not handle the message
const sectionID = { widgetID: widget.id, sectionID: 'none' };
const action = 'updateWidget';
const widgetToDeploy = widget;
//get the widgets in this section
const matchingWidgets: Widget[] = [];
section.widgetIDs.forEach(function (widgetID, widgetIDIndex) {
Object.keys(deployedWidgets).forEach((widgetId) => {
const deployedWidget = deployedWidgets[widgetId];
widgetsToDeploy.push(widgetToDeploy)
actionsToDeploy.push(action)
sectionIdsToDeploy.push(sectionID)
} else {
//the widget doesn't exist yet
if (
deployedWidget.id === widgetID &&
deployedWidget.canOverlap === false
) {
// if the widget is in this section AND it cannot be opverlapped. if it can be overlapped then we can just place on top of it so we don't need to check.
matchingWidgets.push(deployedWidget);
}
});
let widgetPlaced = false;//tracks if we have placed this the widget
//get the sections with matching types
const matchingSections: Section[] = []; //holds matching sections
sections.forEach(function (section, sectionIndex) {
//find matching sections
if (section.type === widget.sectionType) {
matchingSections.push(section); //it matches, so add it
}
});
// let x = section.x
// const xBool = x < section.x + section.w - widget.w
// console.log('xBool:', xBool)
// let y = section.y
// const yBool = y < section.y + section.h - widget.y
// console.log('yBool:', yBool)
for (let x = section.x; x < section.x + section.w - widget.w; x++) {
//go through every x value in the section that could possibly house the widget (we subtract the size of the wdiget to ensure it doesn't get placed semi-outside of the section)
// Used to be widget.y changed to widget.h - Paul
for (let y = section.y; y < section.y + section.h - widget.h; y++) {
//go through every y value in the section that could possibly house the widget (we subtract the size of the wdiget to ensure it doesn't get placed semi-outside of the section)
const proposedX = x; //the current x and y values that are proposed to be used as the top-left coordinates (can probably remove and change into x and y if we don't find more use for them later)
const proposedY = y;
let doesNotOverlap: boolean = true;
matchingSections.forEach(function (section, sectionIndex) {
//go through each section that matches our widget's
matchingWidgets.forEach(
function (deployedWidget, deployedWidgetIndex) {
if (
doesNotOverlap === true &&
doesOverlap(
proposedX,
proposedY,
widget.w,
widget.h,
deployedWidget.x,
deployedWidget.y,
deployedWidget.w,
deployedWidget.h,
) === true
) {
//it did overlap, so set it to false
doesNotOverlap = false;
}
},
);
//get the widgets in this section
const matchingWidgets: Widget[] = [];
section.widgetIDs.forEach(function (widgetID, widgetIDIndex) {
Object.keys(deployedWidgets).forEach((widgetId) => {
const deployedWidget = deployedWidgets[widgetId];
if (doesNotOverlap === true) {
//no overlap, deploy widget
widget.x = proposedX; //set widget's top-left coordinates
widget.y = proposedY;
widget.handledMessageIds = [message.id] //set widget's first message id
widgetToDeploy = widget; //the widget can be deployed
sectionID = { sectionID: section.id, widgetID: widget.id };
action = 'newWidget';
return {
widgetToDeploy,
sectionID,
action,
widgetIndex, //<- group of widgets tomorrow
};
if (
deployedWidget.id === widgetID &&
deployedWidget.canOverlap === false
) {
// if the widget is in this section AND it cannot be opverlapped. if it can be overlapped then we can just place on top of it so we don't need to check.
matchingWidgets.push(deployedWidget);
}
});
});
//set-up starting point of where to check for available space
let startingX = section.x;
let startingY = section.y;
if(Object.prototype.hasOwnProperty.call(message, 'target')){// @ts-ignore
if(message.data.target.location.x + widget.w <= section.x+section.w // @ts-ignore
&& message.data.target.location.y + widget.h <= section.y+section.h){ // @ts-ignore //use the coords given in message if they are within the section and could possibly house the widget
startingX = message.data.target.location.x;// @ts-ignore
startingY = message.data.target.location.y;
}
}
for (let x = startingX; x < section.x + section.w - widget.w; x++) {
//go through every x value in the section that could possibly house the widget (we subtract the size of the wdiget to ensure it doesn't get placed semi-outside of the section)
// Used to be widget.y changed to widget.h - Paul
for (let y = startingY; y < section.y + section.h - widget.h; y++) {
//go through every y value in the section that could possibly house the widget (we subtract the size of the wdiget to ensure it doesn't get placed semi-outside of the section)
if(!widgetPlaced){
//the widget has not been placed yet, we can still try to place it
const proposedX = x; //the current x and y values that are proposed to be used as the top-left coordinates (can probably remove and change into x and y if we don't find more use for them later)
const proposedY = y;
let doesNotOverlap: boolean = true;
matchingWidgets.forEach(
function (deployedWidget, deployedWidgetIndex) {
if (
doesNotOverlap === true &&
doesOverlap(
proposedX,
proposedY,
widget.w,
widget.h,
deployedWidget.x,
deployedWidget.y,
deployedWidget.w,
deployedWidget.h,
) === true
) {
//it did overlap, so set it to false
doesNotOverlap = false;
}
},
);
if (doesNotOverlap === true) {
widgetPlaced = true;
//no overlap, deploy widget
widget.x = proposedX; //set widget's top-left coordinates
widget.y = proposedY;
widget.handledMessageIds = [message.id] //set widget's first message id
const widgetToDeploy = widget; //the widget can be deployed
const sectionID = { sectionID: section.id, widgetID: widget.id };
const action = 'newWidget';
//push to widget cluster info
widgetsToDeploy.push(widgetToDeploy);
sectionIdsToDeploy.push(sectionID);
actionsToDeploy.push(action);
}
}
}
}
});
if (widgetPlaced === false){
allWidgetsPlaced = false;
}
});
}
});
if(allWidgetsPlaced === true){ //all widgets in this cluster were placed, we can return the cluster
widgetClusterToDeploy = {
...widgetClusterToDeploy,
widgets: widgetsToDeploy,
sectionIds: sectionIdsToDeploy,
actions: actionsToDeploy,
}
index = widgetClusterIndex;
return {
widgetClusterToDeploy,
index,
};
}
});
return {
widgetToDeploy,
sectionID,
action,
widgetClusterToDeploy,
index,
};
};

View File

@ -30,7 +30,7 @@ const reactToMessage = ({
const sections = store.getState().minimap.sections;
const widgets = store.getState().minimap.widgets;
const { possibleWidgets } = selector({
const { possibleWidgetClusters } = selector({
message: currentMessage,
stressLevel,
});
@ -38,9 +38,9 @@ const reactToMessage = ({
let resolved = false;
while(!resolved){
//console.log('running through assimilator...');
const { widgetToDeploy, sectionID, action, index} = assimilator({
const { widgetClusterToDeploy, index} = assimilator({
// find if there is room for us to put the widget down (returns null if there is not room)
possibleWidgets: possibleWidgets,
possibleWidgetClusters: possibleWidgets,
sections,
widgets,
message: currentMessage,

View File

@ -1,3 +1,5 @@
import { Widget } from "./widget";
export type Cell = {
widgetIDs: string[];
priority: number;
@ -37,3 +39,9 @@ export type Position = {
x: number;
y: number;
};
export type WidgetCluster = {
widgets: Widget[];
sectionIds?: LinkedSectionWidget[];
actions?: string[];
}