Announcement

Collapse
No announcement yet.

Differences in INPUT QBasic vesus PBasic

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Michael Mattias
    replied
    I'm writing a GRAPHIC WINDOW one at the moment using OOP, here is a character mode "vanilla" version .
    No offense intended to Mr. Brown here, but for someone coming out of MS-DOS BASIC working his way thru the PB/CC INPUT statement, using a "GRAPHIC WINDOW with OOP techniques" seems at least one "Bridge Too Far."

    It probably would have been too far for you, too, at one time.

    FWIW, this oldie (but goodie?) was always one of the more popular downloads on Ye Olde Compuserve PB Forum... maybe it can be fairly easily adapted to PB/CC:

    PB/DOS: String Editor December 08, 2001 (Original: January 1992)

    MCM
    Last edited by Michael Mattias; 27 Oct 2008, 10:01 AM.

    Leave a comment:


  • Chris Holbrook
    replied
    (***IGNORE THIS**) Kevin, tried your code, it just asks for any key then exits. Should I be doing something different?

    (*** NOT THIS**) OK it works, finger trouble.

    It seems to be six one-line editors. Is this what you intended, or do you want text to flow between successive lines, like an edit box?

    If you need 6 x one line editors, my code above will do it. If you want an edit box, why not use a Windows one via the API. I'm sure there are examples around. I recently looked for a character mode edit box without success, which is why I am writing one.

    Loved the GLOBALS BTW - just kidding, I know it's a QB program.
    Last edited by Chris Holbrook; 27 Oct 2008, 09:13 AM.

    Leave a comment:


  • Kevin Brown
    replied
    Differences in INPUT QBasic vesus PBasic

    In order to make things clearer my objective was to be able to input data as per the attched screen dump from a QBasic program for Engineering PARTS, you can seen that the main part description is in effect 6 lines of text. I used the QBasic INPUT to enter this text and as you typed if you made a mistake you could wipe characters with the delete key or use the arrow keys to move the cursor and insert or overwite text.

    Now I have not found out how to do this yet with PBCC using the INPUT fuction maybe I can not do this, however as training/personal development excercise, I have written some code to allow me to edit text in a similar fashion. This code may not be the most elegant but it does work using the WAITKEY$ function. I would be appreciative of any comments or advise on how to improve on this or other general points of coding in PB. Don't hold back on commnents, I can take them and learn.

    Maybe what I really need is an insight into how the QBasic I currently use will be handled in PB, maybe some of you guys have gone through a similar process already. In addition to PARTS as shown above I have programs for

    VENDORS
    CLIENTS
    DRAWINGS
    BILLS OF MATERIALS
    PURCHASE ORDERS
    FINANCIAL REPORTS

    all created in a similar style with the obvious links to make a comprehensive suite of programs.

    Thanks for the feedback up till now it is appreciated.



    Kevin Brown


    Code:
     
    '   Text Editor 6 rows of text 60 characters long
    '
    '
    GLOBAL I$              'keyboard input
    GLOBAL FCN AS INTEGER  'Foreground
    GLOBAL BCN AS INTEGER  'Background
    GLOBAL SCN AS INTEGER  'Screen
    GLOBAL CR AS INTEGER
    GLOBAL CP AS INTEGER   'Cursor posn
    GLOBAL IC$             'Insert mode
    GLOBAL LN AS STRING    'Line
    GLOBAL L1 AS STRING    'Line 1
    GLOBAL L2 AS STRING    '2
    GLOBAL L3 AS STRING    '3
    GLOBAL L4 AS STRING    '4
    GLOBAL L5 AS STRING    '5
    GLOBAL L6 AS STRING    '6
    GLOBAL LS AS INTEGER   'Length of string
    GLOBAL FC AS INTEGER   'First charachter
    GLOBAL CL AS INTEGER   'Current line
    GLOBAL LL AS INTEGER  'Last line
    GLOBAL FL AS INTEGER  'First line
    GLOBAL CV AS INTEGER  'Cursor Vertical Positionc
    GLOBAL FV AS INTEGER  'Firt Vertical
    GLOBAL NV AS INTEGER  'Number of verticals
    GLOBAL CS AS INTEGER  'Cursor Min Horz
    GLOBAL CM AS INTEGER  'Cursor Max Horz
     
     SUB  ColorScreen
        PRINT "Press any key to proceed "
                   'FCN Foreground
                   'BCN Background
         IF FCN = 0 THEN FCN = 7
         IF BCN = 0 THEN BCN = 1
        COLOR FCN,BCN
        'COLOR [foreground], [background]
        '0 Black      '1 Blue    '2 Green    '3 Cyan    '4 Red    '5 Magenta    '6 Brown
        '7 White    '8 Gray    '9 Light blue    '10 Light green    '11 Light cyan    '12 Light red
        '13 Light magenta    '14 Yellow    '15 High intensity white
    END SUB
    
    SUB ArrowDown
        IF CL = LL THEN CL =1: CV =FV  ELSE CL =CL +1:CV =CV +1
        CP =10
        CALL LineEdit
    END SUB
    SUB ArrowUp
        IF CL = FL THEN CL =LL: CV = FV + (NV-1) ELSE CL =CL -1 :CV =CV -1
        CP =10
        CALL LineEdit
    END SUB
    SUB ArrowRight
        IF CP = CM THEN CP = 10 ELSE CP = CP +1
    END SUB
    
    SUB ArrowLeft
         IF CP =CS THEN CP =CM ELSE CP = CP -1
    END SUB
     
    SUB CharcAdd
        CALL LineEdit
        IF CP < = 69 THEN LN= LN+I$:  CP=(CP+1)
        CALL LineDone
    END SUB
    
    SUB CharcCut
        CALL LineEdit
          LN= LEFT$(LN,(CP-FC))+RIGHT$(LN,(LEN(LN)-(CP-FC+1)))   ': CP=(CP+1)
        CALL LineDone
    END SUB
    
    SUB CharcInsert
        CALL LineEdit
        IF LEN(LN) < = 59 THEN LN= LEFT$(LN,(CP-FC))+ I$ +RIGHT$(LN,(LEN(LN)-(CP-FC))): CP=(CP+1)
        CALL LineDone
    END SUB
     
    SUB CharcOverite
        CALL LineEdit
           LN= LEFT$(LN,(CP-FC))+ I$ +RIGHT$(LN,(LEN(LN)-(CP-FC+1))): CP=(CP+1)
        CALL LineDone
    END SUB
    
    SUB LineEdit
        IF CL = 1 THEN LN =L1: LS = LEN(L1)
        IF CL = 2 THEN LN =L2: LS = LEN(L2)
        IF CL = 3 THEN LN =L3: LS = LEN(L3)
        IF CL = 4 THEN LN =L4: LS = LEN(L4)
        IF CL = 5 THEN LN =L5: LS = LEN(L5)
        IF CL = 6 THEN LN =L6: LS = LEN(L6)
    END SUB
    
    SUB LineDone
        IF CL = 1 THEN L1 = LN:LS = LEN(L1)
        IF CL = 2 THEN L2 = LN: LS = LEN(L2)
        IF CL = 3 THEN L3 = LN: LS = LEN(L3)
        IF CL = 4 THEN L4 = LN: LS = LEN(L4)
        IF CL = 5 THEN L5 = LN: LS = LEN(L5)
        IF CL = 6 THEN L6 = LN: LS = LEN(L6)
    END SUB
    
    SUB KeyBoard
        FC =10
        COLOR FCN,BCN
        CONSOLE NAME "MY 6 LINE TEXT EDITOR"
        CURSOR ON  ,05
        IF CP = 0 THEN CP = FC
    DO
        I$ = WAITKEY$  ' Wait for a key or mouse event
       FL =1
       LL =6
       FV = 9
       NV = 6
       CS =10
       CM =70
          'Current line
        IF CL = 0 THEN CL=1
        IF CP = 0 THEN CP =CS
        IF CV = 0 THEN CV =9
        IF LEN(I$) = 1 AND ASC(I$, 1) = 13 THEN EXIT DO        'Car Return
        IF LEN(I$) = 2 AND ASC(I$, 2) = 71 THEN   CP = FC :CURSOR ON,05        ' Home
        IF LEN(I$) = 2 AND ASC(I$, 2) = 75 THEN   CALL ArrowLeft               '<
        IF LEN(I$) = 2 AND ASC(I$, 2) = 77 THEN   CALL ArrowRight              '>
        IF LEN(I$) = 2 AND ASC(I$, 2) = 80 THEN   CALL ArrowDown :CURSOR ON,05 'Down arrow
        IF LEN(I$) = 2 AND ASC(I$, 2) = 72 THEN   CALL ArrowUp:CURSOR ON,05    'UP arrow
        IF LEN(I$) = 2 AND ASC(I$, 2) = 79 THEN   CP = LS+FC :CURSOR ON,05     'End
     
              'Set up Cursor for insert /Delete
          DO
            'Insert
            IF LEN(I$) = 2 AND ASC(I$, 2) = 82 AND IC$="Insert"  THEN IC$="":CURSOR ON,05 :EXIT DO
            IF LEN(I$) = 2 AND ASC(I$, 2) = 82 AND IC$=""  THEN IC$="Insert" :CURSOR ON,75:EXIT DO
            IF LEN(I$) = 2 AND ASC(I$, 2) = 82 AND IC$="Insert"  THEN IC$="" :CURSOR ON,05:EXIT DO
            'Delete
            IF LEN(I$) = 2 AND ASC(I$, 2) = 83 THEN IC$="" :CURSOR ON,05
          LOOP UNTIL IC$ ="Insert" OR IC$=""
     
              DO
                 'Delete
                IF LEN(I$) = 2 AND ASC(I$, 2) = 83 AND (CP-FC)<LS THEN CALL CharcCut:EXIT DO
    
                  'Insert text WITH insert ON
                IF LEN(I$) = 1 AND IC$ ="Insert" AND ASC(I$, 1)> 31 AND ASC(I$, 1)< 128 THEN CALL CharcInsert:EXIT DO
                  'Insert text WITH insert OFF but cursor location to left of end
                IF LEN(I$) = 1 AND IC$="" AND CP >11  AND CP < 10+LS AND ASC(I$, 1)> 31 AND ASC(I$, 1)< 128 THEN CALL CharcOverite:EXIT DO
    
                  'Add text to end of string
                IF LEN(I$) = 1 AND IC$ ="" AND CP>= 10+LS AND ASC(I$, 1)> 31 AND ASC(I$, 1)< 128 THEN CALL CharcAdd :EXIT DO
                EXIT DO
              LOOP
                          CLS
                          PRINT TAB (55) I$; TAB(65) "CHR$("; ASC(I$, 1); ")"
                          PRINT TAB (55) I$; TAB(65) "CHR$(0,"; ASC(I$, 2); ")"
                          PRINT TAB(2)IC$ TAB(12)"Line " CL TAB(25)"String " LS " Cursor " CP
                          'PRINT""
                          'PRINT""
                          'PRINT""
                          'PRINT""
                          PRINT""
                          PRINT""
                          PRINT""
                          PRINT""
                          PRINT TAB(9)CHR$(201) STRING$(61,CHR$(205)) CHR$(187)
                          PRINT "1" TAB(9)CHR$(186)TAB(10) L1   TAB(71)CHR$(186)
                          PRINT "2" TAB(9)CHR$(186)TAB(10) L2   TAB(71)CHR$(186)
                          PRINT "3" TAB(9)CHR$(186)TAB(10) L3   TAB(71)CHR$(186)
                          PRINT "4" TAB(9)CHR$(186)TAB(10) L4   TAB(71)CHR$(186)
                          PRINT "5" TAB(9)CHR$(186)TAB(10) L5   TAB(71)CHR$(186)
                          PRINT "6" TAB(9)CHR$(186)TAB(10) L6   TAB(71)CHR$(186)
                          PRINT TAB(9)CHR$(200) STRING$(61,CHR$(205))CHR$(188)
                          PRINT""
                          PRINT "Carriage return to EXIT"
                          LOCATE CV, (CP)
     
    
                 IF LEN(I$) = 1 AND ASC(I$, 1) = 13 THEN EXIT DO        'Car Return
                 IF LEN(I$) = 1 AND ASC(I$, 1) = 27 THEN EXIT DO        'Esc
             I$=""
       LOOP UNTIL ASC(I$, 1) = 13
      END SUB
    '------------------------------
    ' Main program entry point...
    '
    
    FUNCTION PBMAIN () AS LONG
     CALL ColorScreen
     CALL KeyBoard
    
    END FUNCTION
    Attached Files

    Leave a comment:


  • Gösta H. Lovgren-2
    replied
    Originally posted by Mel Bishop View Post
    What's a "noodge", Gosta? Is that some kind of Sweedish slang?
    Sure. In American it would be pedantic prissy "pita" {laughing}.

    ====================================
    "The charity that is a trifle to us
    can be precious to others."
    Homer"
    ====================================
    Last edited by Gösta H. Lovgren-2; 26 Oct 2008, 09:34 PM. Reason: Elucidation

    Leave a comment:


  • Chris Holbrook
    replied
    Or you could roll your own character mode input routine. I'm writing a GRAPHIC WINDOW one at the moment using OOP, here is a character mode "vanilla" version .

    This one has simple editing and a fixed field size. It returns the terminating key value, so that you can use arrow keys for navigation, etc etc. It knows nothing of the mouse. It would be an easy change to add in colors, etc.

    (added) ISTR this version started life in the Turbo Pascal Database Toolbox. Wonder what became of that?

    Code:
    ' PBCC string input function
    ' compileable PBCC V5 or (probably) 4
    '  Chris Holbrook Oct 2008
    ' translated from my Pascal code written 1983
    ' and not much tested
    '
    #COMPILE EXE
    #DIM ALL
    %TRUE = 1
    %FALSE = 0
    %KEY_LEFT    = 19200
    %KEY_RIGHT   = 19712
    %KEY_HOME    = 18776
    %KEY_END     = 20224
    %KEY_DEL     = 21248
    %KEY_UP      = 18432
    %KEY_DOWN    = 20480
    %KEY_BSP     = 8
    '--------------------------------------------------------------------------------
    ' function to input a string with rudimentary editing and a fixed max length
    ' returns the terminating character
    FUNCTION inputStr  ( BYREF  S        AS STRING, _        { work string           }
                                L AS LONG, Y AS LONG , X AS LONG,   _        { length,  x & y coords }
                                Term    AS STRING, _        { terminating characters, array of word as a string }
                                UC      AS LONG    _        {Upper case flag }
                        ) AS LONG                          '{ return the terminating char
                        
      LOCAL     P           AS LONG
      LOCAL     i, lTC      AS LONG
      LOCAL     Ch          AS STRING
      LOCAL     Linefeed    AS STRING
      LOCAL     bUntouched  AS LONG
      LOCAL     lorigcursorsize    AS LONG
      LOCAL     pw AS WORD PTR
    
        lorigcursorsize = CURSOR
        CURSOR ON, 100
        LineFeed = S: bUntouched = %true
        P = LEN ( S )
        IF p > L THEN S = LEFT$(s, L )
        LOCATE Y, X
        PRINT S + SPACE$( L - p );
        DO
            LOCATE Y, X + P
            ch = WAITKEY$
            SELECT CASE LEN(ch)
                CASE 1 : lTC = ASC(ch)
                CASE 2 : pw = STRPTR(ch): lTC = @pw
                CASE 4 : ' unexpected mouse response
            END SELECT
            CONSOLE NAME STR$(ltc)
            SELECT CASE AS LONG lTC
                CASE 32 TO 126
                      IF P < L THEN
                          bUntouched = %False
                          IF LEN( S ) = L THEN s = LEFT$(s, l - 1)
                          INCR p
                          IF UC THEN Ch = UCASE$ ( Ch )
                          s = LEFT$(s, p - 1) + ch + MID$(s, p)
                          PRINT MID$( S, P, L);
                      END IF
                CASE %KEY_LEFT
                    IF P > 0 THEN DECR P
                    BEEP
                CASE %KEY_RIGHT : IF P < LEN( S ) THEN INCR P
                CASE %KEY_HOME  : P = 0
                CASE %KEY_END   : P = LEN ( S )
                CASE %KEY_DEL
                    IF P < LEN ( S ) THEN
                        bUntouched = %False
                        s = LEFT$(s, p) + MID$(s, p + 2)
                        PRINT MID$(S, P + 1, L ) + " ";
                    END IF
                CASE %KEY_BSP
                    IF P > 0 THEN
                        bUntouched = %False
                        s = LEFT$(s, p-1) + MID$(s, p + 1)
                        LOCATE Y, x + p - 1
                        PRINT MID$(s, p, l) + " ";
                        DECR p
                    END IF
                CASE ASC($LF), ASC($CR), ASC($ESC), %KEY_UP, %KEY_DOWN, ASC($TAB)
                          IF  ( bUntouched ) OR  ( Ch = $LF ) THEN
                              S = LineFeed
                              P = LEN( S )
                              LOCATE Y, X
                              PRINT S + SPACE$(L - LEN ( S ) );
                          END IF
          END SELECT
          FOR i = 0 TO LEN(term)  STEP 2
              pw = STRPTR(term) + i
              IF @pw = lTC THEN
                  FUNCTION = lTC
                  LOCATE  Y, X + P
                  CURSOR ON, lorigcursorsize
                  EXIT FUNCTION
              END IF
          NEXT
      LOOP
    END FUNCTION
    '-------------------------------------------------------------------
    MACRO mFUNKY(x) = CHR$(LO(BYTE,x)) + CHR$(HI(BYTE,x))
    '-------------------------------------------------------------------
    FUNCTION PBMAIN () AS LONG
        LOCAL s, skey AS STRING
        LOCAL ch, i, tc AS LONG
    
        CONSOLE SET SCREEN 25, 80
        COLOR , 8
        CLS
        s = mfunky(%KEY_UP)
        ? ASC(s) , ASC(MID$(s,2))
        s = "hello"
        ' assumption here that terminating chars are EITHER extended
        ' (ie returned by INKEY$ as 2 char) or < 32.
        ' it could be redone by passing in an array of inkey$ values instead.
        ' NB if the terminating characters are returned as single chars
        ' by INKEY$ then they need a trailing null, else split the %<funkey> value
        ' with a macro
        tc = inputstr( s, 12, 10, 50, $ESC + $NUL + $CR + $NUL + mFUNKY(%KEY_UP), %TRUE)
        LOCATE 15, 50 : ? "terminated by " + STR$(tc) + " " + s
        WHILE skey <> $ESC: skey = INKEY$: WEND
    
    END FUNCTION
    Last edited by Chris Holbrook; 27 Oct 2008, 04:31 AM. Reason: see(added)

    Leave a comment:


  • Michael Mattias
    replied
    My bad, I missed that INPUT is supported for keyboard in both PB/CC 4.03 and 5.00.

    However, in 4.03 it is marked "new" so I guess it was not supported prior to 4x. I know it was not supported in 1x or 2x. Don't remember 3x.

    Leave a comment:


  • Mel Bishop
    replied
    Uhh, MM, did you run his code?

    Kev stated he was using CC4.04 and it works as advertised. Now I don't know about CC 5x since I don't have it but (keyboard) INPUT is supported under CC 4.04

    Leave a comment:


  • Michael Mattias
    replied
    "INPUT varname" is totally valid ....using PB/DOS.
    Code:
    INPUT statement
    ───────────────
    Purpose:  Prompts the user for keyboard entry and assigns the input to
              one or more variables.
    
    Syntax:   INPUT [;] [prompt string {;|,}] variable list
    
    prompt string is an optional string constant. variable list is a comma-
    delimited sequence of one or more string or numeric variables. INPUT
    displays prompt string on the screen, waits for the user to enter data
    from the keyboard, and assigns the data to the variable(s) in variable
    list. If you include a semicolon after prompt string, PowerBASIC outputs
    a question mark after the string. Use a comma instead to suppress the
    question mark. If a semicolon appears immediately after the INPUT keyword,
    the cursor will remain on the same line when you press Return to terminate
    the response. Otherwise, a carriage-return/linefeed pair is sent to the
    display and the cursor moves to the beginning of the next line.
    INPUT as a keyboard statement is not supported in PB/Windows or PB/CC

    LINE INPUT as a keyboard statement IS supported in PB/CC.


    MCM

    Leave a comment:


  • Fred Buffington
    replied
    With PBCC you will need to use
    LINE INPUT prompt$,lResult$

    Then use Val(lResult$) if a number is wanted from the input.
    You should be able to use many input keys (left arrow, backspace, etc) with
    line input.

    I Have converted many QB programs to PBcc then finally to pbwin.

    Leave a comment:


  • Mel Bishop
    replied
    I used his example, without mods, and it ran as advertised. I suppose, here, it's a matter of preferences/options.

    Leave a comment:


  • Rodney Hicks
    replied
    This line:
    INPUT "Please enter your name: " fname$
    should read:
    INPUT "Please enter your name: ", fname$
    with that comma being the only difference. If that was a copy/paste from your file then it might be indicative of some issue.
    Just so you know, when posting code, which we hope you'll do as you feel a need, if you use the # above the edit box, your code is formatted properly for the forum.

    Leave a comment:


  • Chris Holbrook
    replied
    Originally posted by Kevin Brown View Post
    I've recently purchased PB complier
    ...and you bought 4.4 just before V5 came out? That's hard lines.

    Leave a comment:


  • Mel Bishop
    replied
    What's a "noodge", Gosta? Is that some kind of Sweedish slang?

    Leave a comment:


  • Gösta H. Lovgren-2
    replied
    Originally posted by Mel Bishop View Post
    All INPUT is is a way to get text from the keyboard into your program.
    Not to be a noodge but in PBWin, the ONLY "Input" is
    INPUT# statement

    Purpose
    Load variables with data from a sequential file.

    =======================================================
    "A narcissist is someone better looking than you are."
    Gore Vidal
    =======================================================

    Leave a comment:


  • Mel Bishop
    replied
    Hi Kevin. First thread. Welcome to the board.

    All INPUT is is a way to get text from the keyboard into your program. I tried your example and the back space key worked just fine for me.

    Personally, I can't see a useful purpose for cursor movement, insert/delete, etc. since backspace and retype, for me, is a lot faster than breaking the momentum and rhythm of data entry. Besides, it will lead to bloatware having to add the support code.

    I suppose you could "roll your own" routine....

    Leave a comment:


  • Kevin Brown
    replied
    Differences QBasic INPUT to PBasic INPUT

    Gents

    The code I was using is as below, this was just a straight forward extract created to try and understand the PB INPUT function.


    Kevin Brown


    'For Power Basic PBCC 4.04
    SUB MyName
    PRINT""
    PRINT""
    INPUT "Please enter your name: " fname$
    END SUB

    '--------------------------------
    ' Main program entry point...
    '
    FUNCTION PBMAIN () AS LONG
    CALL MyName

    END FUNCTION

    Leave a comment:


  • Gösta H. Lovgren-2
    replied
    Kevin,

    This appears to work as you want.

    '
    Code:
    [B]'PBWIN 9.00[/B] - WinApi 05/2008 - XP Pro SP3
    #Compile Exe                                
    #Dim All 
    #Include "WIN32API.INC"
    #Include "COMDLG32.INC"
     
    Function PBMain
      Local sresult$                        
      sResult$ = InputBox$("Enter your Name",, "Jane Doe")
     
      ? sResult$
    End Function
    '
    The only other use of INPUT in PBWin is for files. I think maybe using a TextBox would be better for what you are describing (all editing keys work in a Textbox as well). Again, as Rodney points out, it depends on the compiler you are using. If you posted code, we (someone) could offer more specific help.

    ===================================
    Between saying and doing,
    many a pair of shoes are worn out.
    (Italian proverb)
    ===================================
    Last edited by Gösta H. Lovgren-2; 26 Oct 2008, 11:51 AM.

    Leave a comment:


  • Rodney Hicks
    replied
    Which compiler are you using PBDos, PBCC, PBWin?

    Leave a comment:


  • Kevin Brown
    started a topic Differences in INPUT QBasic vesus PBasic

    Differences in INPUT QBasic vesus PBasic

    I've recently purchased PB complier and I am having a go at trying to write some code. In the main I am looking at code that I have written and continued to develop using QBasic over the last 15 Years or so, with a view to writing code in PB to execute the same tasks.

    A simple thing puzzles me any maybe someone could explain this to me.

    In Qbasic I made extensive use of the INPUT function to enter all sorts of data, and generally as you typed the data you could use the arrow keys the delete and insert keys to edit the data before using the carriage return to finalise the text, just exactly as I am doing now in this window as I write this post.
    Now however in PBasic the INPUT fuction appreasr to be different, once you have typed a character you can not use the other keys such as left arrow and delete etc to correct any mistakes. Can anyone explain this apparent diffrence to me and advise how I can overcome this.

    Kevin Brown
    Last edited by Kevin Brown; 29 Oct 2008, 10:58 AM. Reason: Workable Solutions to hand
Working...
X