1
0
mirror of https://github.com/moshix/mvs.git synced 2026-03-04 18:14:15 +00:00

sabre.rex v0.2

This commit is contained in:
moshix
2025-06-19 20:54:03 +02:00
committed by GitHub
parent 3947721b54
commit 9de5fc6b9c

View File

@@ -1,6 +1,8 @@
/* SABRE CRS DEMO IN BREXX FOR VM/370 CMS BY ERNIETECH - ENHANCED VERSION */
/* EXPANDED WITH DYNAMIC DATA AND MORE SABRE COMMANDS
- JUNE2025 MOSHIX - AUSTRIA*/
- JUNE2025 MOSHIX - AUSTRIA
- V0.2 with new commands and more realistic seat maps
*/
/* Clear screen in a cross-platform way */
address command
@@ -122,6 +124,27 @@ eqDesc.B767 = 'Boeing 767-300'
eqDesc.B757 = 'Boeing 757-200'
eqDesc.MD981 = 'MD-8-81'
/* Seat map configurations */
/* Format: ROWS|LAYOUT|EXIT ROWS|FIRST CLASS ROWS|WHEELCHAIR ROWS|BASSINET ROWS|BLOCKED SEATS */
seatConfig.A320 = '27|ABC DEF|11 12|1-4|1 27|12|14B 14E' /* 3-3 config, 158 seats */
seatConfig.B738 = '28|ABC DEF|14 15|1-4|1 28|15|16B 16E' /* 3-3 config, 162 seats */
seatConfig.B789 = '42|ABC DEF GHJ|24 25|1-5|1 42|25|26E 26F' /* 3-3-3 config, 290 seats */
seatConfig.A350 = '44|ABC DEF GHJ|24 25|1-5|1 44|25|26E 26F' /* 3-3-3 config, 308 seats */
seatConfig.B77W = '51|ABC DEFG HJK|24 25|1-4|1 51|25|26E 26F' /* 3-4-3 config, 357 seats */
seatConfig.B747 = '58|ABC DEFG HJK|24 25|1-4|1 58|25|26E 26F' /* 3-4-3 config, 412 seats */
seatConfig.B767 = '34|ABC DEF GH|20 21|1-3|1 34|21|22D 22E' /* 2-3-2 config, 203 seats */
seatConfig.B757 = '25|ABC DEF|14 15|1-3|1 25|15|16B 16E' /* 3-3 config, 152 seats */
seatConfig.MD981 = '23|ABC DE|10 11|1-2|1 23|11|12B 12D' /* 2-3 config, 109 seats */
/* Seat map legend */
seatLegend.A = 'Available'
seatLegend.X = 'Occupied'
seatLegend.B = 'Blocked'
seatLegend.F = 'First Class'
seatLegend.E = 'Exit Row'
seatLegend.W = 'Wheelchair'
seatLegend.C = 'Bassinet'
seatLegend.M = 'Blocked Middle'
/* Seat configurations per equipment type */
eqSeats.A320 = 158
@@ -202,11 +225,13 @@ say
/* Initialize flight seat tracking */
drop flightSeats.
flightSeats.0 = 0
currentPNR = '' /* Track current PNR */
do forever
say
pull cmd
cmd = strip(translate(cmd))
if cmd = '' then iterate /* Skip empty commands */
/* HELP & SIGN-OUT */
if cmd = 'HELP' then do
@@ -224,8 +249,13 @@ do forever
say "WP/NI Display alternate fare options"
say "N/ADD-<n> Add passenger name (N/ADD-1 DOE/JOHN ADT)"
say "N/CHG-<n> Change passenger name (N/CHG-1 DOE/JANE)"
say "4G<n>* Display seat map for segment n"
say "SO* Sign Out all Work Areas"
iterate
say
say "Enter command:"
pull cmd
if cmd = '' then iterate
cmd = strip(translate(cmd))
end
if cmd = 'SO*' then do
@@ -236,6 +266,330 @@ do forever
/* split into verb + rest */
parse var cmd first rest
/* --- Seat Map Display and Assignment (4G command) --- */
if left(cmd,2) = '4G' then do
/* Check if this is a seat assignment command */
if pos('S', substr(cmd,3)) > 0 then do
/* Parse the command - handle both formats */
if pos('PNR', substr(cmd,3)) > 0 then do
/* Format: 4GPNR001S2A */
parse var cmd '4GPNR' pnrRaw 'S' seatAssign
if left(pnrRaw,3) \= 'PNR' then do
/* Extract numeric part before S */
pnrNum = ''
do i = 1 to length(pnrRaw) until substr(pnrRaw,i,1) = 'S'
if datatype(substr(pnrRaw,i,1),'W') then
pnrNum = pnrNum||substr(pnrRaw,i,1)
end
if pnrNum = '' then do
say '*** Invalid PNR number'
iterate
end
padded = substr('000'||pnrNum,length('000'||pnrNum)-2,3)
currentPNR = 'PNR'||padded
end
else currentPNR = pnrRaw
segNum = 1 /* Default to segment 1 */
end
else do
/* Format: 4G1S2A */
parse var cmd '4G' segNum 'S' seatAssign
if \datatype(segNum,'W') then do
say '*** Invalid segment number'
iterate
end
end
/* Handle numeric conversion safely */
segNum = strip(segNum) + 0 /* Force numeric */
/* Parse seat assignment (e.g., 2A) */
seatAssign = strip(translate(seatAssign))
/* Split into row and seat letter */
do i = 1 to length(seatAssign)
if \datatype(substr(seatAssign,i,1),'W') then leave
end
if i = 1 | i > length(seatAssign) then do
say '*** Invalid seat format - must be ROW+LETTER (e.g., 2A)'
iterate
end
seatRow = substr(seatAssign,1,i-1) + 0 /* Force numeric */
seatLetter = substr(seatAssign,i)
/* Find the PNR and flight */
found = 0
do j = 1 to PNRdata.0
parse var PNRdata.j pnrEntry pname oldSeat flightNum
if pnrEntry = currentPNR then do
parse var matchList.flightNum airline flight depc depd dept arrt arrc avst eqmt
flightKey = airline||flight||depc||arrc||depd||dept
found = 1
leave
end
end
if \found then do
say '*** PNR' currentPNR 'NOT FOUND'
iterate
end
/* Get seat configuration */
parse var seatConfig.eqmt rows '|' layout '|' exitRows '|' firstRows '|' wheelRows '|' bassRows '|' blockSeats
/* Validate seat exists in configuration */
if seatRow < 1 | seatRow > (rows + 0) then do
say '*** Invalid row number' seatRow 'for' eqDesc.eqmt
iterate
end
/* Validate seat letter */
if pos(seatLetter, layout) = 0 then do
say '*** Invalid seat letter' seatLetter 'for' eqDesc.eqmt
iterate
end
/* Check if seat is available */
newSeat = seatRow||seatLetter
if symbol('seatMap.'flightKey'.'newSeat) \= 'LIT' then do
if seatMap.flightKey.newSeat = 'X' then do
say '*** Seat' newSeat 'is not available'
iterate
end
end
/* Check if seat is blocked */
if wordpos(newSeat, blockSeats) > 0 then do
say '*** Seat' newSeat 'is blocked'
iterate
end
/* Release old seat if exists */
if oldSeat \= '' then do
seatMap.flightKey.oldSeat = ''
end
/* Assign new seat */
seatMap.flightKey.newSeat = 'X'
/* Update PNR record */
PNRdata.j = pnrEntry pname newSeat flightNum
say 'Seat changed to' newSeat 'for' currentPNR
iterate
end
/* Handle regular seat map display */
if pos('PNR', substr(cmd,3)) > 0 then do
/* Format: 4GPNR001 */
pnrRaw = substr(cmd,5) /* Skip '4G' and 'PNR' */
if left(pnrRaw,3) \= 'PNR' then do
padded = substr('000'||pnrRaw,length('000'||pnrRaw)-2,3)
pnr = 'PNR'||padded
end
else pnr = pnrRaw
currentPNR = pnr
segNum = 1 /* Default to segment 1 */
end
else do
/* Format: 4G1* */
parse var cmd '4G' segNum '*'
if segNum = '' then segNum = 1
if \datatype(segNum,'W') then do
say '*** Invalid segment number'
say
say "Enter command:"
pull cmd
if cmd = '' then iterate
cmd = strip(translate(cmd))
parse var cmd first rest
end
end
/* Handle numeric conversion safely */
segNum = strip(segNum) /* Remove any whitespace */
if \datatype(segNum,'W') then segNum = 1
segNum = segNum + 0 /* Force numeric */
/* Check if we have an active PNR */
if currentPNR = '' then do
say '*** NO ACTIVE PNR - DISPLAY PNR FIRST'
say
say "Enter command:"
pull cmd
if cmd = '' then iterate
cmd = strip(translate(cmd))
parse var cmd first rest
end
/* Find the flight */
found = 0
do j = 1 to PNRdata.0
parse var PNRdata.j pnrEntry pname seat flightNum
if pnrEntry = currentPNR then do
parse var matchList.flightNum airline flight depc depd dept arrt arrc avst eqmt
flightKey = airline||flight||depc||arrc||depd||dept
found = 1
leave
end
end
if \found then do
say '*** PNR' currentPNR 'NOT FOUND'
say
say "Enter command:"
pull cmd
if cmd = '' then iterate
cmd = strip(translate(cmd))
parse var cmd first rest
end
/* Get seat configuration */
parse var seatConfig.eqmt rows '|' layout '|' exitRows '|' firstRows '|' wheelRows '|' bassRows '|' blockSeats
if rows = '' then do
say '*** Invalid equipment type:' eqmt
say
say "Enter command:"
pull cmd
if cmd = '' then iterate
cmd = strip(translate(cmd))
parse var cmd first rest
end
/* Force numeric conversion */
rows = rows + 0
/* Initialize seat map if not already done */
if symbol('seatMapInit.'flightKey) = 'LIT' then do
/* Calculate number of seats to mark as occupied */
totalSeats = eqSeats.eqmt + 0 /* Force numeric */
availSeats = avst + 0 /* Force numeric */
seatsToOccupy = totalSeats - availSeats
if seatsToOccupy > 0 then do
/* Get list of all possible seats */
allSeats = ''
do r = 1 to rows
do c = 1 to length(layout)
ch = substr(layout,c,1)
if ch = ' ' then iterate
if wordpos(r||ch, blockSeats) > 0 then iterate
allSeats = allSeats r||ch' '
end
end
/* Randomly mark seats as occupied */
do while seatsToOccupy > 0 & words(allSeats) > 0
/* Pick a random seat */
idx = (time('S') // words(allSeats)) + 1
seat = word(allSeats,idx)
/* Remove it from available seats */
allSeats = delword(allSeats,idx,1)
/* Mark it as occupied */
seatMap.flightKey.seat = 'X'
seatsToOccupy = seatsToOccupy - 1
end
end
/* Mark initialization as done */
seatMapInit.flightKey = 1
end
/* Display header */
say 'SEAT MAP FOR' airline||flight eqDesc.eqmt
say 'DATE:' depd 'SEGMENT:' segNum
say
/* Display column headers based on layout */
colHeader = ''
do i = 1 to length(layout)
if substr(layout,i,1) = ' ' then
colHeader = colHeader ' '
else
colHeader = colHeader substr(layout,i,1)
end
say ' 'colHeader
/* Display seat map */
do r = 1 to rows
rowNum = right(r,2)
rowStr = rowNum' '
do c = 1 to length(layout)
ch = substr(layout,c,1)
if ch = ' ' then do
rowStr = rowStr' '
iterate
end
seatCode = r||ch
/* Check seat status */
status = 'A' /* Default to Available */
/* Check if seat is occupied */
if symbol('seatMap.'flightKey'.'seatCode) \= 'LIT' then
status = seatMap.flightKey.seatCode
/* Check if blocked middle seat */
if wordpos(seatCode, blockSeats) > 0 then
if status = 'A' then status = 'M'
/* Check if wheelchair accessible */
if wordpos(r, wheelRows) > 0 then
if status = 'A' then status = 'W'
/* Check if bassinet position */
if wordpos(r, bassRows) > 0 then
if status = 'A' then status = 'C'
/* Check if exit row */
if wordpos(r, exitRows) > 0 then
if status = 'A' then status = 'E'
/* Check if first class */
if wordpos(r, firstRows) > 0 then
if status = 'A' then status = 'F'
rowStr = rowStr||status
end
say rowStr
end
say
say 'A=AVAILABLE X=OCCUPIED E=EXIT ROW F=FIRST CLASS'
say 'B=BLOCKED W=WHEELCHAIR C=BASSINET M=BLOCKED MIDDLE'
iterate
end
/* --- PNR lookup command --- */
if first = 'PNR' then do
parse var rest pnrRaw
pnrNorm = strip(translate(pnrRaw))
if left(pnrNorm,3) \= 'PNR' then do
padded = substr('000'||pnrNorm,length('000'||pnrNorm)-2,3)
pnr = 'PNR'||padded
end
else pnr = pnrNorm
found = 0
do j = 1 to PNRdata.0
parse var PNRdata.j pnrEntry pname seat flightRec
if pnrEntry = pnr then do
currentPNR = pnr /* Set as current PNR */
say 'PNR '||pnrEntry||' => '||pname||' SEAT '||seat||' '||flightRec
/* Display passenger type if exists */
if paxType.j \= '' then
say ' Type: '||paxTypes.paxType.j
/* Display FF info if exists */
if ff.pnr \= '' then
say ' FF: '||ff.pnr||' ('||ff.pnr.airline||')'
found = 1
leave
end
end
if found = 0 then say '*** PNR '||pnr||' not found.'
iterate
end
/* --- BOOK command with seat & name prompting --- */
if first = 'BOOK' then do
parse var rest num
@@ -270,10 +624,34 @@ do forever
say "* Enter passenger name as <first initial><last name> (no spaces):"
pull pname
/* assign next seat */
seatCode = genRandomNum(1, 100) /* Simple seat number */
/* Get seat configuration */
parse var seatConfig.eqmt rows '|' layout '|' exitRows '|' firstRows '|' wheelRows '|' bassRows '|' blockSeats
/* store booking */
/* Find next available seat */
seatFound = 0
do r = 1 to rows + 0 until seatFound /* Force numeric */
do c = 1 to length(layout) until seatFound
if substr(layout,c,1) = ' ' then iterate
seatCode = r||substr(layout,c,1)
/* Skip if seat is blocked middle */
if wordpos(seatCode, blockSeats) > 0 then iterate
/* Check if seat is available */
if symbol('seatMap.'flightKey'.'seatCode) = 'LIT' then do
seatFound = 1
seatMap.flightKey.seatCode = 'X' /* Mark as occupied */
leave
end
end
end
if \seatFound then do
say "*** No seats available"
iterate
end
/* store booking with actual seat assignment */
j = pnrnum
PNRdata.j = pnr||' '||pname||' '||seatCode||' '||matchList.num
@@ -517,35 +895,6 @@ do forever
iterate
end
/* --- PNR lookup command --- */
if first = 'PNR' then do
parse var rest pnrRaw
pnrNorm = strip(translate(pnrRaw))
if left(pnrNorm,3) \= 'PNR' then do
padded = substr('000'||pnrNorm,length('000'||pnrNorm)-2,3)
pnr = 'PNR'||padded
end
else pnr = pnrNorm
found = 0
do j = 1 to PNRdata.0
parse var PNRdata.j pnrEntry pname seat flightRec
if pnrEntry = pnr then do
say 'PNR '||pnrEntry||' => '||pname||' SEAT '||seat||' '||flightRec
/* Display passenger type if exists */
if paxType.j \= '' then
say ' Type: '||paxTypes.paxType.j
/* Display FF info if exists */
if ff.pnr \= '' then
say ' FF: '||ff.pnr||' ('||ff.pnr.airline||')'
found = 1
leave
end
end
if found = 0 then say '*** PNR '||pnr||' not found.'
iterate
end
/* --- Equipment Query Commands --- */
if left(cmd,4) = 'W/EQ' then do
if length(cmd) > 5 & substr(cmd,5,1) = '*' then
@@ -625,65 +974,9 @@ do forever
drop flightSeats.
flightSeats.0 = 0
say
say date||' '||from||'/'||to||' ----------------------'
say ' # ARLN FLTN DEPC/ARVC DEPT ARRT AVST EQTYP'
say '-----------------------------------------------------------------------'
matchList.0 = 0
if flights.0 = 0 then do
say "NO FLIGHTS AVAILABLE FOR THAT QUERY"
iterate
end
do i = 1 to flights.0
parse var flights.i airline flight depc depd dept arrt arrc avst eqmt
/* time-of-day filter if specified */
match = 1
if time \= '' then do
parse var dept hr 3 mn 5 ap 6
if \datatype(hr,'W') | \datatype(mn,'W') then iterate
mins = (hr * 60) + mn
if ap = 'P' & hr \= 12 then mins = mins + (12 * 60)
if ap = 'A' & hr = 12 then mins = 0
timeHr = substr(time,1,length(time)-1)
timeAP = right(time,1)
if \datatype(timeHr,'W') then iterate
targetMins = (timeHr * 60)
if timeAP = 'P' & timeHr \= 12 then targetMins = targetMins + (12 * 60)
if timeAP = 'A' & timeHr = 12 then targetMins = 0
/* Allow 2 hour window around requested time */
if abs(mins - targetMins) > 120 then match = 0
end
if match then do
idx = matchList.0 + 1
matchList.0 = idx
matchList.idx = airline flight depc depd dept arrt arrc avst eqmt
/* Initialize seat tracking with numeric value */
flightKey = airline||flight||depc||arrc||depd||dept
numeric_avst = avst + 0 /* Force numeric conversion */
flightSeats.flightKey = numeric_avst
out = right(idx,2)
out = out||' '||left(airline,5)
out = out||' '||left(flight,7)
out = out||' '||left(depc||'/'||arrc,11)
out = out||' '||left(dept,7)
out = out||' '||left(arrt,7)
out = out||' '||left(avst,6)
out = out||' '||eqmt
say out
end
end
if matchList.0 = 0 then
say "NO FLIGHTS AVAILABLE FOR THAT QUERY"
end
/* Display flight list */
call displayFlights date, from, to
end /* End of main loop */
/* Function definitions */
genRandomNum:
@@ -891,6 +1184,15 @@ displayFlights:
say ' # ARLN FLTN DEPC/ARVC DEPT ARRT AVST EQTYP'
say '-----------------------------------------------------------------------'
/* Initialize matchList stem */
drop matchList.
matchList.0 = 0 + 0 /* Force numeric */
if flights.0 = 0 then do
say "NO FLIGHTS AVAILABLE FOR THAT QUERY"
return
end
do i = 1 to flights.0
parse var flights.i airline flight depc depd dept arrt arrc avst eqmt
@@ -915,11 +1217,18 @@ displayFlights:
end
if match then do
idx = matchList.0 + 1
matchList.0 = idx
/* Store numeric seat count in a separate field */
/* Safe numeric conversion for index */
idx = matchList.0 + 0 /* Force current value to numeric */
idx = idx + 1 /* Increment */
matchList.0 = idx /* Store back */
/* Store flight info */
matchList.idx = airline flight depc depd dept arrt arrc avst eqmt
matchList.idx.seats = avst /* Store seats as a separate numeric field */
/* Initialize seat tracking with numeric value */
flightKey = airline||flight||depc||arrc||depd||dept
numeric_avst = avst + 0 /* Force numeric conversion */
flightSeats.flightKey = numeric_avst
out = right(idx,2)
out = out||' '||left(airline,5)