This is a listing of the Sums.exw program (Learning Sums Program):

-- Sums.exw -----------------------------------------------------------------
-- A beginner's program to present randomly generated "sums" on screen for
-- a child user to respond to. The "sums" involve integers in the range
-- 1 to MAX_INTEGER = 12.
-- --------------------------------------------------------------------------

-- In a Euphoria 3.1 program, text lines or parts of text lines preceded by
-- by 2 hyphens, thus: "-- text", are comments.

-- This program is outrageously over-commented, to give programmers who don't
-- use Euphoria(*) (nor the EuWinGUI(**) wrapper) some idea of what's going
-- on. If you successfully plough through the rest of this listing, I hope
-- you will end up by agreeing that Euphoria (and the EuWinGUI wrapper) make
-- writing a simple windows' program like this one a fairly clear and
-- understandable business. I have found them equally good for writing more
-- complex programs as well.

-- (*),(**) : info about Euphoria and EuWinGUI after end of listing.
-- --------------------------------------------------------------------------
-- (c) Fred Mangan (2011)

-- Skeleton's code generated by "The Window Designer for EuWinGUI Applications"
--(C)2001-2006 by Andrea Cini.

--***************************************************************************

-- Start of program code:

-- read in the following "include" files (like header files in C):
include EuWinGUI.ew  -- for the EuWinGUI Library (wrapper)
include Utility.e     -- for function trim()
include Get.e         -- for function value()
include file.e         -- for current_dir()
--***************************************************************************

-- declare handles for main window controls; the main window is automatically
-- assigned the handle WinHwnd by EuWinGUI, so is not declared here:
atom  SelectCalcModeGroup,AddRadio,SubtractRadio,MultiplyRadio,DivideRadio,
      MixedRadio,ProblemStatementText,UserAnswerEdit,DoWhatText,SummaryLabel,
      MoodPicture,MusicTag
--***************************************************************************

-- declare handles of our 2 programmer-created fonts:
atom  FontA,FontB    -- the fonts will be created later
--***************************************************************************

--*** This is a good place to define constant values used throughout the
-- program. Constants are effectively global. This sort of declaration makes
-- it easy later on to change a value across the whole of your program, by
-- simply altering its value here. It can also help make subsequent program code
-- less cryptic, if you invent good descriptive names for constants.

    -- Assorted constants: customarily named using Caps:
    constant
    RPATH = "Resources\\",                             -- path to resource files

    -- file for main music theme:
    MUSIC = RPATH & "amclassical_joplin_the_entertainer_rag.wav",
    MUSIC_DURATION = (4.55 * 60)* 1000,                -- (aprox., millisecs)

    HAPPY_FSPEC   = RPATH & "HappyFace.bmp",        -- other files used
    SUCCESS_SOUND = RPATH & "Success.wav",
    FAILURE_SOUND = RPATH & "Failure.wav",
    HTM_LISTING = ".\\SCode.htm",

    WIN_SIZE = {400,270},                             -- size of main window
    WIN_POSN = {floor((ScreenWidth()-WIN_SIZE[1])/2),-- position for it
                floor((ScreenHeight()-WIN_SIZE[2])/2)
               },

    MAX_INTEGER = 12,    -- max integer value for any number in this game

    ADD_MODE = 1,        -- the calculation modes: 1 ... 5
    SUBTRACT_MODE = 2,
    MULTIPLY_MODE = 3,
    DIVIDE_MODE = 4,
    MIXED_MODE = 5,

    MUL_CHAR = 215,      -- math multiply character
    DIV_CHAR = 247,      -- math divide character

    -- formats for prompting user with "sums":
    PROMPT = { "%2d + %2d =",                -- adding
               "%2d - %2d =",                -- subtracting
               "%2d " & MUL_CHAR & " %2d =", -- multiplying
               "%2d " & DIV_CHAR & " %2d ="  -- dividing
             },

    -- a format string, to display the current state of the game to user:
    SUMMARY_FMAT = " %d answers correct out of %d questions asked."

    --*** Variables declared here will also be global. Programs using
    -- Windows(r) have to be able to "remember stuff" in between the
    -- occurence of user initiated events. Use of global variables like
    -- these is a way to achieve this.

    -- Declare variables used globally, and initial them as needed:
    sequence IntPair         IntPair = {0,0}  -- to hold integer pairs
    integer CalcMode                          -- to flag calculation mode
    integer NGamesPlayed     NGamesPlayed = 0 -- to tally games played
    integer UserScore        UserScore = 0    -- to tally user's score: 1/game
    integer GameOn           GameOn = False   -- to flag game is in progress

