From 9c2304869d1cfef18ae5a79c2cc84435c6e8e1ff Mon Sep 17 00:00:00 2001 From: Deon George Date: Wed, 5 Dec 2018 21:50:38 +1100 Subject: [PATCH] Code optimisation and minor function fixes --- app/Classes/Frame.php | 173 +++++++++++--- app/Classes/FrameFields.php | 18 ++ app/Console/Commands/Server.php | 392 +++++++++++++++----------------- app/Models/Frame.php | 24 +- config/constants.php | 4 +- 5 files changed, 372 insertions(+), 239 deletions(-) create mode 100644 app/Classes/FrameFields.php diff --git a/app/Classes/Frame.php b/app/Classes/Frame.php index 29f9322..21475fd 100644 --- a/app/Classes/Frame.php +++ b/app/Classes/Frame.php @@ -17,10 +17,12 @@ use Illuminate\Support\Facades\Log; * + Header is on line 1. * + Input field is on Line 24. * + 'i' Frames are info frames, no looking for fields. (Lines 2-23) - * + 'ip' Frames are Information Provider frames - no header added. (Lines 1-23) * + 'a' Frames have active frames with responses. * + 't' Frames terminate the session * + * + Frame types: + * + 'ip' Frames are Information Provider frames - no header added. (Lines 1-23) + * * To Consider * + 'x' External frames - living in another viewdata server * @@ -38,32 +40,55 @@ class Frame private $cost_length = 7; // 9 (prefixed with a color, suffixed with unit) private $cost_unit = 'u'; - private $fieldmap = ['s'=>'systel','n'=>'username','a'=>'address#','d'=>'%date']; public $fields = NULL; // The fields in this frame. + // Magic Fields that are pre-filled + private $fieldmap = [ + 'a'=>'address#', + 'd'=>'%date', + ]; + + // Fields that are editable + private $fieldoptions = [ + 'a'=>['edit'=>TRUE], // Address + 'p'=>['edit'=>TRUE], // Password + 'u'=>['edit'=>TRUE], // User + ]; + // @todo Move this to the database private $header = RED.'T'.BLUE.'E'.GREEN.'S'.YELLOW.'T'.MAGENTA.'!'; public function __construct(\App\Models\Frame $o,string $msg=NULL) { + dump(__METHOD__); $this->frame = $o; $this->output = $this->hasFlag('clear') ? CLS : HOME; + // If we have a message to display on the bottom line. if ($msg) $this->output .= UP.$msg.HOME; + $startline = 0; + if (! $this->hasFlag('ip')) { // Set the page header: CUG/Site Name | Page # | Cost $this->output .= $this->render_header($this->header). $this->render_page($this->frame->frame,$this->frame->index). $this->render_cost($this->frame->cost); + + $startline = 1; } // Calculate fields and render output. - $this->fields(); + $this->fields($startline); } + /** + * Render the frame + * + * @return null|string + */ public function __toString() { return $this->output; @@ -75,10 +100,12 @@ class Frame * * @param int $startline */ - public function fields($startline=0) + public function fields($startline=0,$fieldchar='.') { - $infield = FALSE; - $this->fields = collect(); + $infield = FALSE; // In a field + $fieldtype = NULL; // Type of field + $fieldlength = 0; // Length of field + $this->fields = collect(); // Fields in this frame. if ($startline) $this->output .= str_repeat(DOWN,$startline); @@ -88,28 +115,30 @@ class Frame // Scan the frame for a field start for ($y=$startline;$y<=$this->frame_length;$y++) { + // Fields can only be on a single line $fieldx = $fieldy = FALSE; for ($x=0;$x<$this->frame_width;$x++) { $posn = $y*40+$x; + + // If the frame is not big enough, fill it with spaces. $byte = ord(isset($this->frame->content{$posn}) ? $this->frame->content{$posn} : ' ')%128; - // dump(sprintf('Y: %s,X: %s, POSN: %s, BYTE: %s',$y,$x,$posn,$byte)); // Check for start-of-field if ($byte == ord(ESC)) { // Esc designates start of field (Esc-K is end of edit) $infield = TRUE; - $fieldlength = 0; + $fieldlength = 1; $fieldtype = ord(substr($this->frame->content,$posn+1,1))%128; - $byte = ord(' '); // Replace ESC with space. + $this->output .= $fieldchar; } else { if ($infield) { if ($byte == $fieldtype) { $fieldlength++; - $byte = ord(' '); // Replace field with space. + $byte = ord($fieldchar); // Replace field with $fieldchar. - if ($fieldx === false) { + if ($fieldx === FALSE) { $fieldx = $x; $fieldy = $y; } @@ -131,12 +160,15 @@ class Frame // Replace field with Date if ($field == '%date') { - if ($fieldlength == 1) + // Drop the last dot and replace it. + if ($fieldlength == 2) { $datetime = date('D d M H:ia'); + $this->output = rtrim($this->output,$fieldchar); + $this->output .= $datetime{0}; + } - if ($fieldlength <= strlen($datetime)) + if ($fieldlength > 1 AND $fieldlength <= strlen($datetime)) $byte = ord($datetime{$fieldlength-1}); - } // @todo user data @@ -147,19 +179,18 @@ class Frame } /*else // pre-load field contents. PAM or *00 ? if (isset($fields[what]['value'])) { - } */ - + */ } } else { - Log::debug(sprintf('Frame: %s%s, Field found at [%s,%s], Type: %s, Length: %s','TBA','TBA',$fieldx,$fieldy,$fieldtype,$fieldlength)); - - $this->fields->push([ + $this->fields->push(new FrameFields([ 'type'=>chr($fieldtype), 'length'=>$fieldlength, - 'x'=>$fieldx, + 'x'=>$fieldx-1, // Adjust for the ESC char 'y'=>$fieldy, - ]); + ])); + + Log::debug(sprintf('Frame: %s, Field found at [%s,%s], Type: %s, Length: %s',$this->page(),$fieldx-1,$fieldy,$fieldtype,$fieldlength)); $infield = FALSE; $fieldx = $fieldy = FALSE; @@ -167,23 +198,47 @@ class Frame } } - // truncate end of lines + // truncate end of lines @todo havent validated this code or used it? if (isset($pageflags['tru']) && substr($this->frame->content,$posn,40-$x) === str_repeat(' ',40-$x)) { $this->output .= CR . LF; break; } - $this->output .= ($byte < 32) ? ESC.chr($byte+64) : chr($byte); + if (! $infield OR $fieldlength > 1) + $this->output .= ($byte < 32) ? ESC.chr($byte+64) : chr($byte); } } } /** - * Return the Frame Number + * Returns the current frame. */ - public function framenum() + public function frame() { - return $this->frame->frame.$this->frame->index; + return $this->frame->frame; + } + + /** + * Return the current field configuration + */ + public function getField(int $id) + { + return $this->fields->get($id); + } + + /** + * Get a specific key of the field options that passes a filter test + * + * @param string $type + * @param int $after + * @return mixed + */ + public function getFieldId($type='edit',$after=0) + { + return $this->fields + ->search(function($item,$key) use ($type,$after) { + return $key >= $after AND $this->isFieldEditable($item->type); + }); } /** @@ -194,11 +249,69 @@ class Frame * @param $flag * @return bool */ - private function hasFlag($flag) + public function hasFlag($flag) { return $this->frame->hasFlag($flag); } + /** + * Return the frame DB id + * + * @return mixed + */ + public function id() + { + return $this->frame->id; + } + + /** + * Current frame index + * + * @return mixed + */ + public function index() + { + return $this->frame->index; + } + + /** + * Return the next index + */ + public function index_next() + { + return chr(ord($this->frame->index)+1); + } + + /** + * Determine if a field is editable + * + * @param string $field + * @return mixed + */ + public function isFieldEditable(string $field) + { + return array_get(array_get($this->fieldoptions,$field),'edit',FALSE); + } + + /** + * Return the Page Number + */ + public function page(bool $as_array=FALSE) + { + return $as_array ? ['frame'=>$this->frame->frame,'index'=>$this->frame->index] : $this->frame->page; + } + + /** + * Return the next page number. + * + * @param bool $as_array + * @return mixed + */ + public function pagenext(bool $as_array=FALSE) + { + return $as_array ? ['frame'=>$this->frame->frame,'index'=>$this->index_next()] : $this->frame->frame.$this->index_next(); + } + /** * Render the cost of the frame * @@ -292,10 +405,10 @@ class Frame R_WHITE.'999999999a'.R_RED.sprintf('%07.0f',999).'u'; $o->content .= str_repeat('+-',18).' '.R_RED.'01'; - $o->content .= 'Date: '.ESC.str_repeat('d',25).str_repeat('+-',4); $o->content .= 'Name: '.ESC.str_repeat('u',5).str_repeat('+-',14); - $o->content .= 'Address: '.ESC.str_repeat('a',20).''.str_repeat('+-',5); - $o->content .= ' : '.ESC.str_repeat('a',20).''.str_repeat('+-',5); + $o->content .= 'Date: '.ESC.str_repeat('d',25).str_repeat('+-',4); + $o->content .= 'Address: '.ESC.str_repeat('a',19).' '.str_repeat('+-',5); + $o->content .= ' : '.ESC.str_repeat('a',19).' '.str_repeat('+-',5); return $o; } diff --git a/app/Classes/FrameFields.php b/app/Classes/FrameFields.php new file mode 100644 index 0000000..b0d2281 --- /dev/null +++ b/app/Classes/FrameFields.php @@ -0,0 +1,18 @@ +fields = $fields; + } + + public function __get($key) + { + return array_get($this->fields,$key); + } +} \ No newline at end of file diff --git a/app/Console/Commands/Server.php b/app/Console/Commands/Server.php index ec1c3eb..2ac5455 100644 --- a/app/Console/Commands/Server.php +++ b/app/Console/Commands/Server.php @@ -16,9 +16,6 @@ use Sock\{SocketClient,SocketServer,SocketException}; class Server extends Command { - // @todo Understand how is this used. - private $fieldoptions = ['f'=>['edit'=>TRUE],'a'=>['edit'=>TRUE]]; - /** * The name and signature of the console command. * @@ -89,13 +86,13 @@ class Server extends Command global $config; include ('config/config.php'); - $childpid = pcntl_fork(); + $pid = pcntl_fork(); - if ($childpid == -1) + if ($pid == -1) throw new SocketException(SocketException::CANT_ACCEPT,'Could not fork process'); // Parent return ready for next connection - elseif ($childpid) + elseif ($pid) return; // We are now the child. @@ -139,29 +136,29 @@ class Server extends Command 'CUGS' => array(7800, 15500), // Closed User Groups this user has access to ); - $history = array(); // backup history + // Setup VARS + $timewarp = FALSE; // Is timewarp active. + $history = collect(); // Page history for going backwards + $action = ACTION_GOTO; // Initial action. + $cmd = ''; // Current *command being typed in + $mode = FALSE; // Current mode. + + $current = []; // Attributes about the current page + // field/fieldnum indexes are for fields on the active page + $current['fieldreset'] = FALSE; // Flag to reset position (used in fields) - $cmd = ''; // Current *command being typed in - $mode = false; // input mode. $prevmode = false; // previous mode - $timewarp = false; - $action = ACTION_GOTO; // do something if set. used here to trigger a goto to the login form. + if (isset($config['loginpage'])) { - $page = $config['loginpage']; - $subpage = 'a'; + $page = ['frame'=>$config['loginpage'],'index'=>'a']; } else if (!empty($service['start_page'])) { - $page = $service['start_page']; - $subpage = 'a'; + $page = ['frame'=>$service['start_page'],'index'=>'a']; } else { - $page = '98'; // next page - $subpage = 'a'; + $page = ['frame'=>'98','index'=>'a']; // next page } - $curpage = ''; // current page - $cursub = ''; - $curfield = null; // current input field + $curfp = 0; // current field, position within. $blp = 0; // botton line polluted (by this no. of characters) - $resetpsn = false; // flag to reset position (used in fields) if (!isset($config['varient_id'])) $config['varient_id'] = NULL; @@ -176,9 +173,9 @@ class Server extends Command $matches = array(); if (preg_match('@' . $service['page_format'] . '@', $service['start_frame'], $matches)) { - $page = $matches[1]; - $subpage = $matches[2]; - echo " Using start page " . $page . $subpage . "\n"; + $page['frame'] = $matches[1]; + $page['index'] = $matches[2]; + echo " Using start page " . $page['frame'].$page['index'] . "\n"; } // $start = $service['start_frame']; // where to start from @@ -188,7 +185,7 @@ class Server extends Command $read = $client->read(1); if ($read != '') { - dump(sprintf('Mode: [%s] CMD: [%s] frame: [%s] Received [%s (%s)]', $mode, $cmd, $page, $read, ord($read))); + dump(sprintf('Mode: [%s] CMD: [%s] frame: [%s] Received [%s (%s)]', $mode, $cmd, $page['frame'].$page['index'], $read, ord($read))); // Client initiation input // TELNET http://pcmicro.com/netfoss/telnet.html @@ -263,7 +260,7 @@ class Server extends Command switch ($mode) { // Key presses during field input. case MODE_FIELD: - //dump(sprintf('** Processing Keypress in MODE_FIELD [%s (%s)]. Last POS [%s]',$read,ord($read),$curfp)); + dump(sprintf('** Processing Keypress in MODE_FIELD [%s (%s)]. Last POS [%s]',$read,ord($read),$curfp)); $cmd = ''; $action = FALSE; @@ -274,26 +271,25 @@ class Server extends Command // End of field entry. case HASH: // Next Field - $curfield++; + $current['fieldnum']++; + $curfp = 0; - //dump(['current'=>$curfield, 'numfields'=>count($fields)]); + if ($current['fieldnum'] < $fo->fields->count()) { // skip past non-editable fields + $current['fieldnum'] = $fo->getFieldId('edit',$current['fieldnum']); - if ($curfield < count($fields)) { // skip past non-editable fields - for ($i = $curfield; $i < count($fields); $i++) { - if (isset($this->fieldoptions[$fields[$i]['type']]) && - $this->fieldoptions[$fields[$i]['type']]['edit']) { - $curfield = $i; - break; - } - } + if ($current['fieldnum'] !== FALSE) { + $current['field'] = $fo->getField($current['fieldnum']); + $fielddata[$current['fieldnum']] = ''; - if ($curfield !== false) { - $client->send(outputPosition($fields[$curfield]['x'], $fields[$curfield]['y']) . CON); + dump(['Working field'=>$current['field']]); + + dump(['line'=>__LINE__,'field'=>$current['field'],'x'=>$current['field']->x]); + $client->send($this->outputPosition($current['field']->x,$current['field']->y).CON); $mode = MODE_FIELD; - $fielddate[$curfield] = ''; + $fielddate[$current['fieldnum']] = ''; + // There were no (more) editable fields. } else { - // there were no (more) editable fields. $action = ACTION_SUBMITRF; } @@ -306,24 +302,24 @@ class Server extends Command case STAR: $prevmode = MODE_FIELD; $action = ACTION_STAR; + $curfp = 0; + $fielddata[$current['fieldnum']] = ''; break; case KEY_LEFT: - if ($curfp) { + if ($curfp--) { $client->send(LEFT); - $curfp--; }; break; case KEY_RIGHT: - if ($curfp++ < $fields[$curfield]['length']) { + if ($curfp++ < $current['field']->length) { $client->send(RIGHT); - //$curfp++; }; break; case KEY_DOWN: - if ($curfp + 40 < $fields[$curfield]['length']) { + if ($curfp + 40 < $current['field']->length) { $client->send(DOWN); $curfp = $curfp + 40; }; @@ -337,11 +333,12 @@ class Server extends Command break; case CR: - if ($curfp + $fields[$curfield]['x'] > 40) { // on second or later line of a field + if ($curfp + $current['field']->x > 40) { // on second or later line of a field $client->send($read); - $curfp = (($curfp + $fields[$curfield]['x']) % 40) * 40; + $curfp = (($curfp + $current['field']->x) % 40) * 40; } else { - $client->send(outputPosition($fields[$curfield]['x'], $fields[$curfield]['y']) . CON); + dump(['line'=>__LINE__,'field'=>$current['field']]); + $client->send($this->outputPosition($current['field']->x,$current['field']->y).CON); $curfp = 0; } break; @@ -351,8 +348,8 @@ class Server extends Command // Record Data Entry default: - if (ord($read) > 31 && $curfp < $fields[$curfield]['length']) { - $fielddata[$curfield]{$curfp} = $read; + if (ord($read) > 31 && $curfp < $current['field']->length) { + $fielddata[$current['fieldnum']]{$curfp} = $read; $curfp++; $client->send($read); } @@ -374,7 +371,8 @@ class Server extends Command switch ($read) { // @todo Input received, process it. case '1': - dump(['s' => $service, 'f' => $fielddata]); + dump(['line'=>__LINE__,'s' => $service, 'f' => $fielddata]); + // @todo if send successful or not if (TRUE) { sendBaseline($client, $blp, MSG_SENT); $mode = MODE_RFSENT; @@ -404,24 +402,24 @@ class Server extends Command if ($read == HASH) { if (!empty($pagedata['route1'])) { $action = ACTION_GOTO; - $page = $pagedata['route1']; - $subpage = 'a'; + $page['frame'] = $pagedata['route1']; + $page['index'] = 'a'; - } else if ($r = $db->getFrame($service['service_id'], $varient['varient_id'], $page, chr(1 + ord($subpage)))) { + } else if (\App\Models\Frame::where('frame',$fo->frame())->where('index',$fo->index_next())->exists()) { $action = ACTION_GOTO; - $page = $curpage; - $subpage = chr(1 + ord($subpage)); + $page['frame'] = array_get($current,'page.frame'); + $page['index'] = chr(1 + ord($page['index'])); } else if (!empty($pagedata['route0'])) { $action = ACTION_GOTO; - $page = $pagedata['route0']; - $subpage = 'a'; + $page['frame'] = $pagedata['route0']; + $page['index'] = 'a'; // No further routes defined, go home. } else { $action = ACTION_GOTO; - $page = '0'; - $subpage = 'a'; + $page['frame'] = '0'; + $page['index'] = 'a'; } } elseif ($read == STAR) { @@ -443,24 +441,24 @@ class Server extends Command if ($read == HASH) { if (!empty($pagedata['route2'])) { $action = ACTION_GOTO; - $page = $pagedata['route2']; - $subpage = 'a'; + $page['frame'] = $pagedata['route2']; + $page['index'] = 'a'; - } else if ($r = $db->getFrame($service['service_id'], $varient['varient_id'], $page, chr(1 + ord($subpage)))) { + } else if (\App\Models\Frame::where('frame',$fo->frame())->where('index',$fo->index_next())->exists()) { $action = ACTION_GOTO; - $page = $curpage; - $subpage = chr(1 + ord($subpage)); + $page['frame'] = $fo->frame(); + $page['index'] = $fo->index_next(); } else if (!empty($pagedata['route0'])) { $action = ACTION_GOTO; - $page = $pagedata['route0']; - $subpage = 'a'; + $page['frame'] = $pagedata['route0']; + $page['index'] = 'a'; // No further routes defined, go home. } else { $action = ACTION_GOTO; - $page = '0'; - $subpage = 'a'; + $page['frame'] = '0'; + $page['index'] = 'a'; } } else if ($read == STAR) { @@ -480,8 +478,7 @@ class Server extends Command $v = $db->getAllVarients($config['service_id'], $alts[$read - 1]['varient_id']); if (!empty($v)) { $varient = reset($v); - $page = $curpage; - $subpage = $cursub; + $page = array_get($current,'page'); $action = ACTION_GOTO; break; } @@ -490,9 +487,11 @@ class Server extends Command //drop into // Not doing anything in particular. + case MODE_COMPLETE: + case FALSE: + Log::debug('Idle', ['pid' => $pid]); $cmd = ''; - Log::debug('Idle', ['pid' => $childpid]); switch ($read) { case HASH: @@ -518,6 +517,7 @@ class Server extends Command $action = ACTION_GOTO; } else { + dump(['line'=>__LINE__,'blp was'=>$blp]); sendBaseline($client, $blp, ERR_ROUTE); $mode = $action = FALSE; } @@ -538,6 +538,7 @@ class Server extends Command $cmd .= $read; $client->send($read); $blp++; + dump(['line'=>__LINE__,'blp is now'=>$blp]); } // if we hit a special numeric command, deal with it. if ($cmd === '00') { // refresh page @@ -571,28 +572,31 @@ class Server extends Command if ($read === "*") { // abort command or reset input field. $action = false; sendBaseline($client, $blp, ''); + dump(['line'=>__LINE__,'blp is now'=>$blp]); $cmd = ''; if ($prevmode == MODE_FIELD) { $mode = $prevmode; $prevmode = false; - $client->send(outputPosition($fields[$curfield]['x'], $fields[$curfield]['y']) . CON); - $client->send(str_repeat(' ', $fields[$curfield]['length'])); + dump(['line'=>__LINE__,'field'=>$current['field']]); + $client->send($this->outputPosition($current['field']->x,$current['field']->y).CON); + $client->send(str_repeat('.', $current['field']->length)); // tood reset stored entered text - $resetpsn = $curfield; + $current['fieldreset'] = TRUE; } else { $mode = false; } break; } + // user hit # to complete request if ($read === '_') { // really the # key, $client->send(COFF); if ($cmd === '') { // nothing typed between * and # $action = ACTION_BACKUP; } else { // *# means go back - $page = $cmd; - $subpage = 'a'; + $page['frame'] = $cmd; + $page['index'] = 'a'; $action = ACTION_GOTO; } $cmd = ''; // finished with this now @@ -629,39 +633,42 @@ class Server extends Command break; + // GO Backwards case ACTION_BACKUP: - // do we have anywhere to go? - if (count($history) > 1) { // because current page should always be in there. - array_pop($history); // drop current page to reveal previous - } - list($page, $subpage) = end($history); // get new last entry, - echo "Backing up to $page$subpage\n"; - // drop into + // Do we have anywhere to go, drop the current page from the history. + if ($history->count() > 1) + $history->pop(); + + $page = $history->last(); + + Log::debug('Backing up to: '.$page['frame'].$page['index']); + + // Go to next index frame. case ACTION_NEXT: - if ($action == ACTION_NEXT) { - $cursub = $subpage; - $subpage = chr(ord($subpage) + 1); + // We need this extra test in case we come from ACTION_BACKUP + if ($action == ACTION_NEXT) + { + dump(['current.page.index'=>$current['page']['index'],'fo'=>$fo->index()]); + $current['page']['index'] = $fo->index(); + $page['index'] = $fo->index_next(); } + case ACTION_GOTO: -// $client->send(HOME . UP . GREEN . "Searching for page $page"); -// $blp = 20 + strlenv($page); +// $client->send(HOME . UP . GREEN . "Searching for page $page['frame']"); +// $blp = 20 + strlenv($page['frame']); // look for requested page try { - $fo = (new \App\Models\Frame)->fetch($page, $subpage); + $fo = (new \App\Models\Frame)->fetch($page['frame'],$page['index']); } catch (ModelNotFoundException $e) { - Log::debug(sprintf('Frame: %s%s NOT found', $page, $subpage)); - if ($action == ACTION_NEXT) { - $subpage = $cursub; // Put subpage back as it was - } - sendBaseline($client, $blp, ERR_PAGE); $mode = $action = FALSE; + break; } - dump(['m' => __METHOD__, 'service' => $service['service_id'], 'varient' => $varient['varient_id'], 'frame' => $fo->framenum(), 'type' => $fo->type()]); + dump(['m' => __METHOD__, 'fo'=>$fo->id(),'service' => $service['service_id'], 'varient' => $varient['varient_id'], 'frame' => $fo->page(), 'type' => $fo->type()]); // validate if we have access top it /* if (isset($m['access']) && $m['access'] == 'n') { @@ -688,42 +695,43 @@ class Server extends Command //var_dump(['B','r'=>$r,'m'=>$m]); //$pagedata = array_merge($r, $m); //$varient = $v; - $curpage = $page; - $cursub = $subpage; - $cufield = 0; + $current['page'] = $fo->page(TRUE); $curfp = 0; //$pageflags = $db->getFrameTypeFlags($pagedata['type']); // method missing. $pageflags = []; - if ($action == ACTION_GOTO || $action == ACTION_NEXT) { // only if new location, not going backwards - $history[] = array($page, $subpage); + // Only if new location, not going backwards + if (($history->last() != $page) AND ($action == ACTION_GOTO || $action == ACTION_NEXT)) { + $history->push($page); } // drop into case ACTION_RELOAD: - // - /* if ($pageflags['clear']) { - $output = CLS; - $blp = 0; - } else { - $output = HOME; - } - */ -// print_r($pageflags); print_r($pagedata); + // @todo Move the $output into the object. + if ($fo->hasFlag('clear')) + { + $blp = 0; + $output = CLS; + } else { + $output = HOME; + // Clear the baseline. + $blp = sendBaseline($client,$blp,''); + } + $output .= (string)$fo; switch ($fo->type()) { default: case 'i': // standard frame if ($timewarp && 1 < count( - $alts = $db->getAlternateFrames($service['service_id'], $varient['varient_id'], $curpage, $cursub) + $alts = $db->getAlternateFrames($service['service_id'], $varient['varient_id'], array_get($current,'page.frame'), array_get($current,'page.index')) )) { $msg = MSG_TIMEWARP; } else { $msg = ''; } - $output = getOutputx($curpage, $cursub, [], $pageflags, $msg); - //var_dump(['output'=>$output,'curpage'=>$curpage,'cursub'=>$cursub,'pagedata'=>$pagedata,'pageflag'=>$pageflags,'m'=>$msg]); + dump(['line'=>__LINE__,'blp was'=>$blp,'will be'=>strlenv($msg)]); + $blp = strlenv($msg); $client->send($output); $mode = $action = false; @@ -732,7 +740,7 @@ class Server extends Command case 'a': // active frame. Prestel uses this for Response Framea. /* if ($timewarp && 1 < count( - $alts = $db->getAlternateFrames($service['service_id'],$varient['varient_id'],$curpage,$cursub) + $alts = $db->getAlternateFrames($service['service_id'],$varient['varient_id'],array_get($current,'page.frame'), array_get($current,'page.index')) )) { $msg = MSG_TIMEWARP; } else { @@ -745,50 +753,38 @@ class Server extends Command //$pagedata = str_replace(chr(12),chr(27),$pagedata); // holds data entered by user. - $fielddata = array(); + $fielddata = []; - $fields = $fo->fields; - $msg = '?'; - $output = getOutputx($curpage, $cursub, [], $pageflags, $msg, $user, $fields); - $blp = strlenv($msg); + //$msg = ''; + + //dump(['line'=>__LINE__,'blp was'=>$blp,'will be'=>strlenv($msg)]); + //$blp = strlenv($msg); $client->send($output); - if ($fields->count()) { - // dump($fields,count($fields)); - // need t skip to first field that is.. - // of a field type that is editable - // or finish. - $curfield = FALSE; + // dump($fo->fields,count($fo->fields)); + // @todo If there are no editable fields, it seems the frame is hung. + if (count($fo->fields)) { + // Get our first editable field. + $current['fieldnum'] = $fo->getFieldId('edit',0); + $current['field'] = $fo->getField($current['fieldnum']); + $current['fieldreset'] = TRUE; - for ($i = 0; $i < count($fields); $i++) { - //dump($this->fieldoptions,$i,isset($this->fieldoptions[$fields[$i]['type']])); - - if (isset($this->fieldoptions[$fields[$i]['type']]) && - $this->fieldoptions[$fields[$i]['type']]['edit']) { - $curfield = $i; - break; - } - } - - $resetpsn = $curfield; - - if ($curfield !== false) { + if ($current['fieldnum'] !== FALSE) { $mode = MODE_FIELD; + // There were no editable fields. } else { - // there were no editable fields. $mode = MODE_COMPLETE; + $client->send(COFF); } $curfp = 0; - - //dump(['curfield'=>$curfield,'mode'=>$mode]); } break; case 't': // terminate - $output = getOutputx($curpage, $cursub, [], $pageflags); + //$output = getOutputx(array_get($current,'page.frame'), array_get($current,'page.index'), [], $pageflags); $client->send($output); $action = ACTION_TERMINATE; break; @@ -804,15 +800,16 @@ class Server extends Command $cmd = ''; $action = false; - $output = outputPosition(0, 0) . WHITE . NEWBG . RED . 'TIMEWARP INFO FOR Pg.' . BLUE . $curpage . $cursub . WHITE; - $output .= outputPosition(0, 1) . WHITE . NEWBG . BLUE . 'Service : ' . substr($service['service_name'] . str_repeat(' ', 27), 0, 27); - $output .= outputPosition(0, 2) . WHITE . NEWBG . BLUE . 'Varient : ' . substr($varient['varient_name'] . str_repeat(' ', 27), 0, 27); - $output .= outputPosition(0, 3) . WHITE . NEWBG . BLUE . 'Dated : ' . substr(date('j F Y', strtotime($varient['varient_date'])) . str_repeat(' ', 27), 0, 27); + // @todo Can we use $fo->page() where? + $output = $this->outputPosition(0, 0) . WHITE . NEWBG . RED . 'TIMEWARP INFO FOR Pg.' . BLUE . array_get($current,'page.frame').array_get($current,'page.index'). WHITE; + $output .= $this->outputPosition(0, 1) . WHITE . NEWBG . BLUE . 'Service : ' . substr($service['service_name'] . str_repeat(' ', 27), 0, 27); + $output .= $this->outputPosition(0, 2) . WHITE . NEWBG . BLUE . 'Varient : ' . substr($varient['varient_name'] . str_repeat(' ', 27), 0, 27); + $output .= $this->outputPosition(0, 3) . WHITE . NEWBG . BLUE . 'Dated : ' . substr(date('j F Y', strtotime($varient['varient_date'])) . str_repeat(' ', 27), 0, 27); - $alts = $db->getAlternateFrames($service['service_id'], $varient['varient_id'], $curpage, $cursub); + $alts = $db->getAlternateFrames($service['service_id'], $varient['varient_id'], array_get($current,'page.frame'), array_get($current,'page.index')); if (count($alts) > 1) { $n = 1; - $output .= outputPosition(0, 4) . WHITE . NEWBG . RED . 'ALTERNATIVE VERSIONS:' . str_repeat(' ', 16); + $output .= $this->outputPosition(0, 4) . WHITE . NEWBG . RED . 'ALTERNATIVE VERSIONS:' . str_repeat(' ', 16); $y = 5; foreach ($alts as $ss) { // if (is_numeric($ss['varient_date'])) { @@ -827,7 +824,7 @@ class Server extends Command $line .= BLUE . $date . ' ' . $ss['varient_name']; - $output .= outputPosition(0, $y) . $line . str_repeat(' ', 40 - strlenv($line)); + $output .= $this->outputPosition(0, $y) . $line . str_repeat(' ', 40 - strlenv($line)); $y++; $n++; @@ -844,26 +841,49 @@ class Server extends Command ; } // switch $action - if ($resetpsn !== false && isset($fields[$resetpsn])) { - $client->send(outputPosition($fields[$resetpsn]['x'], $fields[$resetpsn]['y']) . CON); - $resetpsn = false; + // We need to reposition the cursor to the current field. + if ($current['fieldreset'] !== FALSE) { + $client->send($this->outputPosition($current['field']->x,$current['field']->y).CON); + $current['fieldreset'] = FALSE; } + // Did the client disconnect + if ($read === NULL || socket_last_error()) { + Log::debug('Disconnected: '.$client->getaddress()); - if ($read === null || socket_last_error()) { - printf("[%s] Disconnected\n", $client->getaddress()); - - return false; + return FALSE; } } // Something bad happened. We'll log it and then disconnect. } catch (\Exception $e) { Log::emergency($e->getMessage()); + + //@todo TEMP + throw new \Exception($e); } $client->close(); - printf( "[%s] Disconnected\n", $client->getaddress() ); + Log::debug('Disconnected: '.$client->getaddress()); + } + + /** + * Move the cursor via the shortest path. + */ + function outputPosition($x,$y) { + // Take the shortest path. + if ($y < 12) { + return HOME. + (($x < 21) + ? str_repeat(DOWN,$y).str_repeat(RIGHT,$x) + : str_repeat(DOWN,$y+1).str_repeat(LEFT,40-$x)); + + } else { + return HOME.str_repeat(UP,24-$y). + (($x < 21) + ? str_repeat(RIGHT,$x) + : str_repeat(LEFT,40-$x)); + } } } @@ -872,56 +892,20 @@ class Server extends Command } // @todo Not clearing to end of line. - function sendBaseline($client, &$blp, $text, $reposition = false){ - $client->send(HOME . UP . $text . - ( $blp > strlenv($text) ? str_repeat(' ',$blp-strlenv($text)) . - ( $reposition ? HOME . UP . str_repeat(RIGHT, strlenv($text)) : '' ) + // @todo Remove blp by reference, change return to return blp + function sendBaseline($client,&$blp,$text,$reposition=FALSE) { + dump(['method'=>__METHOD__,'blp'=>$blp,'text'=>$text,'re'=>$reposition]); + + $client->send(HOME.UP.$text. + ($blp > strlenv($text) + ? str_repeat(' ',$blp-strlenv($text)). + ($reposition ? HOME.UP.str_repeat(RIGHT,strlenv($text)) : '') : '') ); + $blp = strlenv($text); - return; - } - function outputPosition($x,$y){ + dump(['metho'=>__METHOD__,'blp is now'=>$blp]); - if ($y < 12) { - if ($x < 21) { - return HOME . str_repeat(DOWN, $y) . str_repeat(RIGHT, $x); - } else { - return HOME . str_repeat(DOWN, $y+1) . str_repeat(LEFT, 40-$x); - } - } else { - if ($x < 21) { - return HOME . str_repeat(UP, 24-$y) . str_repeat(RIGHT, $x); - } else { - return HOME . str_repeat(UP, 24-$y) . str_repeat(LEFT, 40-$x); - } - - } - } - - /* - - return a screen output ... $msg sent on baseline just after the cls. - remember to update $blp manually after calling this. - - */ - - function getOutputx($page, $subpage, $pagedata, $pageflags, $msg = '', $user = array(), &$fields = null, &$frame_content = null) { - global $blp; - global $fieldmap; // @todo this is not set outside of the class. - - $price = isset($pagerecord['price']) ? $pagerecord['price'] : 0; - - // get textual content. - - $fo = (new \App\Models\Frame)->fetch($page,$subpage); - $text = (string)$fo; - //$text = $pagedata['frame_content']; - - - -// dump(['C'=>__METHOD__,'frame_content'=>$text,'msg'=>$output,'p'=>$page,'s'=>$subpage,'startline'=>$startline,'frame'=>$fo,'fields'=>$fo->fields($startline)]); - - return (string)$fo; + return $blp; } \ No newline at end of file diff --git a/app/Models/Frame.php b/app/Models/Frame.php index 58838a4..74f1370 100644 --- a/app/Models/Frame.php +++ b/app/Models/Frame.php @@ -2,10 +2,29 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class Frame extends Model { + protected static function boot() { + parent::boot(); + + static::addGlobalScope('order', function (Builder $builder) { + $builder->orderBy('created_at','DESC'); + }); + } + + /** + * Return the Page Number + * + * @return string + */ + public function getPageAttribute() + { + return $this->frame.$this->index; + } + /** * Fetch a specific frame from the database * @@ -13,12 +32,11 @@ class Frame extends Model * @param string $frame * @return mixed */ - public function fetch(int $frame,string $index): \App\Classes\Frame + public function fetch(int $frame,string $index='a'): \App\Classes\Frame { + // Return our internal test frame. if ($frame == '999' and $index == 'a') - { return new \App\Classes\Frame(\App\Classes\Frame::testFrame()); - } return new \App\Classes\Frame($this->where('frame',$frame)->where('index',$index)->firstOrFail()); } diff --git a/config/constants.php b/config/constants.php index bffee7a..df94c4d 100644 --- a/config/constants.php +++ b/config/constants.php @@ -77,8 +77,8 @@ define('MSG_SENDORNOT', GREEN . 'KEY 1 TO SEND, 2 NOT TO SEND'); define('MSG_SENT', GREEN . 'MESSAGE SENT - KEY _ TO CONTINUE'); define('MSG_NOTSENT', GREEN . 'MESSAGE NOT SENT - KEY _ TO CONTINUE'); -define('ERR_ROUTE', WHITE . 'MISTAKE?' . GREEN . 'TRY AGAIN OR TELL US ON *36_'); +define('ERR_ROUTE', WHITE . 'MISTAKE?' . GREEN . 'TRY AGAIN OR TELL US ON *08'); define('ERR_PAGE', ERR_ROUTE); define('ERR_PRIVATE', WHITE . 'PRIVATE PAGE' . GREEN . '- FOR EXPLANATION *37_..'); define('ERR_DATABASE', RED . 'UNAVAILABLE AT PRESENT - PLSE TRY LATER'); -define('ERR_NOTSENT', WHITE . 'MESSAGE NOT SENT DUE TO AN ERROR'); +define('ERR_NOTSENT', WHITE . 'MESSAGE NOT SENT DUE TO AN ERROR'); \ No newline at end of file