Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// בס"ד
import type { Match, ShootEvent } from "@repo/scouting_types";
import type { BPS, FuelObject } from "./fuel-object";
import type { BPS, FuelObject } from "../fuel-object";
import { calculateSum, firstElement, lastElement } from "@repo/array-functions";

const EMPTY_INTERVAL_DURATION = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// בס"ד
import type { ShootEvent } from "@repo/scouting_types";
import type { BPS, FuelObject } from "./fuel-object";
import type { BPS, FuelObject } from "../fuel-object";

const getIncludedShots = (section: number[], shot: ShootEvent) => {
return section.filter(
Expand Down
33 changes: 33 additions & 0 deletions apps/scouting/backend/src/fuel/distance-split.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// בס"ד
import { convertPixelToCentimeters, distanceFromHub } from "@repo/rebuilt_map";
import type { FuelEvents, FuelObject } from "./fuel-object";
import { calculateAverage } from "@repo/array-functions";

const averageFuel = (fuels: FuelObject[]): FuelObject => {
const averageOfKey = (key: FuelEvents) =>
calculateAverage(fuels, (value) => value[key]);
return {
scored: averageOfKey("scored"),
shot: averageOfKey("shot"),
missed: averageOfKey("missed"),
positions: fuels.flatMap((fuel) => fuel.positions),
};
};

export const splitByDistances = <T extends number>(
fuels: FuelObject[],
distances: T[],
): Record<T, FuelObject> =>
Object.assign(
{},
...distances.map((distance) => ({
[distance]: averageFuel(
fuels.filter((fuel) =>
fuel.positions.every(
(position) =>
distanceFromHub(convertPixelToCentimeters(position)) < distance,
),
),
),
})),
);
6 changes: 3 additions & 3 deletions apps/scouting/backend/src/fuel/fuel-object.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// בס"ד
import type { GameObject } from "../game-object";
import type { Match, Point, ShootEvent } from "@repo/scouting_types";
import { calculateFuelByAveraging } from "./fuel-averaging";
import { calculateFuelByMatch } from "./fuel-match";
import { calculateFuelByAveraging } from "./calculations/fuel-averaging";
import { calculateFuelByMatch } from "./calculations/fuel-match";

export interface BPS {
events: { shoot: number[]; score: number[] }[];
match: Match;
}

type FuelEvents = "scored" | "shot" | "missed";
export type FuelEvents = "scored" | "shot" | "missed";
export type FuelObject = GameObject<
FuelEvents,
{
Expand Down
52 changes: 31 additions & 21 deletions apps/scouting/frontend/src/scouter/components/ScoreMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import {
type Touch,
} from "react";
import type { Alliance, Point } from "@repo/scouting_types";
import {
ALLIANCE_ZONE_WIDTH_PIXELS,
FIELD_HEIGHT_PIXELS,
TWO_THIRDS_FIELD_WIDTH_PIXELS,
blueField,
redField,
} from "@repo/rebuilt_map";
import { pipe } from "fp-ts/lib/function";

interface ScoreMapProps {
Expand All @@ -19,17 +26,14 @@ interface ScoreMapProps {
mapZone: Alliance;
}

const ALLIANCE_ZONE_WIDTH_PIXELS = 395;
const TWO_THIRDS_WIDTH_PIXELS = 1010;
const HEIGHT_PIXELS = 652;
const alliancizePosition = (alliance: Alliance, position: Point): Point => {
if (alliance === "red") {
return position;
}

return {
x: TWO_THIRDS_WIDTH_PIXELS - position.x,
y: HEIGHT_PIXELS - position.y,
x: TWO_THIRDS_FIELD_WIDTH_PIXELS - position.x,
y: FIELD_HEIGHT_PIXELS - position.y,
};
};

Expand All @@ -41,8 +45,8 @@ const switchZone = (point: Point) => {
};

const normalizePosition = (point: Point, bounds: Point) => ({
x: (point.x * TWO_THIRDS_WIDTH_PIXELS) / bounds.x,
y: (point.y * HEIGHT_PIXELS) / bounds.y,
x: (point.x * TWO_THIRDS_FIELD_WIDTH_PIXELS) / bounds.x,
y: (point.y * FIELD_HEIGHT_PIXELS) / bounds.y,
});

const dotRadius = 10;
Expand All @@ -51,11 +55,17 @@ const dotDiameter = dotRadius * radiusToDiameterRatio;

const firstTouchIndex = 0;
export const defaultPoint: Point = { x: 0, y: 0 };

interface RobotPositionInfo {
mapPoint: Point;
normalizedPoint: Point;
imageSize: Point;
}
const getRobotPosition = (
touch: Touch,
imageRect: DOMRect,
containerRect: DOMRect,
) => {
): RobotPositionInfo => {
const x = touch.clientX - imageRect.left;
const y = touch.clientY - imageRect.top;

Expand All @@ -77,12 +87,12 @@ const getRobotPosition = (
y: boundedY + imageRect.top - containerRect.top,
},
normalizedPoint: {
x: boundedX,
y: boundedY
},
imageSize: {
x: imageRect.width,
y: imageRect.height
x: boundedX,
y: boundedY,
},
imageSize: {
x: imageRect.width,
y: imageRect.height,
},
};
};
Expand All @@ -103,18 +113,18 @@ export const ScoreMap: FC<ScoreMapProps> = ({
}
const containerElement = containerRef.current;
const imageElement = imageRef.current;
if (!(containerElement&&imageElement)) {
if (!(containerElement && imageElement)) {
return;
}
const containerRect = containerElement.getBoundingClientRect();
const imageRect = imageElement.getBoundingClientRect();
const touch = event.targetTouches[firstTouchIndex];

const { mapPoint: dotPoint, normalizedPoint, imageSize } = getRobotPosition(
touch,
imageRect,
containerRect,
);
const {
mapPoint: dotPoint,
normalizedPoint,
imageSize,
} = getRobotPosition(touch, imageRect, containerRect);

setMapPoint(dotPoint);

Expand All @@ -136,7 +146,7 @@ export const ScoreMap: FC<ScoreMapProps> = ({
>
<img
ref={imageRef}
src={`/${mapZone}-field-4418.png`}
src={mapZone === "red" ? redField : blueField}
onTouchMove={handleMapClick}
onTouchStart={() => {
setHolding(true);
Expand Down
5 changes: 5 additions & 0 deletions packages/array-functions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ export const calculateSum = <T>(
): number =>
arr.reduce((sum, value) => sum + transformation(value), startingSumValue);

export const calculateAverage = <T>(
arr: T[],
transformation: (value: T) => number,
): number => calculateSum(arr, transformation) / arr.length;

export const getMax = <T>(arr: T[], transformation: (value: T) => number): T =>
arr
.map((item) => ({ value: transformation(item), item }))
Expand Down
3 changes: 3 additions & 0 deletions packages/rebuilt-map/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// בס"ד
export * from "./map";
export * from "./units";
5 changes: 5 additions & 0 deletions packages/rebuilt-map/map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// בס"ד
import blue from "./images/blue-field-4418.png";
export const blueField = blue;
import red from "./images/red-field-4418.png";
export const redField = red;
13 changes: 13 additions & 0 deletions packages/rebuilt-map/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "@repo/rebuilt_map",
"version": "0.1.0",
"type": "module",
"private": true,
"exports": {
".": "./index.ts"
},
"dependencies": {},
"devDependencies": {
"typescript": "latest"
}
}
32 changes: 32 additions & 0 deletions packages/rebuilt-map/units.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// בס"ד
import type { Point } from "@repo/scouting_types";

export const ALLIANCE_ZONE_WIDTH_PIXELS = 395;
export const TWO_THIRDS_FIELD_WIDTH_PIXELS = 1010;
export const FIELD_HEIGHT_PIXELS = 652;

const FIELD_SIZE_CENTIMETERS: Point = {
x: 1654,
y: 807,
};
const CENTER_HUB_POINT_CENTIMETERS: Point = {
x: 462.534,
y: 403.5,
};

export const convertPixelToCentimeters = (point: Point): Point => ({
x: (point.x / TWO_THIRDS_FIELD_WIDTH_PIXELS) * FIELD_SIZE_CENTIMETERS.x,
y: (point.y / FIELD_HEIGHT_PIXELS) * FIELD_SIZE_CENTIMETERS.y,
});

const distanceFromDifference = (difference: Point): number =>
Math.sqrt(difference.x * difference.x + difference.y * difference.y);

const distance = (p1: Point, p2: Point): number =>
distanceFromDifference({
x: p1.x - p2.x,
y: p1.y - p2.y,
});

export const distanceFromHub = (point: Point): number =>
distance(point, CENTER_HUB_POINT_CENTIMETERS);
Loading