Merge branch 'main' into lpd

This commit is contained in:
polpol 2024-04-17 13:51:33 -07:00
commit 726576673f
8 changed files with 272 additions and 253 deletions

View File

@ -1,8 +1,10 @@
import Prototype2 from 'src/components/Prototype2';
import 'src/App.css';
import { useState } from 'react';
import Prototype3 from './components/Prototype3';
const App = () => {
return <Prototype2 />;
return <Prototype3 />;
};
export default App;

View File

@ -16,14 +16,16 @@ const Layout = ({ widgets }: LayoutProps) => {
const [layout, setLayout] = useState<LayoutType[]>([
/* { i: 'tinder', x: 0, y: 0, w: 300, h: 1080, static: true }, */
{ i: 'drone1', x: 500, y: 200, w: 50, h: 50 },
{ i: 'drone2', x: 1500, y: 300, w: 50, h: 50 },
{ i: 'drone3', x: 1200, y: 700, w: 50, h: 50 },
{ i: 'drone2', x: 1500, y: 550, w: 50, h: 50 },
{ i: 'drone4', x: 1500, y: 350, w: 50, h: 50 },
{ i: 'drone5', x: 200, y: 900, w: 50, h: 50 },
{ i: 'drone3', x: 1150, y: 750, w: 50, h: 50 },
{ i: 'ownship', x: 400, y: 950, w: 50, h: 50, isDraggable: true },
]);
useEffect(() => {
if (widgets.length > 0) {
const { id: widgetId, x, y, w, h } = widgets[widgets.length - 1];
const { id: widgetId, type, x, y, w, h } = widgets[widgets.length - 1];
setLayout((prevLayout) => {
// if widgetId is in layout, return layout as is
@ -34,12 +36,29 @@ const Layout = ({ widgets }: LayoutProps) => {
// add new widget to widgetMap
const div = document.createElement('div');
div.id = widgetId;
div.style.position = 'relative';
div.style.position = 'absolute';
div.style.left = `${x}px`;
div.style.top = `${y}px`;
div.style.width = `${w}px`;
div.style.height = `${h}px`;
div.style.backgroundColor = 'blue';
div.style.opacity = '0.5';
div.style.border = 'solid';
let bgColor = 'red';
if (type === 'tinder') {
bgColor = 'green';
}
if (type === 'message') {
bgColor = 'blue';
}
if (type === 'lowWarning') {
bgColor = 'orange';
}
div.style.backgroundColor = bgColor;
div.style.zIndex = '100';
layoutRef.current?.appendChild(div);
@ -95,15 +114,15 @@ const Layout = ({ widgets }: LayoutProps) => {
bottom: 50,
};
const droneMove = {
x: 10,
x: 5,
y: 0,
};
setLayout((prevLayout) =>
prevLayout.map((item) => {
if (item.i.includes('drone')) {
droneMove.x = Math.floor(Math.random() * 20) - 10;
droneMove.y = Math.floor(Math.random() * 20) - 10;
droneMove.x = Math.floor(Math.random() * 10) - 5;
droneMove.y = Math.floor(Math.random() * 10) - 5;
// only move drone if within defined bounds
if (
@ -130,41 +149,45 @@ const Layout = ({ widgets }: LayoutProps) => {
return item;
}),
);
}, 1000);
}, 1500);
return () => clearInterval(timer);
}, []);
return (
<div className="h-screen flex items-center justify-center">
<div className="bg-red-300 w-[1920px] h-[1080px] hover:cursor-pointer">
<GridLayout
cols={1920}
width={1920}
layout={layout}
rowHeight={1}
margin={[0, 0]}
isBounded={true}
isResizable={false}
compactType={null}
allowOverlap={true}
preventCollision={true}
innerRef={layoutRef}
>
<div key="drone1">
<GiDeliveryDrone size={50} />
</div>
<div key="drone2">
<GiDeliveryDrone size={50} />
</div>
<div key="drone3">
<GiDeliveryDrone size={50} />
</div>
<div key="ownship">
<FaLocationArrow size={50} />
</div>
</GridLayout>
</div>
<div className="absolute top-0 left-0 bg-stone-300 w-[1920px] h-[1080px] hover:cursor-pointer">
<GridLayout
cols={1920}
width={1920}
layout={layout}
rowHeight={1}
margin={[0, 0]}
isBounded={true}
isResizable={false}
compactType={null}
allowOverlap={true}
preventCollision={true}
innerRef={layoutRef}
>
<div key="drone1">
<GiDeliveryDrone size={50} />
</div>
<div key="drone2">
<GiDeliveryDrone size={50} />
</div>
<div key="drone3">
<GiDeliveryDrone size={50} />
</div>
<div key="drone4">
<GiDeliveryDrone size={50} />
</div>
<div key="drone5">
<GiDeliveryDrone size={50} />
</div>
<div key="ownship">
<FaLocationArrow size={50} />
</div>
</GridLayout>
</div>
);
};

View File

@ -18,7 +18,7 @@ import { useAppDispatch, useAppSelector } from 'src/redux/hooks';
import type { Widget, Element } from 'src/types/modalities';
import { useEffect, useRef, useState } from 'react';
import Layout from 'src/components/Layout';
import type { Section } from 'src/types/support-types.ts';
import type { Section } from 'src/types/support-types';
import { v4 as uuid } from 'uuid';
import assimilator from 'src/prototype/assimilator';
import selector from 'src/prototype/selector';
@ -43,13 +43,20 @@ const Prototype2 = () => {
const listOfMsg = [
'tinder',
'AcaHeadingToBase',
'AcaHeadingToBase',
'tinder',
'RequestApprovalToAttack',
'MissileToOwnshipDetected',
'AcaHeadingToBase',
'AcaFuelLow',
];
//messages and their corresponding section type (for quick reference)
// 'tinder', -> tinder
// 'AcaHeadingToBase', -> message
// 'RequestApprovalToAttack', -> request
// 'MissileToOwnshipDetected', -> highWarning
// 'AcaFuelLow', -> lowWarning
const generateMessage = () => {
if (msgIndex >= listOfMsg.length) return;
@ -59,7 +66,7 @@ const Prototype2 = () => {
};
// generate message every five seconds
const interval = setInterval(generateMessage, ONE_SECOND_IN_MS * 5);
const interval = setInterval(generateMessage, ONE_SECOND_IN_MS * 10);
return () => clearInterval(interval);
}, []);
@ -91,6 +98,7 @@ const Prototype2 = () => {
if (widgetToDeploy) {
console.log('widget deployed:', widgetToDeploy);
console.log('widgets that are now deployed: ', widgets);
//if we can actually place the widget
//ADD RESTRAINER HERE TO CHECK IF WE CAN PLACE THE WIDGET
@ -112,7 +120,6 @@ const Prototype2 = () => {
// only run in the first render
firstRender1.current = false;
const tinderSection: Section = {
x: 50,
y: 40,
@ -126,8 +133,8 @@ const Prototype2 = () => {
dispatch(addMapSection(tinderSection));
const requestSection: Section = {
x: 1000,
y: 500,
x: 50,
y: 850,
w: 800,
h: 200,
priority: 10,
@ -138,10 +145,10 @@ const Prototype2 = () => {
dispatch(addMapSection(requestSection));
const highWarningSection: Section = {
x: 500,
x: 800,
y: 200,
w: 100,
h: 100,
w: 500,
h: 250,
priority: 10,
type: 'highWarning',
};
@ -149,12 +156,11 @@ const Prototype2 = () => {
console.log('dispatching addMapSection');
dispatch(addMapSection(highWarningSection));
const lowWarningSection: Section = {
x: 200,
y: 400,
w: 100,
h: 100,
x: 1800,
y: 450,
w: 500,
h: 200,
priority: 10,
type: 'lowWarning',
};
@ -163,7 +169,7 @@ const Prototype2 = () => {
dispatch(addMapSection(lowWarningSection));
const messageSection: Section = {
x: 1500,
x: 1800,
y: 200,
w: 200,
h: 200,
@ -175,110 +181,28 @@ const Prototype2 = () => {
dispatch(addMapSection(messageSection));
}
// call assimilator and add widget to state if it can find a space
// useEffect(() => {
// console.log('running through assimilator...');
// const topHalf: Element = {
// id: 'topHalf',
// modality: 'visual',
// type: 'text',
// xWidget: 10,
// yWidget: 0,
// w: 30,
// h: 24,
// };
// const bottomHalf: Element = {
// id: 'bottomHalf',
// modality: 'visual',
// type: 'text',
// xWidget: 10,
// yWidget: 25,
// w: 30,
// h: 25,
// };
// const widget: Widget = {
// id: 'tinder',
// elements: [topHalf, bottomHalf],
// type: 'tinder',
// maxAmount: 1,
// x: 100,
// y: 200,
// w: 50,
// h: 50,
// useElementLocation: false,
// canOverlap: false,
// };
return (
<div>
<Layout widgets={widgets} />
// // call assimilator here...
// const { widgetToDeploy } = assimilator({
// // find if there is room for us to put the widget down (returns null if there is not room)
// possibleWidgets: [widget],
// pixelMap,
// sections,
// });
// console.log('widgetToDeploy ' + widgetToDeploy);
// if (widgetToDeploy) {
// console.log('widget deployed:', widgetToDeploy);
// //if we can actually place the widget
// //ADD RESTRAINER HERE TO CHECK IF WE CAN PLACE THE WIDGET
// /* if (
// !restrainer({
// visualComplexity: generateModalityMeasure(),
// audioComplexity: generateModalityMeasure(),
// })
// )
// return; */
// // dispatch action to add new widget
// dispatch(addWidget(widgetToDeploy));
// }
// }, []);
// let coin = 0;
// useEffect(() => {
// if (coin < listOfMsg.length) {
// //get next message
// const currentMessage = listOfMsg[coin];
// const { message, possibleWidgets } = selector({
// message: currentMessage,
// });
// console.log('running through assimilator...');
// // call assimilator here...
// const { widgetToDeploy } = assimilator({
// // find if there is room for us to put the widget down (returns null if there is not room)
// possibleWidgets: possibleWidgets,
// pixelMap,
// sections,
// });
// console.log('widgetToDeploy ' + widgetToDeploy);
// if (widgetToDeploy) {
// console.log('widget deployed:', widgetToDeploy);
// //if we can actually place the widget
// //ADD RESTRAINER HERE TO CHECK IF WE CAN PLACE THE WIDGET
// /* if (
// !restrainer({
// visualComplexity: generateModalityMeasure(),
// audioComplexity: generateModalityMeasure(),
// })
// )
// return; */
// // dispatch action to add new widget
// dispatch(addWidget(widgetToDeploy));
// }
// coin++; //increment coin to next message
// }
// }, []);
return <Layout widgets={widgets} />;
<div className="absolute top-0 right-0 w-[30rem] flex flex-col gap-4">
<div className="bg-green-200 w-full h-96 px-2 py-1">
<p className="text-center text-5xl">List of Messages:</p>
<ul className="overflow-y-scroll divide-y divide-stone-500 h-80">
{messages.map((msg) => (
<li key={msg}>
<div>
<span className="text-3xl">
{msg === 'tinder' ? 'Tinder Message' : msg}
</span>
</div>
</li>
))}
</ul>
</div>
</div>
</div>
);
};
export default Prototype2;

View File

@ -0,0 +1,19 @@
import { useState } from 'react';
import Layout from './Layout';
import { useAppSelector } from 'src/redux/hooks';
import { getSections, getWidgets } from 'src/redux/slices/cmSlice';
const Prototype3 = () => {
const [messages, setMessages] = useState<string[]>([]);
const sections = useAppSelector(getSections);
const widgets = useAppSelector(getWidgets);
return (
<>
<Layout widgets={widgets} />
</>
);
};
export default Prototype3;

View File

@ -3,7 +3,7 @@ import { v4 as uuid } from 'uuid';
import type { Element, Widget } from 'src/types/modalities';
type SelectorProps = {
message: string;//Message;
message: string; //Message;
};
/**
@ -25,28 +25,30 @@ const selector = ({ message }: SelectorProps) => {
// simulation LPD
if (message === 'RequestApprovalToAttack') {
const elements: Element[] = [{
expirationInterval: 5,
expiration: 'Yes',
onExpiration: 'escalate',
interacted: false,
id: uuid(),
modality: 'visual',
type: 'button',
xWidget: 0,
yWidget: 0,
h: 5,
w:5,
canOverlap: false,
}];
const elements: Element[] = [
{
expirationInterval: 5,
expiration: 'Yes',
onExpiration: 'escalate',
interacted: false,
id: uuid(),
modality: 'visual',
type: 'button',
xWidget: 0,
yWidget: 0,
h: 5,
w: 5,
canOverlap: false,
},
];
const widget: Widget = {
id: 'request',
maxAmount: 1,
x: 0,
y: 0,
h: 50,
w: 50,
h: 80,
w: 140,
type: 'request',
useElementLocation: true,
canOverlap: false,
@ -76,28 +78,30 @@ const selector = ({ message }: SelectorProps) => {
// type: 'icon',
// onExpiration,
//});
const elements: Element[] = [{
expirationInterval: 5,
expiration: 'Yes',
onExpiration: 'escalate',
interacted: false,
id: uuid(),
modality: 'visual',
type: 'icon',
xWidget: 0,
yWidget: 0,
h: 5,
w:5,
canOverlap: false,
}];
const elements: Element[] = [
{
expirationInterval: 5,
expiration: 'Yes',
onExpiration: 'escalate',
interacted: false,
id: uuid(),
modality: 'visual',
type: 'icon',
xWidget: 0,
yWidget: 0,
h: 5,
w: 5,
canOverlap: false,
},
];
const widget: Widget = {
id: 'highWarning',
maxAmount: 1,
x: 0,
y: 0,
h: 50,
w: 50,
h: 200,
w: 400,
type: 'highWarning',
useElementLocation: true,
canOverlap: false,
@ -113,20 +117,22 @@ const selector = ({ message }: SelectorProps) => {
// type: 'table',
// onExpiration,
//});
const elements: Element[] = [{
expirationInterval: 5,
expiration: 'Yes',
onExpiration: 'delete',
interacted: false,
id: uuid(),
modality: 'visual',
type: 'table',
xWidget: 0,
yWidget: 0,
h: 5,
w:5,
canOverlap: true,
}];
const elements: Element[] = [
{
expirationInterval: 5,
expiration: 'Yes',
onExpiration: 'delete',
interacted: false,
id: uuid(),
modality: 'visual',
type: 'table',
xWidget: 0,
yWidget: 0,
h: 5,
w: 5,
canOverlap: true,
},
];
const widget: Widget = {
id: 'lowWarning',
@ -157,20 +163,22 @@ const selector = ({ message }: SelectorProps) => {
// type: 'text',
// onExpiration,
//});
const elements: Element[] = [{
expirationInterval: 5,
expiration: 'Yes',
onExpiration: 'escalate',
interacted: false,
id: uuid(),
modality: 'visual',
type: 'text',
xWidget: 0,
yWidget: 0,
h: 5,
w:5,
canOverlap: true,
}];
const elements: Element[] = [
{
expirationInterval: 5,
expiration: 'Yes',
onExpiration: 'escalate',
interacted: false,
id: uuid(),
modality: 'visual',
type: 'text',
xWidget: 0,
yWidget: 0,
h: 5,
w: 5,
canOverlap: true,
},
];
const widget: Widget = {
id: 'message',
@ -186,39 +194,39 @@ const selector = ({ message }: SelectorProps) => {
};
possibleWidgets.push(widget);
} else if ( message === 'tinder'){
} else if (message === 'tinder') {
const topHalf: Element = {
id: 'topHalf',
modality: 'visual',
type: 'text',
xWidget: 10,
yWidget: 0,
w: 30,
h: 24,
};
const bottomHalf: Element = {
id: 'bottomHalf',
modality: 'visual',
type: 'text',
xWidget: 10,
yWidget: 25,
w: 30,
h: 25,
};
const widget: Widget = {
id: 'tinder',
elements: [topHalf, bottomHalf],
type: 'tinder',
maxAmount: 1,
x: 100,
y: 200,
w: 50,
h: 50,
useElementLocation: false,
canOverlap: false,
};
id: 'topHalf',
modality: 'visual',
type: 'text',
xWidget: 10,
yWidget: 0,
w: 30,
h: 24,
};
const bottomHalf: Element = {
id: 'bottomHalf',
modality: 'visual',
type: 'text',
xWidget: 10,
yWidget: 25,
w: 30,
h: 25,
};
const widget: Widget = {
id: uuid(),
elements: [topHalf, bottomHalf],
type: 'tinder',
maxAmount: 1,
x: 150,
y: 200,
w: 160,
h: 300,
useElementLocation: false,
canOverlap: false,
};
possibleWidgets.push(widget);
possibleWidgets.push(widget);
}
return {
@ -228,4 +236,3 @@ const selector = ({ message }: SelectorProps) => {
};
export default selector;

18
src/ui/Button1.tsx Normal file
View File

@ -0,0 +1,18 @@
type ButtonProps = {
text: string;
onClick: () => void;
};
const Button = ({ text, onClick }: ButtonProps) => {
<button
onClick={onClick}
className="w-100 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 text-4xl"
>
{text}
</button>;
};
export default Button;

26
src/ui/MessageList.tsx Normal file
View File

@ -0,0 +1,26 @@
import type { Message } from 'src/types/schema-types';
type MessageListProps = {
messages: Message[];
};
const MessageList = ({ messages }: MessageListProps) => {
/* return (
<div className="bg-green-200 w-[30rem] h-96 px-2 py-1">
<p className="text-center text-5xl">List of Messages:</p>
<ul className="overflow-y-scroll divide-y divide-stone-500 h-80">
{messages.map((msg) => (
<li key={msg}>
<div>
<span className="text-3xl">
{msg === 'tinder' ? 'Tinder Message' : msg}
</span>
</div>
</li>
))}
</ul>
</div>
); */
};
export default MessageList;

View File

@ -3,6 +3,6 @@ export const ONE_SECOND_IN_MS = 1000;
export const OWNSHIP_TRAJECTORY = {
start: [400, 950],
end: [1800, 50],
xSpeed: 10,
ySpeed: 7,
xSpeed: 7,
ySpeed: 4,
};