--*** Next come the routines (functions and procedures) written by the
-- programmer to make this particular application work.

-- 1. Section has a hard-to-classify routine --------------------------------

procedure ShowMoodPicture(integer delay)
-- This does things necessary for display of the MoodPicture
-- Entry:    delay    = time for which to display picture (ms).

    SetPicture(MoodPicture,Picture,HAPPY_FSPEC) -- load pic to control
    SetDim(MoodPicture,90,60)                    -- make sure it fills control
    SetVisible(UserAnswerEdit,False)            -- vanish the user's edit
    SetVisible(MoodPicture,True)                -- visualise the picture
    PlaySnd(SUCCESS_SOUND)                        -- play the success sound
    SetWinTimer(delay)                            -- time for which to view it

end procedure -- ShowMoodPicture

-- 2. Section deals with setting up a problem for user to solve -------------

procedure GenerateIntegerPair()
-- Randomly generates sequence IntPair such that

--     IntPair = {n[1], n[2]};    1 <= n[2] <= n[1] <= MAX_INTEGER, all integer.

-- This arrangement (next) caters for subtraction so it won't produce -ve results.

    IntPair[1] = rand(MAX_INTEGER-1) + 1    -- range: 2...MAX_INTEGER
    IntPair[2] = rand(IntPair[1])               -- range: 1...n[2]

end procedure -- GenerateIntegerPair

procedure AdjustIntegerPairForDivision()
-- Calculate a random n[2] that will divide evenly into n[1]
-- (a requirement if division is to produce an integer result)
    object x
    integer max

    max = floor(IntPair[1]/2)         -- max value dividend n[2] may have

    x = 1.1                           -- x now not an integer
    while not integer(x) do              -- loop until x holds an integer value

        -- this loop is bound to end, if only with a division by 1
        IntPair[2] = rand(max)          -- range: 1...max
        -- do a trial division, save it in x
        x = IntPair[1] / IntPair[2]      -- calculate new x to test

    end while

end procedure -- AdjustIntegerPairForDivision

procedure SetUpForNewProblem()
-- Creates a problem to be offered to user and displays it.
-- The sort of "sum" is dictated by which radio button is checked.
-- Calls GenerateIntegerPair() and AdjustIntegerPairForDivision()
    sequence text_to_display

    -- set the calculation mode, CalcMode, for current "sum"
    if IsChecked(AddRadio) then
        CalcMode = ADD_MODE                    -- mode: adding
    elsif IsChecked(SubtractRadio) then
        CalcMode = SUBTRACT_MODE            -- mode: subtracting
    elsif IsChecked(MultiplyRadio) then
        CalcMode = MULTIPLY_MODE            -- mode: multiplying
    elsif IsChecked(DivideRadio) then
        CalcMode = DIVIDE_MODE                -- mode: dividing
    elsif IsChecked(MixedRadio) then
        CalcMode = rand(4)                    -- mode: one of 4 above, random
    end if

    GenerateIntegerPair()                    -- basic pair for current "sum"

    -- a special case is division; deal with it:
    if CalcMode = DIVIDE_MODE then

        -- adjust pair to have division give an integer result
        AdjustIntegerPairForDivision()

    end if

    -- display the "sum" to user:
    text_to_display = sprintf(PROMPT[CalcMode],{IntPair[1],IntPair[2]})
    SetText(ProblemStatementText,text_to_display)
    SetText(UserAnswerEdit,"")              -- blank the edit field
    Activate(UserAnswerEdit)              -- focus is now on this field

end procedure -- SetUpForNewProblem

-- 3. Section deals with users response to a "sum" problem ------------------

procedure ServiceTimeout()
-- On timeout does the following things

    SetVisible(MoodPicture,False)      -- vanish the MoodPicture, if displayed
    SetVisible(UserAnswerEdit,True)   -- visualise the user edit
    SetWinTimer(0)                      -- turn off the timer

    if not GameOn then                  -- has user started playing?

        -- user has not started playing
        PlaySnd(MUSIC)                  -- play theme MUSIC
        SetWinTimer(MUSIC_DURATION)   -- trigger for possible MUSIC replay

    end if

    SetUpForNewProblem()               -- prepare a new problem for next game

