added easyOCR
This commit is contained in:
parent
37d6678577
commit
9f208b0606
27 changed files with 1780 additions and 112 deletions
115
src/inventory/InventoryTracker.ts
Normal file
115
src/inventory/InventoryTracker.ts
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import { logger } from '../util/logger.js';
|
||||
|
||||
const ROWS = 5;
|
||||
const COLS = 12;
|
||||
|
||||
interface PlacedItem {
|
||||
row: number;
|
||||
col: number;
|
||||
w: number;
|
||||
h: number;
|
||||
}
|
||||
|
||||
export class InventoryTracker {
|
||||
private grid: boolean[][];
|
||||
private items: PlacedItem[] = [];
|
||||
|
||||
constructor() {
|
||||
this.grid = Array.from({ length: ROWS }, () => Array(COLS).fill(false));
|
||||
}
|
||||
|
||||
/** Initialize from a grid scan result (occupied cells + detected items). */
|
||||
initFromScan(cells: boolean[][], items: { row: number; col: number; w: number; h: number }[]): void {
|
||||
// Reset
|
||||
for (let r = 0; r < ROWS; r++) {
|
||||
this.grid[r].fill(false);
|
||||
}
|
||||
this.items = [];
|
||||
|
||||
// Mark occupied cells from scan
|
||||
for (let r = 0; r < Math.min(cells.length, ROWS); r++) {
|
||||
for (let c = 0; c < Math.min(cells[r].length, COLS); c++) {
|
||||
this.grid[r][c] = cells[r][c];
|
||||
}
|
||||
}
|
||||
|
||||
// Record detected items
|
||||
for (const item of items) {
|
||||
this.items.push({ row: item.row, col: item.col, w: item.w, h: item.h });
|
||||
}
|
||||
|
||||
logger.info({ occupied: ROWS * COLS - this.freeCells, items: this.items.length, free: this.freeCells }, 'Inventory initialized from scan');
|
||||
}
|
||||
|
||||
/** Try to place an item of size w×h. Column-first to match game's left-priority placement. */
|
||||
tryPlace(w: number, h: number): { row: number; col: number } | null {
|
||||
for (let col = 0; col <= COLS - w; col++) {
|
||||
for (let row = 0; row <= ROWS - h; row++) {
|
||||
if (this.fits(row, col, w, h)) {
|
||||
this.place(row, col, w, h);
|
||||
logger.info({ row, col, w, h, free: this.freeCells }, 'Item placed in inventory');
|
||||
return { row, col };
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Check if an item of size w×h can fit anywhere. */
|
||||
canFit(w: number, h: number): boolean {
|
||||
for (let col = 0; col <= COLS - w; col++) {
|
||||
for (let row = 0; row <= ROWS - h; row++) {
|
||||
if (this.fits(row, col, w, h)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Get all placed items. */
|
||||
getItems(): PlacedItem[] {
|
||||
return [...this.items];
|
||||
}
|
||||
|
||||
/** Get a copy of the occupancy grid. */
|
||||
getGrid(): boolean[][] {
|
||||
return this.grid.map(row => [...row]);
|
||||
}
|
||||
|
||||
/** Clear entire grid. */
|
||||
clear(): void {
|
||||
for (let r = 0; r < ROWS; r++) {
|
||||
this.grid[r].fill(false);
|
||||
}
|
||||
this.items = [];
|
||||
logger.info('Inventory cleared');
|
||||
}
|
||||
|
||||
/** Get remaining free cells count. */
|
||||
get freeCells(): number {
|
||||
let count = 0;
|
||||
for (let r = 0; r < ROWS; r++) {
|
||||
for (let c = 0; c < COLS; c++) {
|
||||
if (!this.grid[r][c]) count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private fits(row: number, col: number, w: number, h: number): boolean {
|
||||
for (let r = row; r < row + h; r++) {
|
||||
for (let c = col; c < col + w; c++) {
|
||||
if (this.grid[r][c]) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private place(row: number, col: number, w: number, h: number): void {
|
||||
for (let r = row; r < row + h; r++) {
|
||||
for (let c = col; c < col + w; c++) {
|
||||
this.grid[r][c] = true;
|
||||
}
|
||||
}
|
||||
this.items.push({ row, col, w, h });
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue