12-09-2022, 12:54 PM
Here is a progress of my Grade Keeper. It is really feeling like a student management system right now. I need to figure out to do a multiple page report without rewriting the wheel, but we will see. I also need to start on the gradebook side. I have ideas (homework completion is one vs strict 100-point grade which is useless in primary per se)
A lot of additions and changes. I know, I know, no mouse. I have never really dug into mouse use, but I can program how to read my PS3 controller (priorities right?) I will look at that after adding a basic grade book perhaps? Maybe a more experienced programmer can say good idea/bad idea. My longest program yet running over 1,500 lines.
Well, all constructive feedback is welcome. I also include a few fun files to let you play around without too much setup if you like.
[/url][url=https://ibb.co/5Yrx193]
A lot of additions and changes. I know, I know, no mouse. I have never really dug into mouse use, but I can program how to read my PS3 controller (priorities right?) I will look at that after adding a basic grade book perhaps? Maybe a more experienced programmer can say good idea/bad idea. My longest program yet running over 1,500 lines.
Well, all constructive feedback is welcome. I also include a few fun files to let you play around without too much setup if you like.
Code: (Select All)
'====================================================================================
'| |
'| Grade Keeper Build 3 V: 0.4 |
'| Release #2 December 2022 |
'| Additions: #1 - Major student database functions work (add, modify, delete) |
'| #2 - Teacher info collected |
'| #3 - Teacher reports established (except for index cards) |
'| #4 - Ability to remove program files. |
'| |
'| Modifications: #1 - Pause now doesn't race the CPU |
'| #2 - Start transition to building data screens (less files) |
'| #3 - Loops limited to prevent CPU racing |
'| |
'| Current Limitations: #1 - Student records limited to 33 students |
'| #2 - Printed reports limited to windows |
'| #3 = Printed reports limited to 1 page |
'| |
'====================================================================================
'$DYNAMIC
$NOPREFIX
OPTION EXPLICIT
OPTION BASE 1
'Standard file # list (Same # throughout for one file type)
'#1 is namelist.gkn for student name list
'#2 is teacher.gkn for teacher and school info
CONST FALSE = 0, TRUE = NOT FALSE, LIMITRATE = 20, TIME = .1 'Global loop speed limit to control CPU usage: Delay timer
TYPE NameListType 'Used for the student name database
PinYinName AS STRING * 20
FirstName AS STRING * 20
MiddleName AS STRING * 20
LastName AS STRING * 20
Year AS INTEGER
Month AS INTEGER
Day AS INTEGER
HouseColor AS STRING * 8
MomName AS STRING * 30
MomPhone AS STRING * 20 'Saved as string to support symbols and international prefixes
MomEmail AS STRING * 38
DadName AS STRING * 30
DadPhone AS STRING * 20
DadEmail AS STRING * 38
END TYPE
TYPE TeacherType 'Info for reports and such
TeacherName AS STRING * 50
School AS STRING * 100
Grade AS STRING * 10
Class AS STRING * 10
Classroom AS STRING * 10
END TYPE
DIM SHARED AS NameListType NameList(10) 'Student list
DIM SHARED AS TeacherType Teacher 'Teacher/class info
DIM SHARED AS LONG ScreenPointer(5), Arial8, Arial12, Arial16 'Screen & font handles
DIM SHARED AS LONG Arial24, Arial32, Arial48, Arial60 'Font handles
DIM SHARED AS LONG Intro, AboutPic, Current, CheckSelect, Report, BlankData 'Picture handles
DIM SHARED AS LONG NewNameEntry, DisplayStudentData, CurrentLayout, Generic 'Picture handles
DIM SHARED AS INTEGER Counter 'Throw-away counter
DIM SHARED AS INTEGER NumberOfStudents
DIM SHARED AS INTEGER Pointer 'Used for menu selections
DIM SHARED AS BIT SelectFlag 'Used to prevent graphic glitches and/or escape loops
'Loading needed screen space
TITLE "Grade Keeper Alpha Version 0.4"
DISPLAY 'Turn off Auto Display
SCREEN NEWIMAGE(1280, 720, 32)
SCREENMOVE 0, 0
ScreenPointer(1) = DEST 'Main screen
FOR Counter = 2 TO 5 'Screen 5 is exclusive use of QUICKMESSAGE text printing
ScreenPointer(Counter) = NEWIMAGE(1280, 720, 32)
NEXT Counter
'Loading assets
AboutPic = LOADIMAGE("data/assets/about.png", 32)
BlankData = LOADIMAGE("data/assets/blankdat.png", 32)
CheckSelect = LOADIMAGE("data/assets/check.png", 32)
Current = LOADIMAGE("data/assets/current.png", 32)
CurrentLayout = LOADIMAGE("data/assets/cslayout.png", 32)
DisplayStudentData = LOADIMAGE("data/assets/showname.png", 32)
Generic = LOADIMAGE("data/assets/blank.png", 32)
Intro = LOADIMAGE("data/assets/title.png", 32)
NewNameEntry = LOADIMAGE("data/assets/newname.png", 32)
Report = LOADIMAGE("data/assets/reports.png", 32)
'Font sizes
Arial8 = LOADFONT("data/assets/arial.ttf", 8) 'For grades and later use
Arial12 = LOADFONT("data/assets/arial.ttf", 12) 'For grades and later use
Arial16 = LOADFONT("data/assets/arial.ttf", 16) 'For grades and later use
Arial24 = LOADFONT("data/assets/arial.ttf", 24)
Arial32 = LOADFONT("data/assets/arial.ttf", 32)
Arial48 = LOADFONT("data/assets/arial.ttf", 48)
Arial60 = LOADFONT("data/assets/arial.ttf", 60)
DO: LIMIT LIMITRATE: MAINMENU: LOOP 'Main program loop
SYSTEM
errorhandle: 'Error handling
DIM AS STRING ErrorCode
ErrorCode = "Error" + STR$(ERR) + " on program file line" + STR$(ERRORLINE) + ". Program will end."
QUICKMESSAGE ErrorCode, 48, 1
SYSTEM
SUB MAINMENU
IF NOT FILEEXISTS("data/current/teacher.gkn") THEN 'prompt for teacher info if not on record
QUICKMESSAGE "Please go to " + CHR$(34) + "options" + CHR$(34) + CHR$(26) + CHR$(34) +_
"teacher info" + CHR$(34) + " to enter your name and school. Thank you!", 32, 1
ELSE
OPEN "data/current/teacher.gkn" FOR INPUT AS #2
AUTODISPLAY
IF LOF(2) = 200 THEN 'Corruption and tamper check
INPUT #2, Teacher.TeacherName
INPUT #2, Teacher.School
INPUT #2, Teacher.Grade
INPUT #2, Teacher.Class
INPUT #2, Teacher.Classroom
ELSE
QUICKMESSAGE "Teacher file corrupted! Please reenter data on the option screen.", 32, 1
END IF
CLOSE #2
END IF
Pointer = 0: SelectFlag = FALSE
PAUSE (TIME)
SCREEN ScreenPointer(1)
DO
LIMIT LIMITRATE
CLS
PUTIMAGE (0, 0), Intro
SELECT CASE Pointer
CASE 0: PUTIMAGE (375, 221), CheckSelect
CASE 1: PUTIMAGE (375, 292), CheckSelect
CASE 2: PUTIMAGE (375, 365), CheckSelect
CASE 3: PUTIMAGE (375, 437), CheckSelect
CASE 4: PUTIMAGE (375, 510), CheckSelect
END SELECT
DISPLAY
IF SelectFlag THEN PAUSE (TIME) 'Avoid double press delay
SelectFlag = FALSE
'Checking for key press (keyboard)
IF KEYDOWN(CVI(CHR$(0) + "H")) THEN ' up case
IF Pointer = 0 THEN Pointer = 4 ELSE Pointer = Pointer - 1
SelectFlag = TRUE
END IF
IF KEYDOWN(CVI(CHR$(0) + "P")) THEN 'down case
IF Pointer = 4 THEN Pointer = 0 ELSE Pointer = Pointer + 1
SelectFlag = TRUE
END IF
LOOP UNTIL KEYDOWN(13) OR KEYDOWN(32) 'Return/Spacebar to select
SELECT CASE Pointer
CASE 0: CURRENTCLASS
CASE 1: 'ARCHIVEDCLASS
CASE 2: OPTIONS
CASE 3: ABOUT
CASE 4: SYSTEM
END SELECT
END SUB
'For configuration & archiving/restoring existing classes - Future release
SUB OPTIONS
DIM AS INTEGER Row, Column
DIM AS LONG Script
SCREEN ScreenPointer(2)
Pointer = 0
DO
LIMIT LIMITRATE
DO
'Prepare and draw the menu
LIMIT LIMITRATE
CLS
PUTIMAGE , Generic
Script = LOADFONT("data/assets/script.ttf", 96)
FONT Script
Row = 2: Column = 1280 / 2 - PRINTWIDTH("Options") / 2
LOCATE Row, Column: PRINT "Options";
FONT Arial24
FREEFONT Script
Script = LOADFONT("data/assets/script.ttf", 60)
FONT Script
Row = 5: Column = 250
LOCATE Row, Column: PRINT "Teacher Info"
LOCATE Row + 1, Column: PRINT "Archive Current Class & Gradebook(s)"
LOCATE Row + 2, Column: PRINT "Program Reset Options"
LOCATE Row + 3, Column: PRINT "Back"
FONT Arial24
FREEFONT Script
SELECT CASE Pointer
CASE 0: PUTIMAGE (190, 240), CheckSelect
CASE 1: PUTIMAGE (190, 300), CheckSelect
CASE 2: PUTIMAGE (190, 360), CheckSelect
CASE 3: PUTIMAGE (190, 420), CheckSelect
END SELECT
DISPLAY
IF SelectFlag THEN PAUSE (.125) 'Avoid double press delay
SelectFlag = FALSE
'Checking for key press (keyboard)
IF KEYDOWN(CVI(CHR$(0) + "H")) THEN ' up case
IF Pointer = 0 THEN Pointer = 3 ELSE Pointer = Pointer - 1
SelectFlag = TRUE
END IF
IF KEYDOWN(CVI(CHR$(0) + "P")) THEN 'down case
IF Pointer = 3 THEN Pointer = 0 ELSE Pointer = Pointer + 1
SelectFlag = TRUE
END IF
LOOP UNTIL KEYDOWN(13) OR KEYDOWN(32) 'Return or Space bar to select
'Execute choice
SELECT CASE Pointer
CASE 0: TEACHERINFO
CASE 1: 'Future release
CASE 2: RESETPROGRAM
END SELECT
LOOP UNTIL Pointer = 3
SCREEN ScreenPointer(1)
END SUB
'Deletes data files as requested
SUB RESETPROGRAM
DIM AS INTEGER X, Y
DIM AS STRING Delete
DIM AS BYTE DeleteTeacher, DeleteStudents
DeleteTeacher = FALSE: DeleteStudents = FALSE
'Required warning
BEEP
QUICKMESSAGE "This operation is unrecoverable!", 60, 2
BEEP
QUICKMESSAGE "Note: Printed reports WILL NOT be removed. Please take care of student data.", 32, 2
SCREEN ScreenPointer(3)
CLS: PUTIMAGE , Generic
FONT Arial32
AUTODISPLAY
'#1 - Student name list
IF FILEEXISTS("data/current/namelist.gkn") THEN
X = 1280 / 2 - PRINTWIDTH("Remove ALL Student infomation (type all caps YES to confirm)? ") / 2
Y = (HEIGHT / FONTHEIGHT) / 2 - 5
LOCATE Y, X: INPUT "Remove ALL Student infomation (type all caps YES to confirm)? ", Delete
IF Delete = "YES" THEN DeleteStudents = TRUE
ELSE
QUICKMESSAGE "Student info NOT ON FILE. No action required.", 32, 3
END IF
'#2 - Teacher and school info
IF FILEEXISTS("data/current/teacher.gkn") THEN
X = 1280 / 2 - PRINTWIDTH("Remove teacher & school info (type all caps YES to confirm)? ") / 2
Y = Y + 2
LOCATE Y, X: INPUT "Remove teacher & school info (type all caps YES to confirm)? ", Delete
IF Delete = "YES" THEN DeleteTeacher = TRUE
ELSE
QUICKMESSAGE "Teacher info NOT ON FILE. No action required.", 32, 3
END IF
'Build our delete file string or escape for abort
Delete = ""
IF DeleteStudents THEN
Delete = "student information"
ELSEIF DeleteTeacher THEN
Delete = "teacher information"
END IF
IF DeleteTeacher AND DeleteStudents THEN
Delete = Delete + " and teacher information"
ELSEIF NOT DeleteTeacher AND NOT DeleteStudents THEN
Delete = "no files"
END IF
IF DeleteStudents OR DeleteTeacher THEN
Delete = "You are removing " + Delete + "."
ELSE
BEEP
QUICKMESSAGE "No action taken. Please try again if you desire.", 32, 3
PAUSE TIME
DISPLAY
SCREEN ScreenPointer(2)
EXIT SUB
END IF
'Final comfirmation
X = 1280 / 2 - PRINTWIDTH(Delete) / 2
Y = Y + 2
LOCATE Y, X: PRINT Delete
X = 1280 / 2 - PRINTWIDTH("Are you sure (Type YES to confirm? ") / 2
Y = Y + 1
LOCATE Y, X: INPUT "Are you sure (Type YES to confirm? ", Delete
'Execute file removal or abort
IF Delete = "YES" AND (DeleteStudents OR DeleteTeacher) THEN
IF DeleteStudents THEN KILL "data/current/namelist.gkn"
IF DeleteTeacher THEN KILL "data/current/teacher.gkn"
BEEP
QUICKMESSAGE "Files deleted. Please take care of all printed reports.", 32, 3
ELSE
BEEP
QUICKMESSAGE "No action taken. Please try again if you desire.", 32, 3
END IF
PAUSE TIME
DISPLAY
SCREEN ScreenPointer(2)
END SUB
SUB CURRENTCLASS
PAUSE (TIME)
Pointer = 0
DO
LIMIT LIMITRATE
DO
LIMIT LIMITRATE
CLS 'Prepare and draw the menu
PUTIMAGE (0, 0), Current
SELECT CASE Pointer
CASE 0: PUTIMAGE (260, 190), CheckSelect
CASE 1: PUTIMAGE (260, 280), CheckSelect
CASE 2: PUTIMAGE (260, 380), CheckSelect
END SELECT
DISPLAY
IF SelectFlag THEN PAUSE (.125) 'Avoid double press delay
SelectFlag = FALSE
'Checking for key press (keyboard)
IF KEYDOWN(CVI(CHR$(0) + "H")) THEN ' up case
IF Pointer = 0 THEN Pointer = 2 ELSE Pointer = Pointer - 1
SelectFlag = TRUE
END IF
IF KEYDOWN(CVI(CHR$(0) + "P")) THEN 'down case
IF Pointer = 2 THEN Pointer = 0 ELSE Pointer = Pointer + 1
SelectFlag = TRUE
END IF
LOOP UNTIL KEYDOWN(13) OR KEYDOWN(32) 'Return or Space bar to select
'Execute choice
SELECT CASE Pointer
CASE 0: 'LOADGRADES
CASE 1: LOADNAMES
END SELECT
LOOP UNTIL Pointer = 2
END SUB
SUB LOADGRADES 'Future release
END SUB
SUB LOADNAMES
DIM AS INTEGER Rows, Columns, RowStep, ColumnStep, StartX, StartY, OffsetX
DIM AS STRING FirstName, LastName
DIM AS INTEGER Highlight(500000)
DIM AS BIT Selected, Back
IF FILEEXISTS("data/current/namelist.gkn") THEN 'Display current list if it exists
LOADSTUDENTDATA
SORT 1
DIM AS INTEGER BuildCounter
Rows = 3: Counter = 1: StartX = 4: StartY = (Rows - 1) * FONTHEIGHT(Arial32)
DO 'Keep looping until explicitly told to return to prior menu
LIMIT LIMITRATE
FONT Arial32
BuildCounter = 1: Rows = 3: Columns = 15: RowStep = FONTHEIGHT(Arial32): ColumnStep = 625: OffsetX = 604
Back = FALSE
CLS
PUTIMAGE (0, 0), CurrentLayout 'Simple box layout
WHILE BuildCounter <= NumberOfStudents 'Prints student names to screen
FirstName = TRIM$(NameList(BuildCounter).FirstName)
LastName = TRIM$(NameList(BuildCounter).LastName)
LOCATE Rows, Columns: PRINT FirstName + " " + LastName
BuildCounter = BuildCounter + 1
Rows = Rows + 1
IF BuildCounter = 19 THEN
Rows = 3
Columns = 15 + ColumnStep
END IF
WEND
LOCATE Rows, Columns: PRINT "Add student to class"
LOCATE Rows + 1, Columns: PRINT "Whole class data reports"
LOCATE Rows + 2, Columns: PRINT "Go back to the prior screen"
Selected = FALSE
PAUSE (TIME)
GET (StartX, StartY)-(StartX + OffsetX, StartY + RowStep), Highlight()
PUT (StartX, StartY), Highlight(), PRESET
DO 'GUI student interface selection
LIMIT LIMITRATE
DISPLAY
IF KEYDOWN(18432) THEN 'up case
IF Counter = 1 THEN 'Top of table check
'Do nothing, ignore key press
ELSE 'Process the change
GET (StartX, StartY)-(StartX + OffsetX, StartY + RowStep), Highlight()
PUT (StartX, StartY), Highlight(), PRESET
IF Counter = 19 THEN
StartX = 4
StartY = 640
END IF
StartY = StartY - RowStep
GET (StartX, StartY)-(StartX + OffsetX, StartY + RowStep), Highlight()
PUT (StartX, StartY), Highlight(), PRESET
Counter = Counter - 1
PAUSE (TIME)
END IF
END IF
IF KEYDOWN(20480) THEN 'down case
IF NumberOfStudents + 3 = Counter THEN 'Bottom of table check
'Do nothing, ignore key press
ELSE 'Process the change
GET (StartX, StartY)-(StartX + OffsetX, StartY + RowStep), Highlight()
PUT (StartX, StartY), Highlight(), PRESET
IF Counter = 18 THEN
StartX = 628
StartY = 32
END IF
StartY = StartY + RowStep
GET (StartX, StartY)-(StartX + OffsetX, StartY + RowStep), Highlight()
PUT (StartX, StartY), Highlight(), PRESET
Counter = Counter + 1
PAUSE (TIME)
END IF
END IF
IF KEYDOWN(19712) THEN 'right case
IF StartX = 628 OR Counter + 18 > NumberOfStudents + 3 THEN 'Already on the left or going off table
'Do nothing, ignore key press
ELSE
GET (StartX, StartY)-(StartX + OffsetX, StartY + RowStep), Highlight()
PUT (StartX, StartY), Highlight(), PRESET
StartX = 628
GET (StartX, StartY)-(StartX + OffsetX, StartY + RowStep), Highlight()
PUT (StartX, StartY), Highlight(), PRESET
Counter = Counter + 18
PAUSE (TIME)
END IF
END IF
IF KEYDOWN(19200) THEN 'left case
IF StartX = 4 THEN 'Already on the left
'Do nothing, ignore key press
ELSE
GET (StartX, StartY)-(StartX + OffsetX, StartY + RowStep), Highlight()
PUT (StartX, StartY), Highlight(), PRESET
StartX = 4
GET (StartX, StartY)-(StartX + OffsetX, StartY + RowStep), Highlight()
PUT (StartX, StartY), Highlight(), PRESET
Counter = Counter - 18
PAUSE (TIME)
END IF
END IF
IF KEYDOWN(13) OR KEYDOWN(32) THEN 'Select a choice and exit the loop
Selected = TRUE
PAUSE (TIME)
GET (StartX, StartY)-(StartX + OffsetX, StartY + RowStep), Highlight()
PUT (StartX, StartY), Highlight(), PRESET
END IF
LOOP WHILE NOT Selected
SELECT CASE Counter 'Process selected choice
CASE 1 TO NumberOfStudents: SHOWSTUDENTDATA Counter: SORT 1
CASE NumberOfStudents + 1: ADDSTUDENT: SORT 1
Rows = 3: Counter = 1 'Start at the top of the list
StartX = 4: StartY = (Rows - 1) * FONTHEIGHT(Arial32)
CASE NumberOfStudents + 2: STUDENTREPORTS
CASE NumberOfStudents + 3: Back = TRUE 'Return to prior meny
END SELECT
LOOP UNTIL Back
PAUSE (TIME)
ELSE
CREATESTUDENTLIST
END IF
END SUB
'Displays student data to screen and modifies or deletes said student
SUB SHOWSTUDENTDATA (Student AS INTEGER)
DIM AS BIT ExitFlag
ExitFlag = FALSE
SCREEN ScreenPointer(2)
CLS
PUTIMAGE (0, 0), DisplayStudentData
FONT Arial24
QUICKPRINTSTUDENTDATA NameList(Student), Student
DISPLAY
PAUSE (TIME)
DO
LIMIT LIMITRATE
IF KEYDOWN(109) OR KEYDOWN(77) THEN 'Modify a student
DIM AS NameListType UpdateData 'Holds data, only overwrites fields with data present
DIM AS STRING Blank8, Blank20, Blank30 'Used to check for blank entries of fixed strings
Blank8 = " "
Blank20 = " "
Blank30 = " "
ExitFlag = FALSE
COLOR RGB32(196, 255, 14)
FONT Arial32
LOCATE 19, 750: PRINT "If a data field requires no update,"
LOCATE 20, 750: PRINT "you may just press enter."
DISPLAY
COLOR RGB32(255, 255, 255)
FONT Arial24
AUTODISPLAY
LOCATE 7, 140: PRINT Counter 'Built with Arial24
PAUSE (TIME)
LOCATE 7, 280: INPUT "", UpdateData.PinYinName
DO
LOCATE 7, 710: PRINT " "
LOCATE 7, 710: INPUT "", UpdateData.Month
LOOP UNTIL UpdateData.Month = 0 OR (UpdateData.Month > 0 AND UpdateData.Month < 13)
DO
LOCATE 7, 780: PRINT " "
LOCATE 7, 780: INPUT "", UpdateData.Day
LOOP UNTIL UpdateData.Day = 0 OR (UpdateData.Day > 0 AND UpdateData.Day < 32)
DO
LOCATE 7, 840: PRINT " "
LOCATE 7, 840: INPUT "", UpdateData.Year
LOOP UNTIL UpdateData.Year = 0 OR (UpdateData.Year > 2000 AND UpdateData.Year < 2100)
LOCATE 7, 970: INPUT "", UpdateData.HouseColor
LOCATE 12, 55: INPUT "", UpdateData.FirstName
LOCATE 12, 400: INPUT "", UpdateData.MiddleName
LOCATE 12, 780: INPUT "", UpdateData.LastName
LOCATE 17, 55: INPUT "", UpdateData.MomName
LOCATE 17, 400: INPUT "", UpdateData.MomPhone
LOCATE 17, 780: INPUT "", UpdateData.MomEmail
LOCATE 22, 55: INPUT "", UpdateData.DadName
LOCATE 22, 400: INPUT "", UpdateData.DadPhone
LOCATE 22, 780: INPUT "", UpdateData.DadEmail
DISPLAY
IF UpdateData.PinYinName = Blank20 THEN UpdateData.PinYinName = NameList(Student).PinYinName 'Replace blank entries with current data
IF UpdateData.FirstName = Blank20 THEN UpdateData.FirstName = NameList(Student).FirstName
IF UpdateData.MiddleName = Blank20 THEN UpdateData.MiddleName = NameList(Student).MiddleName
IF UpdateData.LastName = Blank20 THEN UpdateData.LastName = NameList(Student).LastName
IF UpdateData.Year = 0 THEN UpdateData.Year = NameList(Student).Year
IF UpdateData.Month = 0 THEN UpdateData.Month = NameList(Student).Month
IF UpdateData.Day = 0 THEN UpdateData.Day = NameList(Student).Day
IF UpdateData.HouseColor = Blank8 THEN UpdateData.HouseColor = NameList(Student).HouseColor
IF UpdateData.MomName = Blank30 THEN UpdateData.MomName = NameList(Student).MomName
IF UpdateData.MomPhone = Blank20 THEN UpdateData.MomPhone = NameList(Student).MomPhone
IF UpdateData.MomEmail = Blank30 + Blank8 THEN UpdateData.MomEmail = NameList(Student).MomEmail
IF UpdateData.DadName = Blank30 THEN UpdateData.DadName = NameList(Student).DadName
IF UpdateData.DadPhone = Blank20 THEN UpdateData.DadPhone = NameList(Student).DadPhone
IF UpdateData.DadEmail = Blank30 + Blank8 THEN UpdateData.DadEmail = NameList(Student).DadEmail
CLS
PUTIMAGE (0, 0), DisplayStudentData
QUICKPRINTSTUDENTDATA UpdateData, Student
FONT Arial32
COLOR RGB32(147, 237, 255)
LOCATE 18, 75: PRINT "Saving this change to the list. "
LOCATE 19, 75: PRINT "Press Enter to confirm, any other key to abort. "
LOCATE 20, 75: PRINT " "
LOCATE 21, 75: PRINT " ";
COLOR RGB(255, 255, 255)
FONT Arial24
DISPLAY
PAUSE (TIME)
DO
LIMIT LIMITRATE
IF KEYDOWN(13) THEN
DIM AS INTEGER LoopCounter
ExitFlag = TRUE
UPDATESTUDENTLIST UpdateData, Student
OPEN "data/current/namelist.gkn" FOR OUTPUT AS #1
FOR LoopCounter = 1 TO NumberOfStudents
WRITESTUDENTLIST NameList(LoopCounter)
NEXT LoopCounter
CLOSE #1
QUICKMESSAGE "File updated succesfully!", 48, 2
ELSEIF KEYHIT THEN
ExitFlag = TRUE
QUICKMESSAGE "Modification discarded, please try agian if you need to make changes.", 32, 2
END IF
LOOP UNTIL ExitFlag
ELSEIF KEYDOWN(100) OR KEYDOWN(83) THEN 'delete student
FONT Arial32
COLOR RGB32(255, 79, 79)
LOCATE 18, 75: PRINT "Deleting student from list. Once done, cannot be reversed"
LOCATE 19, 75: PRINT " ARE YOU SURE? "
LOCATE 20, 75: PRINT " "
LOCATE 21, 75: PRINT "Press K to confirm, any other key to abort. ";
COLOR RGB(255, 255, 255)
FONT Arial24
DISPLAY
PAUSE (TIME)
DO
LIMIT LIMITRATE
IF KEYDOWN(107) OR KEYDOWN(75) THEN 'K hit, delete confirmed.
DIM AS INTEGER DeleteCounter
OPEN "data/current/namelist.gkn" FOR OUTPUT AS #1
IF Counter = NumberOfStudents THEN 'Deleting the last student
FOR DeleteCounter = 1 TO NumberOfStudents - 1
WRITESTUDENTLIST NameList(DeleteCounter)
NEXT DeleteCounter
ELSEIF Counter = 1 THEN 'Deleting the first student
FOR DeleteCounter = 2 TO NumberOfStudents
UPDATESTUDENTLIST NameList(DeleteCounter), DeleteCounter - 1
WRITESTUDENTLIST NameList(DeleteCounter - 1)
NEXT DeleteCounter
ELSE 'Deleting a student in the middle of the list
FOR DeleteCounter = Counter + 1 TO NumberOfStudents
UPDATESTUDENTLIST NameList(DeleteCounter), DeleteCounter - 1
NEXT DeleteCounter
FOR DeleteCounter = 1 TO NumberOfStudents - 1
WRITESTUDENTLIST NameList(DeleteCounter)
NEXT DeleteCounter
END IF
CLOSE #1
NumberOfStudents = NumberOfStudents - 1
ExitFlag = TRUE
QUICKMESSAGE "Deletion confirmed. File updated succesfully!", 48, 2
ELSEIF KEYHIT THEN
ExitFlag = TRUE
QUICKMESSAGE "Deletion cancelled. Try again if desired.", 48, 2
END IF
LOOP UNTIL ExitFlag
ELSEIF INKEY$ <> "" THEN ExitFlag = TRUE
END IF
LOOP UNTIL ExitFlag
SCREEN ScreenPointer(1)
END SUB
SUB STUDENTREPORTS
DIM AS BIT Back
DIM AS INTEGER ReportCounter
SCREEN ScreenPointer(2)
ReportCounter = 0
SelectFlag = FALSE: Back = FALSE
PAUSE (TIME)
DO
LIMIT LIMITRATE
DO
LIMIT LIMITRATE
CLS
PUTIMAGE (0, 0), Report
SELECT CASE ReportCounter
CASE 0: PUTIMAGE (285, 170), CheckSelect
CASE 1: PUTIMAGE (285, 240), CheckSelect
CASE 2: PUTIMAGE (285, 310), CheckSelect
CASE 3: PUTIMAGE (285, 380), CheckSelect
CASE 4: PUTIMAGE (285, 455), CheckSelect
CASE 5: PUTIMAGE (285, 525), CheckSelect
END SELECT
DISPLAY
IF SelectFlag THEN PAUSE (TIME) 'Avoid double press delay
SelectFlag = FALSE
'Checking for key press (keyboard)
IF KEYDOWN(18432) THEN ' up case
IF ReportCounter = 0 THEN ReportCounter = 5 ELSE ReportCounter = ReportCounter - 1
SelectFlag = TRUE
END IF
IF KEYDOWN(20480) THEN 'down case
IF ReportCounter = 5 THEN ReportCounter = 0 ELSE ReportCounter = ReportCounter + 1
SelectFlag = TRUE
END IF
LOOP UNTIL KEYDOWN(13) OR KEYDOWN(32) 'Return or Spacebar to select
SELECT CASE ReportCounter
CASE 0: REPORTWRITER "Birthday Report", 2
CASE 1: REPORTWRITER "Index Cards", 2
CASE 2: REPORTWRITER "House Color Groupings", 2
CASE 3: REPORTWRITER "Name List", 2
CASE 4: REPORTWRITER "Parent Contact Info", 2
CASE 5: Back = TRUE
END SELECT
PAUSE (TIME)
LOOP UNTIL Back
SCREEN ScreenPointer(1)
END SUB
SUB ARCHIVEDCLASS 'Prior year record keeping - Future release
END SUB
'===========Support Subs/Functions===========
'Quick about the program and the release to public domain
SUB ABOUT
DIM AS LONG Script
CLS
PUTIMAGE (0, 0), Generic
Script = LOADFONT("data\assets\script.ttf", 60)
FONT Script: LOCATE 2, 1280 / 2 - PRINTWIDTH("Grade Keeper") / 2: PRINT "Grade Keeper"
FONT Arial32: LOCATE 8, 1280 / 2 - PRINTWIDTH("Alpha Version 0.4") / 2: PRINT "Alpha Version 0.4"
FONT Arial24: LOCATE 15, 50: PRINT "Public alpha release #2. Built November 27th, 2022. Released as non-commercial and share alike as defined"
LOCATE 16, 50: PRINT "by the creative commons 4.0. May not apply any additional legal terms nor technological measures that"
LOCATE 17, 50: PRINT "legally restrict others from doing anything that the license permits. Please contact NasaCow at"
LOCATE 18, 50: PRINT "NasaCowPro@gmail.com with any questions or feedback. No warranty or guarantee explicitly or implicitly"
LOCATE 19, 50: PRINT "made with the use of this software."
LOCATE 28, 50: PRINT "Press any key to go back..."
FREEFONT Script
DISPLAY
SLEEP
END SUB
'Writes reports with PRINTIMAGE (one page limit currently)
SUB REPORTWRITER (ReportName AS STRING, SourceScreen AS INTEGER)
DIM AS INTEGER PageH, PageW, PageS 'Height, Width, Scale (higher is clearer)
DIM AS INTEGER FSize, FHeight 'Size is used to set the height
DIM AS INTEGER X, Y, YReturn, MaxY 'Location on page
DIM AS INTEGER PrintCounter, StartPointer 'DO/LOOP index: Where to start in the namelist
DIM AS INTEGER LongName 'Longest name on the student list (first name + last name)
DIM AS LONG Page, Script, Cursive 'Paper, Report font, cursive font for logo
DIM AS STRING School, Teach, Location, DateAndTime 'Preparing teacher info for printer
DIM AS STRING * 1 Confirm
DIM AS BYTE WantGrid, WantMother 'Used to estblish a grid or just names.
SCREEN ScreenPointer(4)
FONT Arial32
'Collect info for the "Name List" report before the please wait screen is displayed...
IF ReportName = "Name List" THEN
CLS: PUTIMAGE (0, 0), Generic
X = (HEIGHT / FONTHEIGHT) / 2 - 1
Y = 1280 / 2 - PRINTWIDTH("Do you wish to have a grid boxing with the name list (Y/N)? ") / 2
AUTODISPLAY
DO
LOCATE X, Y: INPUT "Do you wish to have a grid boxing with the name list (Y/N)? ", Confirm
LOOP UNTIL UCASE$(Confirm) = "Y" OR UCASE$(Confirm) = "N"
DISPLAY
IF UCASE$(Confirm) = "Y" THEN WantGrid = TRUE ELSE WantGrid = FALSE
PAUSE (TIME)
END IF
'Collect info for the "Name List" report before the please wait screen is displayed...
IF ReportName = "Parent Contact Info" THEN
CLS: PUTIMAGE (0, 0), Generic
X = (HEIGHT / FONTHEIGHT) / 2 - 1
Y = 1280 / 2 - PRINTWIDTH("Do you wish to have the mother's or father's info (M/F)? ") / 2
AUTODISPLAY
DO
LOCATE X, Y: INPUT "Do you wish to have the mother's or father's info (M/F)? ", Confirm
LOOP UNTIL UCASE$(Confirm) = "M" OR UCASE$(Confirm) = "F"
DISPLAY
IF UCASE$(Confirm) = "M" THEN WantMother = TRUE ELSE WantMother = FALSE
PAUSE (TIME)
END IF
'Make a wait screen, printer prep takes more than a few seconds...
CLS: PUTIMAGE (0, 0), Generic
X = (HEIGHT / FONTHEIGHT) / 2 - 1
Y = 1280 / 2 - PRINTWIDTH("Report is being generated,") / 2
LOCATE X - 1, Y: PRINT "Report is being generated."
Y = 1280 / 2 - PRINTWIDTH("Standby for printer selection...") / 2
LOCATE X, Y: PRINT "Standby for printer selection..."
Y = 1280 / 2 - PRINTWIDTH("Please press nothing while waiting") / 2
LOCATE X + 2, Y: PRINT "Please press nothing while waiting"
DISPLAY
'Inital settings for printing
PageS = 100: PageH = 297 * PageS: PageW = 210 * PageS: FSize = 16
School = TRIM$(Teacher.School)
Teach = "Teacher of Record: " + TRIM$(Teacher.TeacherName)
Location = "Grade: " + TRIM$(Teacher.Grade) + " / Class: " + TRIM$(Teacher.Class) + " / Room: " + TRIM$(Teacher.Classroom)
DateAndTime = DAYOFWEEK(VAL(RIGHT$(DATE$, 2)), VAL(LEFT$(DATE$, 2)), VAL(MID$(DATE$, 4, 2))) + ", " + TODAY$ + " at " + CLOCK$
'Building the page and fonts needed
FHeight = INT(FSize * 0.3527 * PageS) 'Formula for a font size
Script = LOADFONT("Data\Assets\arial.ttf", FHeight) 'Load the print font at the proper size
Cursive = LOADFONT("Data\Assets\script.ttf", FHeight) 'Load the cursive font at the proper size
Page = NEWIMAGE(PageW, PageH, 32) 'Create the page
DEST Page: CLS , RGB(255, 255, 255) 'Page set for writing with a white background
FONT Script 'Makes printing text active, done after setting DEST
COLOR RGB(0, 0, 0), RGBA(0, 0, 0, 0) 'Black text with a clear background
'Print the common header of the reports
X = PageW / 2 - PRINTWIDTH(ReportName) / 2: Y = FHeight * 3
PRINTSTRING (X, Y), ReportName
X = PageW / 2 - PRINTWIDTH(Teach) / 2: Y = Y + FHeight * 2
PRINTSTRING (X, Y), Teach
X = PageW / 2 - PRINTWIDTH(School) / 2: Y = Y + FHeight
PRINTSTRING (X, Y), School
X = PageW / 2 - PRINTWIDTH(Location) / 2: Y = Y + FHeight
PRINTSTRING (X, Y), Location
X = PageW / 2 - PRINTWIDTH(DateAndTime) / 2: Y = Y + FHeight
PRINTSTRING (X, Y), DateAndTime
YReturn = Y + FHeight * 2
'Prints the selected report
SELECT CASE ReportName
CASE "Birthday Report":
DIM AS INTEGER CurrentYear
DIM AS BYTE NoLoop 'For no birthdays in the last 4 months of the year (Start printing in Jan.)
SORT 2 'Sort by Birthday
PrintCounter = 0: StartPointer = 0: NoLoop = FALSE
X = 20 * PageS: Y = Y + FHeight * 2
PRINTSTRING (X, Y), "Name"
X = 70 * PageS
PRINTSTRING (X, Y), "Birthday"
X = 180 * PageS
PRINTSTRING (X, Y), "Age"
X = 20 * PageS: Y = Y + FHeight
LINE (X, Y)-(190 * PageS, Y + .5 * PageS), , BF
Y = Y + FHeight * .5
IF VAL(LEFT$(DATE$, 2)) >= 9 THEN CurrentYear = VAL(RIGHT$(DATE$, 4)) ELSE CurrentYear = VAL(RIGHT$(DATE$, 4)) - 1 'Age needs the correct current year for the school year
DO 'Loop searches for the first entry that starts in September or later
PrintCounter = PrintCounter + 1
StartPointer = NameList(PrintCounter).Month
LOOP UNTIL StartPointer >= 9 OR PrintCounter = NumberOfStudents
IF StartPointer < 9 THEN
StartPointer = 1 'On the off-chance of no birthdays in the last 4 months of the year
CurrentYear = CurrentYear + 1 'And advance to next year
NoLoop = TRUE 'Print all at once
END IF
StartPointer = PrintCounter - 1 'Maintain our place in the list
FOR PrintCounter = PrintCounter TO NumberOfStudents 'Print from September to tbe end of the year
PRINTSTRING (X, Y), TRIM$(NameList(PrintCounter).FirstName) + " " + TRIM$(NameList(PrintCounter).LastName)
X = 70 * PageS
PRINTSTRING (X, Y), BIRTHDAY$(NameList(PrintCounter).Month, NameList(PrintCounter).Day, CurrentYear)
X = 180 * PageS
PRINTSTRING (X, Y), STR$(CurrentYear - NameList(PrintCounter).Year)
X = 20 * PageS: Y = Y + FHeight * 1.15
NEXT PrintCounter
IF NOT NoLoop THEN 'Print the list from January to August if not already fully printed
CurrentYear = CurrentYear + 1
FOR PrintCounter = 1 TO StartPointer
PRINTSTRING (X, Y), TRIM$(NameList(PrintCounter).FirstName) + " " + TRIM$(NameList(PrintCounter).LastName)
X = 70 * PageS
PRINTSTRING (X, Y), BIRTHDAY$(NameList(PrintCounter).Month, NameList(PrintCounter).Day, CurrentYear)
X = 180 * PageS
PRINTSTRING (X, Y), STR$(CurrentYear - NameList(PrintCounter).Year)
X = 20 * PageS: Y = Y + FHeight * 1.15
NEXT PrintCounter
END IF
SORT 1 'Restore display sort
CASE "Index Cards": 'Planned report not possible with one page limit
FONT Arial24
FREEFONT Script
FREEFONT Cursive
SCREEN ScreenPointer(SourceScreen): DEST ScreenPointer(SourceScreen) 'Restore our prior screen
QUICKMESSAGE "This report is under development. Aborting...", 32, SourceScreen
EXIT SUB
CASE "House Color Groupings":
DIM AS INTEGER R, Ye, G, B, O, MissingColor, XLine
R = 0: Ye = 0: G = 0: B = 0: O = 0: MissingColor = 0
SORT 3 'Color sort (Should make it faster?)
'Count the number of students in each house
FOR PrintCounter = 1 TO NumberOfStudents
SELECT CASE UCASE$(TRIM$(NameList(PrintCounter).HouseColor))
CASE "RED": R = R + 1
CASE "YELLOW": Ye = Ye + 1
CASE "GREEN": G = G + 1
CASE "BLUE": B = B + 1
CASE "ORANGE": O = O + 1
CASE ELSE: MissingColor = MissingColor + 1 'For mistype and unplaced students
END SELECT
NEXT PrintCounter
'Blue house
YReturn = Y: X = 20 * PageS: Y = Y + FHeight * 2: PrintCounter = 0: StartPointer = 0
XLine = PRINTWIDTH("Blue House:") + X
PRINTSTRING (X, Y), "Blue House:"
Y = Y + FHeight
LINE (X, Y)-(XLine, Y + .5 * PageS), , BF
IF NOT B THEN
DO
StartPointer = StartPointer + 1
IF UCASE$(TRIM$(NameList(StartPointer).HouseColor)) = "BLUE" THEN
X = 25 * PageS: Y = Y + FHeight
PRINTSTRING (X, Y), TRIM$(NameList(StartPointer).FirstName) + " " + TRIM$(NameList(StartPointer).LastName)
PrintCounter = PrintCounter + 1
END IF
LOOP UNTIL PrintCounter = B
END IF
MaxY = Y 'To know how far down we have reached for the next major row
'Green house
Y = YReturn: X = 80 * PageS: Y = Y + FHeight * 2: PrintCounter = 0: StartPointer = 0
XLine = PRINTWIDTH("Green House:") + X
PRINTSTRING (X, Y), "Green House:"
Y = Y + FHeight
LINE (X, Y)-(XLine, Y + .5 * PageS), , BF
IF NOT G THEN
DO
StartPointer = StartPointer + 1
IF UCASE$(TRIM$(NameList(StartPointer).HouseColor)) = "GREEN" THEN
X = 95 * PageS: Y = Y + FHeight
PRINTSTRING (X, Y), TRIM$(NameList(StartPointer).FirstName) + " " + TRIM$(NameList(StartPointer).LastName)
PrintCounter = PrintCounter + 1
END IF
LOOP UNTIL PrintCounter = G
END IF
IF Y > MaxY THEN MaxY = Y 'Are we further down the page?
'Orange house
Y = YReturn: X = 140 * PageS: Y = Y + FHeight * 2: PrintCounter = 0: StartPointer = 0
XLine = PRINTWIDTH("Orange House:") + X
PRINTSTRING (X, Y), "Orange House:"
Y = Y + FHeight
LINE (X, Y)-(XLine, Y + .5 * PageS), , BF
IF NOT O THEN
DO
StartPointer = StartPointer + 1
IF UCASE$(TRIM$(NameList(StartPointer).HouseColor)) = "ORANGE" THEN
X = 145 * PageS: Y = Y + FHeight
PRINTSTRING (X, Y), TRIM$(NameList(StartPointer).FirstName) + " " + TRIM$(NameList(StartPointer).LastName)
PrintCounter = PrintCounter + 1
END IF
LOOP UNTIL PrintCounter = O
END IF
IF Y > MaxY THEN MaxY = Y 'Are we further down the page?
'Red house and next major row
Y = MaxY: X = 20 * PageS: Y = Y + FHeight * 2: PrintCounter = 0: StartPointer = 0
XLine = PRINTWIDTH("Red House:") + X
PRINTSTRING (X, Y), "Red House:"
Y = Y + FHeight
LINE (X, Y)-(XLine, Y + .5 * PageS), , BF
IF NOT R THEN
DO
StartPointer = StartPointer + 1
IF UCASE$(TRIM$(NameList(StartPointer).HouseColor)) = "RED" THEN
X = 25 * PageS: Y = Y + FHeight
PRINTSTRING (X, Y), TRIM$(NameList(StartPointer).FirstName) + " " + TRIM$(NameList(StartPointer).LastName)
PrintCounter = PrintCounter + 1
END IF
LOOP UNTIL PrintCounter = R
END IF
'Yellow house
Y = MaxY: X = 80 * PageS: Y = Y + FHeight * 2: PrintCounter = 0: StartPointer = 0
XLine = PRINTWIDTH("Yellow House:") + X
PRINTSTRING (X, Y), "Yellow House:"
Y = Y + FHeight
LINE (X, Y)-(XLine, Y + .5 * PageS), , BF
IF NOT Ye THEN
DO
StartPointer = StartPointer + 1
IF UCASE$(TRIM$(NameList(StartPointer).HouseColor)) = "YELLOW" THEN
X = 85 * PageS: Y = Y + FHeight
PRINTSTRING (X, Y), TRIM$(NameList(StartPointer).FirstName) + " " + TRIM$(NameList(StartPointer).LastName)
PrintCounter = PrintCounter + 1
END IF
LOOP UNTIL PrintCounter = Ye
END IF
'Unkown house
Y = MaxY: X = 140 * PageS: Y = Y + FHeight * 2: PrintCounter = 0: StartPointer = 0
XLine = PRINTWIDTH("House Unknown:") + X
PRINTSTRING (X, Y), "House Unknown:"
Y = Y + FHeight
LINE (X, Y)-(XLine, Y + .5 * PageS), , BF
IF NOT MissingColor THEN
DO
StartPointer = StartPointer + 1
IF UCASE$(TRIM$(NameList(StartPointer).HouseColor)) <> "ORANGE" OR UCASE$(TRIM$(NameList(StartPointer).HouseColor)) <> "BLUE" _
OR UCASE$(TRIM$(NameList(StartPointer).HouseColor)) <> "GREEN" OR UCASE$(TRIM$(NameList(StartPointer).HouseColor)) <> "YELLOW" _
OR UCASE$(TRIM$(NameList(StartPointer).HouseColor)) <> "RED" THEN
X = 145 * PageS: Y = Y + FHeight
IF TRIM$(NameList(StartPointer).HouseColor) = "" THEN NameList(StartPointer).HouseColor = "Unknown" 'Prints the current entry in case of data entry error
PRINTSTRING (X, Y), TRIM$(NameList(StartPointer).FirstName) + " " + TRIM$(NameList(StartPointer).LastName) + "-"
X = 150 * PageS: Y = Y + FHeight
PRINTSTRING (X, Y), NameList(StartPointer).HouseColor
PrintCounter = PrintCounter + 1
Y = Y + FHeight
END IF
LOOP UNTIL PrintCounter = MissingColor
END IF
SORT 1 'Restore display sort
CASE "Name List":
'Print the names to the sheet
X = 20 * PageS: Y = Y + FHeight * 2: LongName = 0
FOR PrintCounter = 1 TO NumberOfStudents
PRINTSTRING (X, Y), TRIM$(NameList(PrintCounter).FirstName) + " " + TRIM$(NameList(PrintCounter).LastName)
Y = Y + FHeight * 1.5
IF LongName < PRINTWIDTH(TRIM$(NameList(PrintCounter).FirstName) + " " + TRIM$(NameList(PrintCounter).LastName)) THEN 'Finds the longest name
LongName = PRINTWIDTH(TRIM$(NameList(PrintCounter).FirstName) + " " + TRIM$(NameList(PrintCounter).LastName))
END IF
NEXT PrintCounter
'Prints a grid if desired
IF WantGrid THEN
X = LongName + 21 * PageS: Y = YReturn - .25 * FHeight 'intial corner of box drawing
DO WHILE X < 180 * PageS 'Draw boxes horiztionally to the margin.
FOR PrintCounter = 1 TO NumberOfStudents 'Draw boxes vertically
LINE (X, Y)-(X + 15 * PageS, Y + .025 * FHeight), , BF
LINE -(X + 14.95 * PageS, Y + 1.25 * FHeight), , BF
LINE -(X, Y + 1.225 * FHeight), , BF
LINE -(X + .05 * PageS, Y), , BF
Y = Y + FHeight * 1.5
NEXT PrintCounter
X = X + 15 * PageS: Y = YReturn - .25 * FHeight
LOOP
END IF
CASE "Parent Contact Info":
DIM AS STRING MotherFather 'Are we printing the Mother or Father
DIM AS INTEGER XSpacing, MomDadLongName, MomDadLongPhone, MomDadLongEmail 'Used for spacing the report
'Printing mom's or dad's info to keep it to one page.
IF WantMother THEN MotherFather = "Mother's " ELSE MotherFather = "Father's "
'Finds the longest name, and parent info on our name list and print them to the report
YReturn = Y: X = 10 * PageS: Y = Y + FHeight * 3: XSpacing = PageS
FOR PrintCounter = 1 TO NumberOfStudents
PRINTSTRING (X, Y), TRIM$(NameList(PrintCounter).FirstName) + " " + TRIM$(NameList(PrintCounter).LastName)
Y = Y + FHeight * 1.15
IF LongName < PRINTWIDTH(TRIM$(NameList(PrintCounter).FirstName) + " " + TRIM$(NameList(PrintCounter).LastName)) THEN 'Finds the longest name
LongName = PRINTWIDTH(TRIM$(NameList(PrintCounter).FirstName) + " " + TRIM$(NameList(PrintCounter).LastName))
END IF
IF MotherFather = "Mother's " THEN
IF MomDadLongName < PRINTWIDTH(TRIM$(NameList(PrintCounter).MomName)) THEN MomDadLongName = PRINTWIDTH(TRIM$(NameList(PrintCounter).MomName))
IF MomDadLongEmail < PRINTWIDTH(TRIM$(NameList(PrintCounter).MomEmail)) THEN MomDadLongEmail = PRINTWIDTH(TRIM$(NameList(PrintCounter).MomEmail))
IF MomDadLongPhone < PRINTWIDTH(TRIM$(NameList(PrintCounter).MomPhone)) THEN MomDadLongPhone = PRINTWIDTH(TRIM$(NameList(PrintCounter).MomPhone))
ELSE
IF MomDadLongName < PRINTWIDTH(TRIM$(NameList(PrintCounter).DadName)) THEN MomDadLongName = PRINTWIDTH(TRIM$(NameList(PrintCounter).DadName))
IF MomDadLongEmail < PRINTWIDTH(TRIM$(NameList(PrintCounter).DadEmail)) THEN MomDadLongEmail = PRINTWIDTH(TRIM$(NameList(PrintCounter).DadEmail))
IF MomDadLongPhone < PRINTWIDTH(TRIM$(NameList(PrintCounter).DadPhone)) THEN MomDadLongPhone = PRINTWIDTH(TRIM$(NameList(PrintCounter).DadPhone))
END IF
NEXT PrintCounter
'Ensure our spacing is at least as long as our header
IF MomDadLongName < PRINTWIDTH(MotherFather + "name:") THEN MomDadLongName = PRINTWIDTH(MotherFather + "name:")
IF MomDadLongPhone < PRINTWIDTH(MotherFather + "phone:") THEN MomDadLongPhone = PRINTWIDTH(MotherFather + "phone:")
IF MomDadLongPhone < PRINTWIDTH(MotherFather + "email:") THEN MomDadLongPhone = PRINTWIDTH(MotherFather + "email:")
'Print the rest of the selected info
MaxY = Y: Y = YReturn + FHeight * 3
FOR PrintCounter = 1 TO NumberOfStudents
IF MotherFather = "Mother's " THEN
PRINTSTRING (X + LongName + XSpacing, Y), NameList(PrintCounter).MomName
PRINTSTRING (X + LongName + XSpacing + MomDadLongName + XSpacing, Y), NameList(PrintCounter).MomPhone
PRINTSTRING (X + LongName + XSpacing + MomDadLongName + XSpacing + MomDadLongPhone + XSpacing, Y), NameList(PrintCounter).MomEmail
ELSE
PRINTSTRING (X + LongName + XSpacing, Y), NameList(PrintCounter).DadName
PRINTSTRING (X + LongName + XSpacing + MomDadLongName + XSpacing, Y), NameList(PrintCounter).DadPhone
PRINTSTRING (X + LongName + XSpacing + MomDadLongName + XSpacing + MomDadLongPhone + XSpacing, Y), NameList(PrintCounter).DadEmail
END IF
LINE (X, Y + FHeight)-(X + XSpacing * 3 + LongName + MomDadLongName + MomDadLongPhone + MomDadLongEmail - .15 * PageS, Y + 1.05 * FHeight), , BF 'Line spliting rows
Y = Y + FHeight * 1.15
NEXT PrintCounter
'Print the sub-header (mom or dad) with grid lines
X = 10 * PageS: Y = YReturn + FHeight * 2
LINE (X, Y + FHeight)-(X - .15 * PageS, MaxY - .15 * FHeight), , BF 'Top-left to bottom-left
LINE -(X + XSpacing * 3 + LongName + MomDadLongName + MomDadLongPhone + MomDadLongEmail, MaxY - .1 * FHeight), , BF 'to bottom-right
LINE -(X + XSpacing * 3 + LongName + MomDadLongName + MomDadLongPhone + MomDadLongEmail - .15 * PageS, Y - .15 + FHeight), , BF 'to top-tight
LINE -(X, Y + FHeight * 1.05), , BF 'to top-left
LINE (X + LongName + XSpacing * 1 / 3, Y + FHeight)-(X + LongName + XSpacing * 2 / 3, MaxY - .15 * FHeight), , BF 'Top to bottom between name and parent's name
LINE (X + LongName + MomDadLongName + XSpacing * 2 / 3, Y + FHeight)-_
(X + LongName + MomDadLongName + XSpacing, MaxY - .15 * FHeight), , BF 'Top to bottom between parent's name and parent's phone
LINE (X + LongName + MomDadLongName + MomDadLongPhone + XSpacing, Y + FHeight)-_
(X + LongName + MomDadLongName + MomDadLongPhone + XSpacing * 4 / 3, MaxY - .15 * FHeight), , BF 'Top to bottom between parent's phone and parent's email
X = X + XSpacing + LongName
PRINTSTRING (X, Y), MotherFather + "name:"
X = X + XSpacing + MomDadLongName
PRINTSTRING (X, Y), MotherFather + "phone:"
X = X + XSpacing + MomDadLongPhone
PRINTSTRING (X, Y), MotherFather + "email:"
END SELECT
'Report footer
Y = 280 * PageS
PRINTSTRING (20 * PageS, Y), "Prepared with "
PRINTSTRING (190 * PageS - PRINTWIDTH("Page 1 of 1"), Y), "Page 1 of 1"
X = (20 * PageS) + PRINTWIDTH("Prepared with ")
FONT Cursive
PRINTSTRING (X, Y), "Grade Keeper"
'Send the report to the printer, cleans up our fonts, and inform the user of success.
PRINTIMAGE Page
FONT Arial24
FREEFONT Script
FREEFONT Cursive
SCREEN ScreenPointer(SourceScreen): DEST ScreenPointer(SourceScreen) 'Restore our prior screen
QUICKMESSAGE "Report generated!", 32, SourceScreen
END SUB
'Collects info on the teacher to make reports look more professional.
SUB TEACHERINFO
DIM AS STRING * 1 OverWrite
OverWrite = "N"
SCREEN ScreenPointer(3)
CLS
PUTIMAGE , Generic
'prompt for overwrite
IF FILEEXISTS("data/current/teacher.gkn") THEN
QUICKMESSAGE "Info is on file. You may go back on the next screen.", 32, 3
FONT Arial60
LOCATE 4, 1280 / 2 - PRINTWIDTH("OVERWRITE!") / 2: PRINT "OVERWRITE!"
FONT Arial48
AUTODISPLAY
DO
LOCATE 8, 1280 / 2 - PRINTWIDTH("Do you wish to overwrite current teacher info (Y/N)?") / 2
INPUT "Do you wish to overwrite current teacher info (Y/N)?", OverWrite
OverWrite = UCASE$(OverWrite)
LOOP UNTIL OverWrite = "Y" OR OverWrite = "N"
DISPLAY
END IF
'No file? Make one here
IF NOT FILEEXISTS("data/current/teacher.gkn") OR OverWrite = "Y" THEN
DIM AS LONG Script
Script = LOADFONT("data/assets/script.ttf", 39)
CLS
PUTIMAGE , BlankData
FONT Script
AUTODISPLAY
LOCATE 2, 1280 / 2 - PRINTWIDTH("Teacher Info") / 2: PRINT "Teacher Info"
PAUSE (TIME)
LOCATE 5, 50: INPUT "Please enter your name (Mr./Ms. Smith): ", Teacher.TeacherName
PAUSE (TIME)
LOCATE 6, 50: INPUT "Please enter the name of your school: ", Teacher.School
PAUSE (TIME)
LOCATE 7, 50: INPUT "Please enter your grade/subject: ", Teacher.Grade
PAUSE (TIME)
LOCATE 8, 50: INPUT "please enter your class/section: ", Teacher.Class
PAUSE (TIME)
LOCATE 9, 50: INPUT "Pleae enter your classroom number: ", Teacher.Classroom
DISPLAY
OPEN "data/current/teacher.gkn" FOR OUTPUT AS #2
WRITE #2, Teacher.TeacherName
WRITE #2, Teacher.School
WRITE #2, Teacher.Grade
WRITE #2, Teacher.Class
WRITE #2, Teacher.Classroom
CLOSE #2
QUICKMESSAGE "Teacher info written succesfully!", 32, 3
FONT Arial24
FREEFONT Script
END IF
SCREEN ScreenPointer(2)
END SUB
'Used for initial database building of student data
SUB CREATESTUDENTLIST
DIM AS STRING * 1 AddAnother, Correct
DIM AS NameListType NewData
PAUSE (TIME)
FONT Arial24
OPEN "data/current/namelist.gkn" FOR OUTPUT AS #1 'For writing the master name list data
Counter = 1
AUTODISPLAY
'Gathering data about students
DO
CLS
PUTIMAGE (0, 0), NewNameEntry
LOCATE 7, 140: PRINT Counter 'Built with Arial24
LOCATE 7, 280: INPUT "", NewData.PinYinName
DO
LOCATE 7, 710: PRINT " "
LOCATE 7, 710: INPUT "", NewData.Month
LOOP UNTIL NewData.Month > 0 AND NewData.Month < 13
DO
LOCATE 7, 780: PRINT " "
LOCATE 7, 780: INPUT "", NewData.Day
LOOP UNTIL NewData.Day > 0 AND NewData.Day < 32
DO
LOCATE 7, 840: PRINT " "
LOCATE 7, 840: INPUT "", NewData.Year
LOOP UNTIL NewData.Year > 2000 AND NewData.Year < 2100
LOCATE 7, 970: INPUT "", NewData.HouseColor
LOCATE 12, 55: INPUT "", NewData.FirstName
LOCATE 12, 400: INPUT "", NewData.MiddleName
LOCATE 12, 780: INPUT "", NewData.LastName
LOCATE 17, 55: INPUT "", NewData.MomName
LOCATE 17, 400: INPUT "", NewData.MomPhone
LOCATE 17, 780: INPUT "", NewData.MomEmail
LOCATE 22, 55: INPUT "", NewData.DadName
LOCATE 22, 400: INPUT "", NewData.DadPhone
LOCATE 22, 780: INPUT "", NewData.DadEmail
DO
LOCATE 27, 430: PRINT " "
LOCATE 27, 430: INPUT "", Correct
Correct = UCASE$(Correct)
LOOP UNTIL Correct = "Y" OR Correct = "N"
DO
LOCATE 27, 690: PRINT " "
LOCATE 27, 690: INPUT "", AddAnother
AddAnother = UCASE$(AddAnother)
LOOP UNTIL AddAnother = "Y" OR AddAnother = "N"
'Check if the entry is correct. If it is write it, otherwise repeat with same entry number
IF Correct = "Y" THEN
WRITESTUDENTLIST NewData
Counter = Counter + 1
ELSE
QUICKMESSAGE "Data not written. Please re-enter data.", 32, 1
AUTODISPLAY
FONT Arial24
AddAnother = "Y"
END IF
LOOP UNTIL AddAnother = "N"
DISPLAY
CLOSE #1
QUICKMESSAGE "Data written successfully!", 32, 1
END SUB
SUB ADDSTUDENT
DIM AS NameListType NewData
DIM AS STRING * 1 Correct
SCREEN ScreenPointer(2)
CLS
PUTIMAGE (0, 0), NewNameEntry
FONT Arial24
'Used to blank the option to add another
LOCATE 24, 550: PRINT " "
LOCATE 25, 550: PRINT " "
LOCATE 25, 550: PRINT " "
LOCATE 26, 550: PRINT " ";
'Gather data about our new student
LOCATE 7, 140: PRINT Counter 'Built with Arial24
LOCATE 7, 280: INPUT "", NewData.PinYinName
DO
LOCATE 7, 710: PRINT " "
LOCATE 7, 710: INPUT "", NewData.Month
LOOP UNTIL NewData.Month > 0 AND NewData.Month < 13
DO
LOCATE 7, 780: PRINT " "
LOCATE 7, 780: INPUT "", NewData.Day
LOOP UNTIL NewData.Day > 0 AND NewData.Day < 32
DO
LOCATE 7, 840: PRINT " "
LOCATE 7, 840: INPUT "", NewData.Year
LOOP UNTIL NewData.Year > 2000 AND NewData.Year < 2100
LOCATE 7, 970: INPUT "", NewData.HouseColor
LOCATE 12, 55: INPUT "", NewData.FirstName
LOCATE 12, 400: INPUT "", NewData.MiddleName
LOCATE 12, 780: INPUT "", NewData.LastName
LOCATE 17, 55: INPUT "", NewData.MomName
LOCATE 17, 400: INPUT "", NewData.MomPhone
LOCATE 17, 780: INPUT "", NewData.MomEmail
LOCATE 22, 55: INPUT "", NewData.DadName
LOCATE 22, 400: INPUT "", NewData.DadPhone
LOCATE 22, 780: INPUT "", NewData.DadEmail
DO
LOCATE 27, 430: PRINT " "
LOCATE 27, 430: INPUT "", Correct
Correct = UCASE$(Correct)
LOOP UNTIL Correct = "Y" OR Correct = "N"
'Checks correctness and writes or aborts writing and returns to the prior screen
IF Correct = "Y" THEN
NumberOfStudents = NumberOfStudents + 1
UPDATESTUDENTLIST NewData, NumberOfStudents
OPEN "data/current/namelist.gkn" FOR OUTPUT AS #1
FOR Counter = 1 TO NumberOfStudents
WRITESTUDENTLIST NameList(Counter)
NEXT Counter
CLOSE #1
QUICKMESSAGE "Student added successfully!", 32, 2
ELSE
QUICKMESSAGE "Student not added. Please try again.", 32, 2
FONT Arial24
END IF
DISPLAY
SCREEN ScreenPointer(1)
END SUB
'Replace student info from a source NameListType
SUB UPDATESTUDENTLIST (DataSource AS NameListType, Student AS INTEGER)
NameList(Student).PinYinName = DataSource.PinYinName
NameList(Student).FirstName = DataSource.FirstName
NameList(Student).MiddleName = DataSource.MiddleName
NameList(Student).LastName = DataSource.LastName
NameList(Student).Year = DataSource.Year
NameList(Student).Month = DataSource.Month
NameList(Student).Day = DataSource.Day
NameList(Student).HouseColor = DataSource.HouseColor
NameList(Student).MomName = DataSource.MomName
NameList(Student).MomPhone = DataSource.MomPhone
NameList(Student).MomEmail = DataSource.MomEmail
NameList(Student).DadName = DataSource.DadName
NameList(Student).DadPhone = DataSource.DadPhone
NameList(Student).DadEmail = DataSource.DadEmail
END SUB
'Writes a NameListType to file (#1 is reservered)
SUB WRITESTUDENTLIST (DataSource AS NameListType)
WRITE #1, DataSource.PinYinName
WRITE #1, DataSource.Month
WRITE #1, DataSource.Day
WRITE #1, DataSource.Year
WRITE #1, DataSource.HouseColor
WRITE #1, DataSource.FirstName
WRITE #1, DataSource.MiddleName
WRITE #1, DataSource.LastName
WRITE #1, DataSource.MomName
WRITE #1, DataSource.MomPhone
WRITE #1, DataSource.MomEmail
WRITE #1, DataSource.DadName
WRITE #1, DataSource.DadPhone
WRITE #1, DataSource.DadEmail
END SUB
'Displays student data to the screen. Requires Arial24 font to print correctly.
SUB QUICKPRINTSTUDENTDATA (PrintStudent AS NameListType, StudentNum AS INTEGER)
LOCATE 7, 140: PRINT StudentNum
LOCATE 7, 280: PRINT PrintStudent.PinYinName
LOCATE 7, 710: PRINT PrintStudent.Month
LOCATE 7, 780: PRINT PrintStudent.Day
LOCATE 7, 840: PRINT PrintStudent.Year
LOCATE 7, 970: PRINT PrintStudent.HouseColor
LOCATE 12, 55: PRINT PrintStudent.FirstName
LOCATE 12, 400: PRINT PrintStudent.MiddleName
LOCATE 12, 780: PRINT PrintStudent.LastName
LOCATE 17, 55: PRINT PrintStudent.MomName
LOCATE 17, 400: PRINT PrintStudent.MomPhone
LOCATE 17, 780: PRINT PrintStudent.MomEmail
LOCATE 22, 55: PRINT PrintStudent.DadName
LOCATE 22, 400: PRINT PrintStudent.DadPhone
LOCATE 22, 780: PRINT PrintStudent.DadEmail
END SUB
'Loads the student data into memory. Ensure file exists before calling (#1 is reserved)
SUB LOADSTUDENTDATA
NumberOfStudents = 0
OPEN "data/current/namelist.gkn" FOR INPUT AS #1
WHILE NOT EOF(1)
NumberOfStudents = NumberOfStudents + 1
IF UBOUND(namelist) = NumberOfStudents THEN REDIM PRESERVE NameList(NumberOfStudents + 1) AS NameListType
INPUT #1, NameList(NumberOfStudents).PinYinName
INPUT #1, NameList(NumberOfStudents).Month
INPUT #1, NameList(NumberOfStudents).Day
INPUT #1, NameList(NumberOfStudents).Year
INPUT #1, NameList(NumberOfStudents).HouseColor
INPUT #1, NameList(NumberOfStudents).FirstName
INPUT #1, NameList(NumberOfStudents).MiddleName
INPUT #1, NameList(NumberOfStudents).LastName
INPUT #1, NameList(NumberOfStudents).MomName
INPUT #1, NameList(NumberOfStudents).MomPhone
INPUT #1, NameList(NumberOfStudents).MomEmail
INPUT #1, NameList(NumberOfStudents).DadName
INPUT #1, NameList(NumberOfStudents).DadPhone
INPUT #1, NameList(NumberOfStudents).DadEmail
WEND
CLOSE #1
END SUB
'Prints a short pop-up message to the user
SUB QUICKMESSAGE (ToPrint AS STRING, FontHandle AS INTEGER, CurrentScreen AS INTEGER)
DIM AS INTEGER Rows, Columns
'Save prior screen (ScreenPointer(5) is reserved for the sub)
SCREEN ScreenPointer(5)
'Font size selection
SELECT CASE FontHandle
CASE 8: FONT Arial8
CASE 12: FONT Arial12
CASE 16: FONT Arial16
CASE 24: FONT Arial24
CASE 32: FONT Arial32
CASE 48: FONT Arial48
CASE 60: FONT Arial60
CASE ELSE: BEEP 'Debug use only
EXIT SUB
END SELECT
'Write the message
CLS
PUTIMAGE (0, 0), Generic
Rows = (HEIGHT / FONTHEIGHT) / 2 - 1
Columns = 1280 / 2 - PRINTWIDTH(ToPrint) / 2
LOCATE Rows, Columns: PRINT ToPrint
Columns = 1280 / 2 - PRINTWIDTH("Press any key.") / 2
LOCATE Rows + 2, Columns: PRINT "Press any key."
DISPLAY
SLEEP
PAUSE (TIME)
SCREEN ScreenPointer(CurrentScreen) 'Restore prior screen before call
END SUB
'Formats birthdays and calls to add the day of the week
FUNCTION BIRTHDAY$ (MonthInt AS INTEGER, DayInt AS INTEGER, YearInt AS INTEGER)
DIM AS STRING Month, Day, Year
Year = STR$(YearInt)
SELECT CASE DayInt:
CASE 1, 21, 31: Day = STR$(DayInt) + "st, "
CASE 2, 22: Day = STR$(DayInt) + "nd, "
CASE 3, 23: Day = STR$(DayInt) + "rd, "
CASE ELSE: Day = STR$(DayInt) + "th, "
END SELECT
SELECT CASE MonthInt:
CASE 1: Month = "January "
CASE 2: Month = "February "
CASE 3: Month = "March "
CASE 4: Month = "April "
CASE 5: Month = "May "
CASE 6: Month = "June "
CASE 7: Month = "July "
CASE 8: Month = "August "
CASE 9: Month = "September "
CASE 10: Month = "October "
CASE 11: Month = "November "
CASE 12: Month = "December "
END SELECT
BIRTHDAY$ = DAYOFWEEK(YearInt - 2000, MonthInt, DayInt) + ", " + Month + Day + Year
END FUNCTION
'Formats the date
FUNCTION TODAY$
DIM AS STRING Month, Day, Year
DIM AS INTEGER M
Month = LEFT$(DATE$, 2): M = VAL(Month)
Day = MID$(DATE$, 4, 2)
Year = RIGHT$(DATE$, 4)
SELECT CASE M:
CASE 1: Month = "January "
CASE 2: Month = "February "
CASE 3: Month = "March "
CASE 4: Month = "April "
CASE 5: Month = "May "
CASE 6: Month = "June "
CASE 7: Month = "July "
CASE 8: Month = "August "
CASE 9: Month = "September "
CASE 10: Month = "October "
CASE 11: Month = "November "
CASE 12: Month = "December "
END SELECT
TODAY$ = Month + Day + ", " + Year
END FUNCTION
'Thank you QB64 member Hannes Sehestedt for documenting Day of the week so well!
FUNCTION DAYOFWEEK$ (Year AS INTEGER, Month AS INTEGER, Day AS INTEGER)
DIM AS STRING WeekDay(1 TO 7)
DIM AS INTEGER MonthDay(1 TO 12)
DIM AS INTEGER Result2, Result1, Result3, Temp, Temp2, LeapYear
WeekDay(2) = "Sunday"
WeekDay(3) = "Monday"
WeekDay(4) = "Tuesday"
WeekDay(5) = "Wednesday"
WeekDay(6) = "Thursday"
WeekDay(7) = "Friday"
WeekDay(1) = "Saturday"
MonthDay(1) = 0
MonthDay(2) = 3
MonthDay(3) = 3
MonthDay(4) = 6
MonthDay(5) = 1
MonthDay(6) = 4
MonthDay(7) = 6
MonthDay(8) = 2
MonthDay(9) = 5
MonthDay(10) = 0
MonthDay(11) = 3
MonthDay(12) = 5
Temp = Day + MonthDay(Month) 'Add the day of the month with the MonthDay Value
IF Temp > 6 THEN 'If above 6, subtract the highest multiple of 7
Temp2 = INT(Temp / 7)
Temp = Temp - (Temp2 * 7)
END IF
Result1 = Temp
Temp = Year
IF Year > 27 THEN 'Last two digits of the year, subtract the year that has the highest multiple of 28
Temp2 = INT(Temp / 28)
Temp = Year - (Temp2 * 28)
END IF
Result2 = Temp
Temp = 0
IF Year > 3 THEN 'Take the year value and divide by 4 rounding down
Temp = INT(Year / 4)
END IF
Result3 = Result2 + Temp
IF Month < 3 THEN 'Leap year check, take one away if leap year before leap year day 2/29
IF (Year / 4) = (INT(Year / 4)) THEN
LeapYear = 1
ELSE
LeapYear = 0
END IF
Result3 = Result3 - LeapYear
END IF
Result3 = Result3 + Result1
IF Result3 > 6 THEN
Temp = INT(Result3 / 7)
Result3 = Result3 - (Temp * 7)
END IF
Result3 = Result3 + 1
DAYOFWEEK$ = WeekDay(Result3)
END FUNCTION
'Thank you QB64 WIKI!/Returns time into a more friendly reading style.
FUNCTION CLOCK$
DIM AS STRING Hour, Min, AmPm
DIM AS INTEGER H
Hour = LEFT$(TIME$, 2): H = VAL(Hour)
Min = MID$(TIME$, 3, 3)
IF H >= 12 THEN AmPm = " PM" ELSE AmPm = " AM"
IF H > 12 THEN
IF H - 12 < 10 THEN Hour$ = STR$(H - 12) ELSE Hour$ = LTRIM$(STR$(H% - 12))
ELSEIF H = 0 THEN Hour = "12" ' midnight hour
ELSE: IF H < 10 THEN Hour = STR$(H) ' eliminate leading zeros
END IF
CLOCK$ = Hour + Min + AmPm
END FUNCTION
SUB SORT (Element AS INTEGER) '1 - first name, 2 - birthday, 3 - house color
DIM AS BYTE OOO 'Out of order
DIM AS INTEGER SortCounter
SELECT CASE Element
CASE 1: 'First name sort
DO
OOO = FALSE
FOR SortCounter = 1 TO NumberOfStudents - 1
IF NameList(SortCounter).FirstName > NameList(SortCounter + 1).FirstName THEN
SWAP NameList(SortCounter), NameList(SortCounter + 1)
OOO = TRUE
ELSEIF NameList(SortCounter).FirstName = NameList(SortCounter + 1).FirstName AND _
NameList(SortCounter).LastName > NameList(SortCounter + 1).LastName THEN 'Used for same first names only
SWAP NameList(SortCounter), NameList(SortCounter + 1)
OOO = TRUE
END IF
NEXT SortCounter
LOOP WHILE OOO
CASE 2: 'Birthday Sort
DO
OOO = FALSE
FOR SortCounter = 1 TO NumberOfStudents - 1
IF NameList(SortCounter).Month > NameList(SortCounter + 1).Month THEN
SWAP NameList(SortCounter), NameList(SortCounter + 1)
OOO = TRUE
ELSEIF NameList(SortCounter).Month = NameList(SortCounter + 1).Month AND _
NameList(SortCounter).Day > NameList(SortCounter + 1).Day THEN 'Sort the days inside a month
SWAP NameList(SortCounter), NameList(SortCounter + 1)
OOO = TRUE
ELSEIF NameList(SortCounter).Month = NameList(SortCounter + 1).Month AND _
NameList(SortCounter).Day = NameList(SortCounter + 1).Day AND _
NameList(SortCounter).FirstName > NameList(SortCounter + 1).FirstName THEN 'Secondary sort first name
SWAP NameList(SortCounter), NameList(SortCounter + 1)
OOO = TRUE
ELSEIF NameList(SortCounter).Month = NameList(SortCounter + 1).Month AND _
NameList(SortCounter).Day = NameList(SortCounter + 1).Day AND _
NameList(SortCounter).FirstName = NameList(SortCounter + 1).FirstName AND _
NameList(SortCounter).LastName > NameList(SortCounter + 1).LastName THEN 'Trinary sort last name
SWAP NameList(SortCounter), NameList(SortCounter + 1)
OOO = TRUE
END IF
NEXT SortCounter
LOOP WHILE OOO
CASE 3: 'Color sort
DO
OOO = FALSE
FOR SortCounter = 1 TO NumberOfStudents - 1
IF NameList(SortCounter).HouseColor > NameList(SortCounter + 1).HouseColor THEN
SWAP NameList(SortCounter), NameList(SortCounter + 1)
OOO = TRUE
ELSEIF NameList(SortCounter).HouseColor = NameList(SortCounter + 1).HouseColor AND _
NameList(SortCounter).FirstName > NameList(SortCounter + 1).FirstName THEN 'Secondary sort by first name
SWAP NameList(SortCounter), NameList(SortCounter + 1)
OOO = TRUE
ELSEIF NameList(SortCounter).HouseColor = NameList(SortCounter + 1).HouseColor AND _
NameList(SortCounter).FirstName = NameList(SortCounter + 1).FirstName AND _
NameList(SortCounter).LastName > NameList(SortCounter + 1).LastName THEN 'Trinary sort by last name
SWAP NameList(SortCounter), NameList(SortCounter + 1)
OOO = TRUE
END IF
NEXT SortCounter
LOOP WHILE OOO
END SELECT
END SUB
'Simple delay with keyboard flush - Used to avoid double key presses
SUB PAUSE (Dlay)
DELAY Dlay
KEYCLEAR 'Clear any key press
END SUB