end procedure -- ServiceTimeout

function Validate(integer user_answer)
-- Check user's arithmetic
    integer ok, right_answer

    -- cumputer needs to know the right_answer: calculate it:
    if CalcMode = ADD_MODE then
        right_answer = IntPair[1] + IntPair[2]
    elsif CalcMode = SUBTRACT_MODE then
        right_answer = IntPair[1] - IntPair[2]
    elsif CalcMode = MULTIPLY_MODE then
        right_answer = IntPair[1] * IntPair[2]
    elsif CalcMode = DIVIDE_MODE then
        right_answer = IntPair[1] / IntPair[2]
    end if

    if user_answer = right_answer then

        -- user has correct answer
        ok = True

    else

        -- user has wrong answer
        ok = False

        -- set up to show correct answer
        SetText(UserAnswerEdit,sprintf("%d",right_answer))

    end if

    return ok        -- tell caller the outcome of user response
end function -- Validate

procedure ComputeUserResult()
-- Processes user's response, to be found in UserAnswerEdit control
-- Calls function Validate()
    sequence response,v
    atom user_answer

    response = trim(GetText(UserAnswerEdit))    -- fetch and trim response

    if length(response) > 0 then

        -- possible valid input; get its numeric value
        v = value(response)

        if v[1] = GET_SUCCESS then

            -- user has a number of some sort
            user_answer = v[2]                -- get users numeric answer
            NGamesPlayed += 1                -- advance game counter

            if integer(user_answer) then

                -- have legal (integer) input; test it in Validate()
                if Validate(user_answer) then

                    -- user has correct answer
                    UserScore +=1             -- advance user's score
                    ShowMoodPicture(2000)     -- show success picture

                else

                    -- user has a wrong answer
                    PlaySnd(FAILURE_SOUND)
                    SetWinTimer(2000)

                end if

            else

                -- user typed a decimal number - count it as wrong
                PlaySnd(FAILURE_SOUND)

            end if

        else

            -- user typed rubbish: just put him/her back into Edit, no penalty
            SetText(UserAnswerEdit,"")
            Activate(UserAnswerEdit)

        end if

    else

        -- user's field is empty: just put him back into it, with no penalty
        Activate(UserAnswerEdit)

    end if

    -- report state-of-play summary:
    SetText(SummaryLabel,sprintf(SUMMARY_FMAT,{UserScore,NGamesPlayed}))

    -- suppress playing of music while game is in progress
    GameOn = True

end procedure -- ComputeUserResult

procedure ProcessUserInput()
-- Over-all control of checking user response and of scoring

    if EventItem = KEY_ENTER then

        -- process user's (possible) response in UserAnswerEdit
        ComputeUserResult()

        -- you might expect a call to SetUpForNewProblem() here;
        -- but it was found better to transfer the call to
        -- procedure ServiceTimeout(), so that theme MUSIC plays
        -- only at the start of the first game and not (distractingly)
        -- during actual game play.

    else

        -- user is just typing ... let him finish doing so by doing nothing

    end if

end procedure -- ProcessUserInput

-- 4. Section handles program terminating routine ---------------------------

procedure TerminatingRoutine()
    sequence message
    integer dummy

    message = "Do you want to view this program's source code?"
    if AskMsg(message, "View Source Code") then

        -- call up htm containing a copy of the program code:
        RunApp("Explorer.exe",HTM_LISTING)    -- note: needed full form

    end if

end procedure -- TerminatingRoutine

-- 5. Section handles most of program initialling ---------------------------

