From 04828b94e9df8321feae0bfb99daa468c0d3d383 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 23 Jul 2019 13:57:20 +0200 Subject: [roomplanner] Support creating recursive/composed rooms --- .../roomplanner/inc/pvsgenerator.inc.php | 206 ++++----------------- 1 file changed, 35 insertions(+), 171 deletions(-) (limited to 'modules-available/roomplanner/inc/pvsgenerator.inc.php') diff --git a/modules-available/roomplanner/inc/pvsgenerator.inc.php b/modules-available/roomplanner/inc/pvsgenerator.inc.php index cfb38fd2..3646ae6a 100644 --- a/modules-available/roomplanner/inc/pvsgenerator.inc.php +++ b/modules-available/roomplanner/inc/pvsgenerator.inc.php @@ -1,77 +1,31 @@ fetch(PDO::FETCH_ASSOC)) { - $row['locationname'] = str_replace(',', ';', $row['locationname']); // comma probably not the best sep here - settype($row['locationid'], 'int'); - settype($row['parentlocationid'], 'int'); - $rooms[$row['locationid']] = $row; - } - // Mark all non-leafs as skip - foreach ($rooms as &$room) { - if ($room['parentlocationid'] > 0 && isset($rooms[$room['parentlocationid']])) { - $rooms[$room['parentlocationid']]['skip'] = true; // Don't just unset, might be wrong order - } - } - // Now un-mark all where there's at least one child without valid room plan - foreach ($rooms as &$room) { - if (!isset($room['skip']) && (is_null($room['notnull']) || empty($room['managerip']))) { - $room['skip'] = true; - $r2 =& $room; - while ($r2['parentlocationid'] > 0) { - $r2 =& $rooms[$r2['parentlocationid']]; - if (!(is_null($room['notnull']) || empty($room['managerip']))) { - unset($r2['skip']); - break; - } - } - } - } - unset($room, $r2); // refd! - /* collect names and build room blocks - filter empty rooms while at it */ $roomNames = array(); $roomBlocks = ''; + $rooms = Room::getAll(); foreach ($rooms as $room) { - if (is_null($room['notnull']) || isset($room['skip'])) // Not leaf + if ($room->shouldSkip()) continue; - if (Module::isAvailable('runmode')) { - $pc = RunMode::getForMode('roomplanner', $room['locationid'], true); - if (!empty($pc)) { - $pc = array_pop($pc); - $room['managerip'] = $pc['clientip']; - } - } - if (empty($room['managerip'])) // rooms without managerips don't make sense + if ($room->getManagerIp() === false) // No .ini entry for rooms without manager (do we want this?) continue; $roomBlock = PvsGenerator::generateRoomBlock($room); if ($roomBlock === false) continue; // Room nonexistent or empty - $roomNames[] = md5($room['locationname']); - $roomBlocks .= $roomBlock; + $section = substr(md5($room->locationId() . '-' . $room->locationName()), 0, 10); + $roomNames[] = $section; + $roomBlocks .= "[$section]\n" . $roomBlock; } /* output room plus [General]-block */ return "[General]\n" . 'rooms=' . implode(', ', $roomNames) . "\n" . "allowClientQuit=False\n" // TODO: configurable - . "showLockDesktopButton=True\n" // TODO: Make this configurable (or not) . "\n\n" . $roomBlocks; } @@ -79,69 +33,36 @@ class PvsGenerator /** * Generate .ini section for specific room. * - * @param $room array room/location data as fetched from db - * @return string|bool .ini section for room, or false if room is empty + * @param Room $room room/location data as fetched from db + * @return string|false .ini section for room, or false if room is empty */ private static function generateRoomBlock($room) { - $out = '[' . md5($room['locationname']) . "]\n"; - - - /* find all clients in that room */ - $machines = PvsGenerator::getMachines($room['locationid']); - if (empty($machines)) + $room->getSize($sizeX, $sizeY); + if ($sizeX === 0 || $sizeY === 0) + return false; + $count = 0; + $section = $room->getIniClientSection($count); + if ($section === false) return false; - $out .= "name=" . $room['locationname'] . "\n"; + $cs = SimpleRoom::CLIENT_SIZE; + $out = "name=" . $room->locationName() . "\n"; /* manager */ - $mgr = $room['managerip']; - $tutor = $room['tutorip']; - if ($mgr) { - $out .= 'mgrIP=' . $mgr . "\n"; - } + $out .= 'mgrIP=' . $room->getManagerIp() . "\n"; /* tutor */ - if ($tutor) { - $out .= 'tutorIP=' . $tutor . "\n"; + if ($room->getTutorIp() !== false) { + $out .= 'tutorIP=' . $room->getTutorIp() . "\n"; } - /* grid */ - $out .= PvsGenerator::generateGrid($machines); - - return $out . "\n"; - } - - /** - * Generate grid size information and client position data for given clients. - * - * @param $machines array list of clients - * @return string grid and position data as required for a room's .ini section - */ - private static function generateGrid($machines) - { - $out = ""; - - /* find bounding box */ - PvsGenerator::boundingBox($machines, $minX, $minY, $maxX, $maxY); - $clientSizeX = 4; /* TODO: optimize */ - $clientSizeY = 4; /* TODO: optimize */ - $sizeX = max($maxX - $minX + $clientSizeX, 1); /* never negative */ - $sizeY = max($maxY - $minY + $clientSizeY, 1); /* and != 0 to avoid divide-by-zero in pvsmgr */ - - /* output basic settings for this room */ + /* basic settings for this room */ $out .= "gridSize=@Size($sizeX $sizeY)\n"; - $out .= "clientSize=@Size($clientSizeX $clientSizeY)\n"; - $out .= "client\\size=" . count($machines) . "\n"; - - /* output individual client positions, shift coordinates to origin */ - $i = 1; - foreach ($machines as $pos) { - $out .= "client\\$i\\ip={$pos['clientip']}\n"; - $out .= "client\\$i\\pos=@Point(" . ($pos['gridCol'] - $minX) . ' ' . ($pos['gridRow'] - $minY) . ")\n"; - $i++; - } + $out .= "clientSize=@Size($cs $cs)\n"; + $out .= "client\\size=$count\n"; - return $out; + /* output with grid */ + return $out . $section . "\n"; } /** @@ -154,6 +75,7 @@ class PvsGenerator * @param int|false $locationId * @param string|false $highlightUuid * @param int $rotate rotate plan (0-3 for N E S W up, -1 for "auto" if highlightUuid is given) + * @param float $scale scaling factor for output * @return string SVG */ public static function generateSvg($locationId = false, $highlightUuid = false, $rotate = 0, $scale = 1) @@ -167,10 +89,15 @@ class PvsGenerator return false; $locationId = $locationId['fixedlocationid']; } - $machines = self::getMachines($locationId); - if (empty($machines)) + // Load room + $room = Room::get($locationId); + if ($room === false) return false; + $room->getSize($sizeX, $sizeY); + if ($sizeX === 0 || $sizeY === 0) + return false; // Empty + $machines = $room->getShiftedArray(); $ORIENTATION = ['north' => 2, 'east' => 3, 'south' => 0, 'west' => 1]; if (is_string($highlightUuid)) { $highlightUuid = strtoupper($highlightUuid); @@ -186,22 +113,13 @@ class PvsGenerator } } $rotate %= 4; - // Highlight given machine, rotate it's "keyboard" + // Highlight given machine, rotate its "keyboard" foreach ($machines as &$machine) { if ($machine['machineuuid'] === $highlightUuid) { $machine['class'] = 'hl'; } $machine['rotation'] = $ORIENTATION[$machine['rotation']] * 90; } - PvsGenerator::boundingBox($machines, $minX, $minY, $maxX, $maxY); - $clientSizeX = 4; /* this is optimal */ - $clientSizeY = 4; - $minX--; - $minY--; - $maxX++; - $maxY++; - $sizeX = max($maxX - $minX + $clientSizeX, 1); /* never negative */ - $sizeY = max($maxY - $minY + $clientSizeY, 1); /* and != 0 to avoid divide-by-zero in pvsmgr */ if ($rotate === 0) { $centerY = $centerX = 0; } elseif ($rotate === 1) { @@ -221,11 +139,8 @@ class PvsGenerator 'centerX' => $centerX, 'centerY' => $centerY, 'rotate' => $rotate * 90, - 'shiftX' => -$minX, - 'shiftY' => -$minY, 'machines' => $machines, - 'line' => ['x1' => $minX, 'y1' => $maxY + $clientSizeY, - 'x2' => $maxX + $clientSizeX, 'y2' => $maxY + $clientSizeY], + 'line' => ['x' => $sizeX, 'y' => $sizeY], ], 'roomplanner'); // FIXME: Needs module param if called from api.inc.php } @@ -236,58 +151,6 @@ class PvsGenerator $b = $tmp; } - /** - * Get all clients for given room with IP and position. - * - * @param $roomid int locationid of room - * @return array - */ - private static function getMachines($roomid) - { - $ret = Database::simpleQuery( - 'SELECT machineuuid, clientip, position FROM machine WHERE fixedlocationid = :locationid', - ['locationid' => $roomid]); - - $machines = array(); - - while ($row = $ret->fetch(PDO::FETCH_ASSOC)) { - $position = json_decode($row['position'], true); - - if ($position === false || !isset($position['gridRow']) || !isset($position['gridCol'])) - continue; // TODO: Remove entry/set to NULL? - - $rotation = 'north'; - if (preg_match('/(north|east|south|west)/', $position['itemlook'], $out)) { - $rotation = $out[1]; - } - $machines[] = array( - 'machineuuid' => $row['machineuuid'], - 'clientip' => $row['clientip'], - 'gridRow' => $position['gridRow'], - 'gridCol' => $position['gridCol'], - 'rotation' => $rotation, - ); - } - - return $machines; - - } - - private static function boundingBox($machines, &$minX, &$minY, &$maxX, &$maxY) - { - $minX = PHP_INT_MAX; /* PHP_INT_MIN is only available since PHP 7 */ - $maxX = ~PHP_INT_MAX; - $minY = PHP_INT_MAX; - $maxY = ~PHP_INT_MAX; - - foreach ($machines as $pos) { - $minX = min($minX, $pos['gridCol']); - $maxX = max($maxX, $pos['gridCol']); - $minY = min($minY, $pos['gridRow']); - $maxY = max($maxY, $pos['gridRow']); - } - } - public static function runmodeConfigHook($machineUuid, $locationId, $data) { if (!empty($data)) { @@ -308,6 +171,7 @@ class PvsGenerator /** * Get display name for manager of given locationId. + * Hook for "runmode" module to resolve mode name. * @param $locationId * @return bool|string */ -- cgit v1.2.3-55-g7522