procedure Initialize()
-- Does initialling of main window (system handle: WinHwnd) and its controls
-- and establishes conditions for first game.
-- Much of the code in this procedure was generated by the "Designer". I have
-- tweaked it here and there.

    CloseEventEnabled = True

    -- create programmer's fonts; fonts can be external if wished
    --              name,        pt, bold, italic, u-line
    FontA = NewFont("FN_DEFAULT",48, True, False,  False) -- a real big font
    FontB = NewFont("FN_DEFAULT",12, True, False,  False) -- a bit of bolding

    -- create main window:
    WindowType = NoMaxWin
    ShowFlag = False
    Window("Starting Arithmetic",WIN_POSN[1],WIN_POSN[2],WIN_SIZE[1],WIN_SIZE[2])
    ShowFlag = True
    SelectCalcModeGroup = Control(Group,
                                  "   Select the sort of Tables to do   ",
                                  10,10,
                                  370,85)
    AddRadio = Control(Radio,"ADDITION",80,30,110,25)
    SubtractRadio = Control(Radio,"SUBTRACTION",200,30,110,25)
    MultiplyRadio = Control(Radio,"MULTIPLICATION",20,60,110,25)
    DivideRadio = Control(Radio,"DIVISION",140,60,110,25)
    MixedRadio = Control(Radio,"MIXED MODE",260,60,110,25)
    ProblemStatementText = Control(Text,"12 + 12 =",40,110,210,50)
    UserAnswerEdit = Control(Edit,"24",250,104,90,55)
    -- MoodPicture will overlie UserAnswerEdit to show a picture in its place
    MoodPicture = Control(Picture,"",250,104,90,60)
    DoWhatText = Control(Text,
                         "TYPE YOUR ANSWER THEN PRESS THE ENTER KEY",
                         40,170,
                         280,20)
    SummaryLabel = Control(Label,sprintf(SUMMARY_FMAT,{0,0}),50,200,280,15)
    MusicTag = Control(Label,
                       "Music: The Entertainer Rag - recording (c) amclassical.com",
                       50,WIN_SIZE[2]-50,
                       280,20)

    -- apply programmer's fonts selectively:
    -- (anything else printed on WinHwnd or its controls will use EuWinGUI's
    -- FN_DEFAULT font, size 12 pt. plain, by default).
    SetFont(ProblemStatementText,FontA)
    SetFont(UserAnswerEdit,FontA)
    SetFont(SummaryLabel,FontB)

    -- set colouring to enhance appearance of some controls:
    -- (this was all done visually in the "Designer")
    SetColor(SelectCalcModeGroup,CL_WHITE,CL_RED)
    SetColor(AddRadio,CL_WHITE,CL_BLUE)
    SetColor(SubtractRadio,CL_WHITE,CL_BLUE)
    SetColor(MultiplyRadio,CL_WHITE,CL_BLUE)
    SetColor(DivideRadio,CL_WHITE,CL_BLUE)
    SetColor(MixedRadio,CL_WHITE,CL_BLUE)
    SetColor(ProblemStatementText,CL_RED,CL_DEFAULT)
    SetColor(UserAnswerEdit,CL_RED,CL_DEFAULT)
    SetColor(SummaryLabel,CL_WHITE,CL_BLUE)

    SetVisible(WinHwnd,True)   -- make the main window visible
    SetCheck(AddRadio,True)       -- have at least one radio button checked

    ShowMoodPicture(2000)       -- display this

    SetUpForNewProblem()       -- initial the first "sum"

end procedure -- Initialize

-- 6. Section deals with the EventLoop --------------------------------------

--*** Every program skeleton generated by the "Designer" has an EventLoop()
-- procedure. It contains an endless closed "while" loop in which occurence
-- of user-generated events is tested for. When one occurs, the programmer
-- can modify and add to code in the loop so that loop code will test for
-- occurence of events of interest to the particular program being written
-- and will call procedures or functions accordingly.

-- The EventLoop() in this program responds to only a few events since this
-- is a relatively simple program. I have left unused code in the loop in
-- place so you can see something of the range of events that an EventLoop()
-- can respond to.

procedure EventLoop()

while True do
 WaitEvent()

 if Event = Click then            -- if there is a left-click on the mouse

   -- if any radio button is clicked, start a new problem
   -- (code here is, perhaps, a bit inelegant, but it is clear).
   if EventOwner = AddRadio then
       SetUpForNewProblem()
   elsif EventOwner = SubtractRadio then
       SetUpForNewProblem()
   elsif EventOwner = MultiplyRadio then
       SetUpForNewProblem()
   elsif EventOwner = DivideRadio then
       SetUpForNewProblem()
   elsif EventOwner = MixedRadio then
       SetUpForNewProblem()
   end if

 end if

 if Event = RClick then          -- our program is not interested in this event
                               -- (right-click with mouse)

   if EventOwner = WinHwnd then

   end if

 end if

 if Event = Release then       -- our program is not interested in this event
                                -- (release of mouse left-button)

   if EventOwner = WinHwnd then

   end if

 end if

 if Event = RRelease then      -- our program is not interested in this event
                               -- (release of mouse right-button)

   if EventOwner = WinHwnd then

   end if

 end if

 if Event = Move then          -- our program is not interested in this event
                               -- (movement of the mouse)

   if EventOwner = WinHwnd then

   end if

 end if

 if Event = Key then           -- if a keyboard key was pressed

   if EventOwner = UserAnswerEdit then

         ProcessUserInput()       -- call our key handling routine

   end if

 end if

 if Event = Restore then       -- our program is not interested in this event
                               -- (restoring  program from toolbar)

   if EventOwner = WinHwnd then

   end if

 end if

 if Event = Close then        -- is it a "Close" event?

   -- it is a "Close"
   if EventOwner = WinHwnd then   -- was it generated at main window?

           -- it was generated by main window, so ...
           TerminatingRoutine()
           return                 -- ... quit this procedure
           -- this gets us out of the endless loop and will let the calling
           -- procedure, WinMain(), close the program.

   end if

 end if

 if Event = Time then             -- is it a WinTimer (timeout) event?

    -- it is a WinTimer event, so ...
    ServiceTimeout()             -- ... call our timeout handling routine

 end if

 if Event = HotKey then        -- our program is not interested in this event
                               -- (a press on the Tab key)

 end if

end while

end procedure -- EventLoop
--***************************************************************************

-- 7. Section deals with the WinMain() procedure ----------------------------

procedure WinMain()
--*** The "Designer" always generates code for this routine. In this program
-- it has been modified to do 3 things as commented below

    Initialize()    -- 1. do all main initialling of program

    EventLoop()        -- 2. run the EventLoop()

    CloseApp(0)        -- 3. we're finished; close the program

end procedure -- WinMain
--***************************************************************************

WinMain()    -- fire-up the program by calling WinMain() procedure

-- end of program code ---------------------------------------------------------

-- SOME EXPLANATION OF EUPHORIA AND EUWINGUI:

-- (*) This program is coded for EUPHORIA version 3.1. Version 4.0.0 has
-- recently been released containing many enhancements and more directed
-- towards programming for Windows; it may still be a bit buggy.
-- Version 3.1 is probably easier for beginners to use and is very stable.
-- Both versions are available to run under Windows and under some popular
-- versions of Unix (FreeBSD, Linux, etc.).
-- Euphoria is free, Open Source in the public domain; it can be used more
-- or less by anyone for any purpose.
-- Other extensions available for Euphoria include:

--    * OOP wrappers: Euphoria itself is a procedural language but can be extended
--    to use OOP definitions and methods via a number of OOP wrappers.

--  * Euphoria to C translator: where top speed is essential, critical code
--      can be translated to C.

--    * Database: The "Euphoria Database System" (EDS) can be incorporated
--        into Euphoria programs. EDS provides indexed database files which
--        can be created, interrogated and retrieved from using near English-
--        like statements. An EDS data file can hold about 2GB of data. There
--        is no limit on the number of data files you can have. EDS Tables
--        can contain any or all of the data object(s) supported by Euphoria.

--    * Binding: all Euphoria programs can be "bound" to a copy of the
--        of the Euphoria Interpreter to produce a directly executable (exe)
--        file which will run the program without having to invoke the
--        interpreter by name. In such files your code is "shrouded" and
--        can't be read or tinkered with by users.

-- (**) EuWinGUI.ew is an easy-to-use Library file giving the programmer
-- simplified access to the Windows' API, or the Unix equivalent.
-- Euphoria has a more advanced wrapper (Win32Lib.ew). It is for more
-- ambitious or advanced Windows programmers.

--*** The "The Window Designer for EuWinGUI Applications" (the "Designer"
-- from now on) is a simple IDE with which you can create the main window,
-- the secondary windows (if any), and lay out the controls (buttons, text,
-- edit fields, and so on) to be used by your program. The IDE can save your
-- design for future development, and also can output "skeleton" code for
-- your program written as Euphoria statements, and as statements which
-- EuWinGUI.ew and EuWinGUI.dll can understand.

-- More information and free downloads at RapidEuphoria.com.

Conversion to HTML by PC2HTM.EXE