Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - George McGinn

Pages: [1] 2
1
I've have updates ready to QB64 that will automatically install it on a Raspberry PI and works properly, including DATA statements.

With Apple's new computers running the M1 ARM processor, and Intel (announced in June of 2021), along with AMD and Microsoft working together (announced in October of 2021) to develop ARM processors, QB64 needs to be able to run on these chips as well.

I have tested my changes, but I would like some others to check it out as well before I push the change on Gitub.

In my tests, I have even run compiled QB64 programs that use MariaDB and Zenity on the PI without issues. Pipecom runs without issues as well as $DEBUG. However, my testing has only been done on the 32bit Raspian OS. I do plan to test it with other Linux systems that run on the PI.

There were a number of changes needed, which most are automated in the setup_lnx.sh script. The other change was made directly to common.h.

The two files that changed are below, but here is what I needed to change.

common.h
Two of the issues I ran into had to do with mis-aligned addresses (int32 and int16 for example). To correct this, I either needed to add "-fsanitize=address" to the gcc statement, or add code to the common.h file for ARM processors. I was given the code by a C++ programmer who explained that, while not an issue with x86_64 or i386 processors, it is an issue with ARM processors. The code (see below) corrects this issue. She also gave me the corresponding code for the x86_64/i386, just in case. I've regression tested this on my x86_64 system, but others should also run it as well.

setup_lnx.sh
The setup script has a number of issues on ARM processors. The first is it doesn't download the libraries needed, and the other it created invalid link modules. To correct the first issue, the setup script now checks whether or not the processor is an ARM. If so, it sets DISTRO to "raspbian". The issue about the link/binary executables has to do with how the ARM processes bits. ARM processors are little endian (See note below). So the script replaces both the makedat_lnx32.txt and makedat_lnx64.txt files with the correct parameters for the OBJCOPY. ("-Oelf32-littlearm -Barm" replaced the original "-Oelf32-i386 -Bi386" in the 32bit file and the "-Oelf64-littlearm -Barm" replaced the "-Oelf64-x86-64 -Bi386:x86-64" in the 64bit file)

NOTE: Yes, Intel, AMD and the PI ARM chips are all little endian. However, from what I've read, the Intel and AMD chips convert the little endian to big endian. It has something to do with floating point. However, this does not seem to be the case with ARM processors, at least for the PI. From what I read, the Apple M1 is designed the same as that the PI's ARM. This change to the OBJCOPY allows DATA statements, among other things, to work. the -Barm tells OBJCOPY how to format the binary executable file. This is my understanding, which is of course, subject to interpretation, but the changes makes QB64 run and compile, and compiled programs also run on the PI.

To implement these changes, after extracting the QB64 compiler, you need to replace the common.h file in the qb64/internal/c directory, and the setup_lnx.sh file in the main qb64 directory. Then all you have to do is run the setup_lnx.sh file to install library dependencies and compile qb64.bas.

These changes should also work on the Apple M1 ARM processor, but I do not have one to test this on. If someone has a M1 ARM processor, I can provide the changes to the setup_osx.command script. You'll have to do the testing as I will not have a M1 processor until July.

Also, besides the M1 processor, I haven't been able to test is a 64bit OS on the Raspberry PI. Raspberry no longer offers the 64bit version of their Raspbian OS. So while I am looking for non-raspbian OS's to test on, if someone here is running, say Kali on a PI or an earlier version of the 64bit Raspbian OS, please test this. I will do so as well, but the more who tests this, the better. (This was suggested by Fellippe).

Some Issues:
When testing this on my PI, I was unable to get InForm to run. It compiles, but I get a series of errors from "Bus signal errors" to misaligned addresses. I am still looking into this, but I may need to defer to Fellippe or Luke on this, as I am not a C++ programmer, and in my C coding, I've never encountered these errors. I have run tests in gdb and ddd utilites to try and isolate the issue, but I am at a loss. If someone wants to tackle this on their PI, I'd appreciate it.

Here is the common.h file:
Code: C: [Select]
  1. //Setup for ARM Processor (Similar to -fsanitize=address GCC compiler flag)
  2. #ifdef __arm__
  3.         #define POST_PACKED_STRUCTURE
  4. #else
  5.         #define POST_PACKED_STRUCTURE __attribute__((__packed__))
  6. #endif /* ARM */
  7.  
  8. //Fill out dependency macros
  9. #ifndef DEPENDENCY_NO_SOCKETS
  10.     #define DEPENDENCY_SOCKETS
  11. #endif
  12.  
  13. #ifndef DEPENDENCY_NO_PRINTER
  14.     #define DEPENDENCY_PRINTER
  15. #endif
  16.  
  17. #ifndef DEPENDENCY_NO_ICON
  18.     #define DEPENDENCY_ICON
  19. #endif
  20.  
  21. #ifndef DEPENDENCY_NO_SCREENIMAGE
  22.     #define DEPENDENCY_SCREENIMAGE
  23. #endif
  24.  
  25. #ifndef INC_COMMON_CPP
  26.     #define INC_COMMON_CPP
  27.     #include "os.h"
  28.    
  29.     #define QB64_GL1
  30.     #define QB64_GLUT
  31.    
  32.     #ifdef DEPENDENCY_CONSOLE_ONLY
  33.         #undef QB64_GLUT
  34.         #else
  35.         #define QB64_GUI
  36.     #endif
  37.    
  38.     //core
  39.     #ifdef QB64_GUI
  40.         #ifdef QB64_GLUT
  41.             //This file only contains header stuff
  42.             #include "parts/core/src.c"
  43.         #endif
  44.     #endif
  45.    
  46.     #ifdef QB64_WINDOWS
  47.        
  48.         #ifndef QB64_GUI
  49.             #undef int64 //definition of int64 from os.h conflicts with a definition within windows.h, temporarily undefine then redefine
  50.             #include <windows.h>
  51.             #define int64 __int64
  52.         #endif
  53.        
  54.         #include <shfolder.h>
  55.        
  56.         #include <float.h>
  57.         #include <winbase.h>
  58.        
  59.     #endif
  60.    
  61.     //common includes
  62.     #include <stdio.h>
  63.     #ifdef QB64_MACOSX
  64.         #include <cmath>
  65.         #else
  66.         //#include <math.h> //<-causes overloading abs conflicts in Windows
  67.         #include <cmath>
  68.     #endif
  69.     #include <time.h>
  70.     #include <iostream>
  71.     #include <fstream>
  72.     #include <time.h>
  73.     #include <string.h>
  74.     #include <errno.h>
  75.     #include <fcntl.h>
  76.    
  77.     //OS/compiler specific includes
  78.     #ifdef QB64_WINDOWS
  79.         #include <direct.h>
  80.         #ifdef DEPENDENCY_PRINTER
  81.             #include <winspool.h>
  82.         #endif
  83.         #include <csignal>
  84.         #include <process.h> //required for multi-threading
  85.         #if defined DEPENDENCY_AUDIO_OUT || defined QB64_GUI
  86.             #include <mmsystem.h>
  87.         #endif
  88.        
  89.         #else
  90.        
  91.         #include <stdlib.h>
  92.         #include <sys/types.h>
  93.         #include <sys/stat.h>
  94.         #include <sys/wait.h>
  95.         #include <unistd.h>
  96.         #include <stdint.h>
  97.         #include <pthread.h>
  98.         #ifndef QB64_MACOSX
  99.             #include <dlfcn.h>
  100.         #endif
  101.        
  102.     #endif
  103.    
  104.     #ifdef QB64_GUI
  105.         #ifdef QB64_GLUT
  106.             #include "parts/core/gl_headers/opengl_org_registery/glext.h"
  107.         #endif
  108.     #endif
  109.    
  110.    
  111.     //QB64 string descriptor structure
  112.     struct qbs_field{
  113.         int32 fileno;
  114.         int64 fileid;
  115.         int64 size;
  116.         int64 offset;
  117.     };
  118.    
  119.     struct qbs{
  120.         uint8 *chr;//a 32 bit pointer to the string's data
  121.         int32 len;//must be signed for comparisons against signed int32s
  122.         uint8 in_cmem;//set to 1 if in the conventional memory DBLOCK
  123.         uint16 *cmem_descriptor;
  124.         uint16 cmem_descriptor_offset;
  125.         uint32 listi;//the index in the list of strings that references it
  126.         uint8 tmp;//set to 1 if the string can be deleted immediately after being processed
  127.         uint32 tmplisti;//the index in the list of strings that references it
  128.         uint8 fixed;//fixed length string
  129.         uint8 readonly;//set to 1 if string is read only
  130.         qbs_field *field;
  131.     };
  132.    
  133.     struct img_struct{
  134.         void *lock_offset;
  135.         int64 lock_id;
  136.         uint8 valid;//0,1 0=invalid
  137.         uint8 text;//if set, surface is a text surface
  138.         uint8 console;//dummy surface to absorb unimplemented console functionality
  139.         uint16 width,height;
  140.         uint8 bytes_per_pixel;//1,2,4
  141.         uint8 bits_per_pixel;//1,2,4,8,16(text),32
  142.         uint32 mask;//1,3,0xF,0xFF,0xFFFF,0xFFFFFFFF
  143.         uint16 compatible_mode;//0,1,2,7,8,9,10,11,12,13,32,256
  144.         uint32 color,background_color,draw_color;
  145.         uint32 font;//8,14,16,?
  146.         int16 top_row,bottom_row;//VIEW PRINT settings, unique (as in QB) to each "page"
  147.         int16 cursor_x,cursor_y;//unique (as in QB) to each "page"
  148.         uint8 cursor_show, cursor_firstvalue, cursor_lastvalue;
  149.         union{
  150.             uint8 *offset;
  151.             uint32 *offset32;
  152.         };
  153.         uint32 flags;
  154.         uint32 *pal;
  155.         int32 transparent_color;//-1 means no color is transparent
  156.         uint8 alpha_disabled;
  157.         uint8 holding_cursor;
  158.         uint8 print_mode;
  159.         //BEGIN apm ('active page migration')
  160.         //everything between apm points is migrated during active page changes
  161.         //note: apm data is only relevent to graphics modes
  162.         uint8 apm_p1;
  163.         int32 view_x1,view_y1,view_x2,view_y2;
  164.         int32 view_offset_x,view_offset_y;
  165.         float x,y;
  166.         uint8 clipping_or_scaling;
  167.         float scaling_x,scaling_y,scaling_offset_x,scaling_offset_y;
  168.         float window_x1,window_y1,window_x2,window_y2;
  169.         double draw_ta;
  170.         double draw_scale;
  171.         uint8 apm_p2;
  172.         //END apm
  173.     };
  174.     //img_struct flags
  175.     #define IMG_FREEPAL 1 //free palette data before freeing image
  176.     #define IMG_SCREEN 2 //img is linked to other screen pages
  177.     #define IMG_FREEMEM 4 //if set, it means memory must be freed
  178.    
  179.    
  180.     //QB64 internal variable type flags (internally referenced by some C functions)
  181.     #define ISSTRING 1073741824
  182.     #define ISFLOAT 536870912
  183.     #define ISUNSIGNED 268435456
  184.     #define ISPOINTER 134217728
  185.     #define ISFIXEDLENGTH 67108864 //only set for strings with pointer flag
  186.     #define ISINCONVENTIONALMEMORY 33554432
  187.     #define ISOFFSETINBITS 16777216
  188.    
  189.     struct ontimer_struct{
  190.         uint8 allocated;
  191.         uint32 id;//the event ID to trigger (0=no event)
  192.         int64 pass;//the value to pass to the triggered event (only applicable to ON ... CALL ...(x)
  193.         uint8 active;//0=OFF, 1=ON, 2=STOP
  194.         uint8 state;//0=untriggered,1=triggered
  195.         double seconds;//how many seconds between events
  196.         double last_time;//the last time this event was triggered
  197.     };
  198.    
  199.     struct onkey_struct{
  200.         uint32 id;//the event ID to trigger (0=no event)
  201.         int64 pass;//the value to pass to the triggered event (only applicable to ON ... CALL ...(x)
  202.         uint8 active;//0=OFF, 1=ON, 2=STOP
  203.         uint8 state;//0=untriggered,1=triggered,2=in progress(TIMER only),2+=multiple events queued(KEY only)
  204.         uint32 keycode;//32-bit code, same as what _KEYHIT returns
  205.         uint32 keycode_alternate;//an alternate keycode which may also trigger event
  206.         uint8 key_scancode;
  207.         uint8 key_flags;
  208.         //flags:
  209.         //0 No keyboard flag, 1-3 Either Shift key, 4 Ctrl key, 8 Alt key,32 NumLock key,64 Caps Lock key, 128 Extended keys on a 101-key keyboard
  210.         //To specify multiple shift states, add the values together. For example, a value of 12 specifies that the user-defined key is used in combination with the Ctrl and Alt keys.
  211.         qbs *text;
  212.     };
  213.    
  214.     struct onstrig_struct{
  215.         uint32 id;//the event ID to trigger (0=no event)
  216.         int64 pass;//the value to pass to the triggered event (only applicable to ON ... CALL ...(x)
  217.         uint8 active;//0=OFF, 1=ON, 2=STOP
  218.         uint8 state;//0=untriggered,1=triggered,2=in progress(TIMER only),2+=multiple events queued(KEY only)
  219.     };
  220.    
  221.     struct byte_element_struct
  222.     {
  223.         uint64 offset;
  224.         int32 length;
  225.     };
  226.    
  227.     struct device_struct{
  228.         int32 used;
  229.         int32 type;
  230.         //0=Unallocated
  231.         //1=Joystick/Gamepad
  232.         //2=Keybaord
  233.         //3=Mouse  
  234.         char *name;
  235.         int32 connected;
  236.         int32 lastbutton;
  237.         int32 lastaxis;
  238.         int32 lastwheel;
  239.         //--------------
  240.         int32 max_events;
  241.         int32 queued_events;
  242.         uint8 *events;//the structure and size of the events depends greatly on the device and its capabilities
  243.         int32 event_size;
  244.         //--------------
  245.         uint8 STRIG_button_pressed[256];//checked and cleared by the STRIG function
  246.         //--------------
  247.         void *handle_pointer;//handle as pointer
  248.         int64 handle_int;//handle as integer
  249.         char *description;//description provided by manufacturer
  250.         int64 product_id;
  251.         int64 vendor_id;
  252.         int32 buttons;
  253.         int32 axes;
  254.         int32 balls;
  255.         int32 hats;
  256.     };
  257.    
  258.     //device_struct constants
  259.     #define QUEUED_EVENTS_LIMIT 1024
  260.     #define DEVICETYPE_CONTROLLER 1
  261.     #define DEVICETYPE_KEYBOARD 2
  262.     #define DEVICETYPE_MOUSE 3
  263.    
  264.     struct mem_block{
  265.         ptrszint offset;
  266.         ptrszint size;
  267.         int64 lock_id;//64-bit key, must be present at lock's offset or memory region is invalid
  268.         ptrszint lock_offset;//pointer to lock
  269.         ptrszint type;
  270.         /*
  271.             memorytype (4 bytes, but only the first used, for flags):
  272.             1 integer values
  273.             2 unsigned (set in conjunction with integer)
  274.             4 floating point values
  275.             8 char string(s) 'element-size is the memory size of 1 string
  276.         */
  277.         ptrszint elementsize;
  278.         int32 image;
  279.         int32 sound;
  280.     };
  281.     struct mem_lock{
  282.         uint64 id;
  283.         int32 type;//required to know what action to take (if any) when a request is made to free the block
  284.         //0=no security (eg. user defined block from _OFFSET)
  285.         //1=C-malloc'ed block
  286.         //2=image
  287.         //3=sub/function scope block
  288.         //4=array
  289.         //5=sound
  290.         //---- type specific variables follow ----
  291.         void *offset;//used by malloc'ed blocks to free them
  292.     };
  293.    
  294. #endif //INC_COMMON_CPP
  295.  

Here is the setup_lnx.sh file:
Code: Bash: [Select]
  1. #!/bin/bash
  2. #QB64 Installer -- Shell Script -- Matt Kilgore 2013
  3. #Version 5 -- January 2020
  4.  
  5. #This version includes the updates to sucessfully install QB64 on the PI
  6. #or any ARM processor (Current version only tested on the Raspberry PI and
  7. #sets the DISTRO to "raspbian".) -- George McGinn (2/1/2022)
  8.  
  9. #This checks the currently installed packages for the one's QB64 needs
  10. #And runs the package manager to install them if that is the case
  11. pkg_install() {
  12.   #Search
  13.   packages_to_install=
  14.   for pkg in $pkg_list; do
  15.     if [ -z "$(echo "$installed_packages" | grep $pkg)" ]; then
  16.       packages_to_install="$packages_to_install $pkg"
  17.     fi
  18.   done
  19.   if [ -n "$packages_to_install" ]; then
  20.     echo "Installing required packages. If prompted to, please enter your password."
  21.     $installer_command $packages_to_install
  22.   fi
  23.  
  24. }
  25.  
  26. #Make sure we're not running as root
  27. if [ $EUID == "0" ]; then
  28.   echo "You are trying to run this script as root. This is highly unrecommended."
  29.   echo "This script will prompt you for your sudo password if needed to install packages."
  30.   exit 1
  31. fi
  32.  
  33. GET_WGET=
  34. #Path to Icon
  35. #Relative Path to icon -- Don't include beginning or trailing '/'
  36. QB64_ICON_PATH="internal/source"
  37.  
  38. #Name of the Icon picture
  39. QB64_ICON_NAME="qb64icon32.png"
  40.  
  41. DISTRO=
  42.  
  43. lsb_command=`which lsb_release 2> /dev/null`
  44. if [ -z "$lsb_command" ]; then
  45.   lsb_command=`which lsb_release 2> /dev/null`
  46. fi
  47.  
  48. #Outputs from lsb_command:
  49.  
  50. #Arch Linux  = arch
  51. #Debian      = debian
  52. #Fedora      = Fedora
  53. #KUbuntu     = ubuntu
  54. #LUbuntu     = ubuntu
  55. #Linux Mint  = linuxmint
  56. #Ubuntu      = ubuntu
  57. #Raspbian    = raspbian
  58. #Slackware   = slackware
  59. #VoidLinux   = voidlinux
  60. #XUbuntu     = ubuntu
  61. #Zorin       = Zorin
  62. if [ -n "$lsb_command" ]; then
  63.   DISTRO=`$lsb_command -si | tr '[:upper:]' '[:lower:]'`
  64. elif [ -e /etc/arch-release ]; then
  65.   DISTRO=arch
  66. elif [ -e /etc/debian_version ] || [ -e /etc/debian_release ]; then
  67.   DISTRO=debian
  68. elif [ -e /etc/fedora-release ]; then
  69.   DISTRO=fedora
  70. elif [ -e /etc/redhat-release ]; then
  71.   DISTRO=redhat
  72. elif [ -e /etc/centos-release ]; then
  73.   DISTRO=centos
  74. elif $(arch | grep arm > /dev/null); then
  75.   DISTRO=raspbian
  76. fi
  77.  
  78. echo "DISTRO detected = $DISTRO"
  79.  
  80. #Find and install packages
  81. if [ "$DISTRO" == "arch" ]; then
  82.   echo "ArchLinux detected."
  83.   pkg_list="gcc zlib xorg-xmessage $GET_WGET"
  84.   installed_packages=`pacman -Q`
  85.   installer_command="sudo pacman -S "
  86.   pkg_install
  87. elif [ "$DISTRO" == "linuxmint" ] || [ "$DISTRO" == "ubuntu" ] || [ "$DISTRO" == "debian" ] || [ "$DISTRO" == "zorin" ] || [ "$DISTRO" == "raspbian" ]; then
  88.   echo "Debian/Raspian based distro detected."
  89.   pkg_list="g++ x11-utils mesa-common-dev libglu1-mesa-dev libasound2-dev zlib1g-dev $GET_WGET"
  90.   installed_packages=`dpkg -l`
  91.   installer_command="sudo apt-get -y install "
  92.   pkg_install
  93. elif [ "$DISTRO" == "fedora" ] || [ "$DISTRO" == "redhat" ] || [ "$DISTRO" == "centos" ]; then
  94.   echo "Fedora/Redhat based distro detected."
  95.   pkg_list="gcc-c++ xmessage mesa-libGLU-devel alsa-lib-devel zlib-devel $GET_WGET"
  96.   installed_packages=`yum list installed`
  97.   installer_command="sudo yum install "
  98.   pkg_install
  99. elif [ "$DISTRO" == "voidlinux" ]; then
  100.    echo "VoidLinux detected."
  101.    pkg_list="gcc xmessage glu-devel zlib-devel alsa-lib-devel $GET_WGET"
  102.    installed_packages=`xbps-query -l |grep -v libgcc`
  103.    installer_command="sudo xbps-install -Sy "
  104.    pkg_install
  105. elif [ -z "$DISTRO" ]; then
  106.   echo "Unable to detect distro, skipping package installation"
  107.   echo "Please be aware that for QB64 to compile, you will need the following installed:"
  108.   echo "  OpenGL developement libraries"
  109.   echo "  ALSA development libraries"
  110.   echo "  GNU C++ Compiler (g++)"
  111.   echo "  xmessage (x11-utils)"
  112.   echo "  zlib"
  113. fi
  114.  
  115. echo "Compiling and installing QB64..."
  116.  
  117. ### Build process
  118. find . -name "*.sh" -exec chmod +x {} \;
  119. find internal/c/parts -type f -iname "*.a" -exec rm -f {} \;
  120. find internal/c/parts -type f -iname "*.o" -exec rm -f {} \;
  121. find internal/c/libqb -type f -iname "*.o" -exec rm -f {} \;
  122. rm ./internal/temp/*
  123.  
  124. #if [ "$DISTRO" == "raspbian" ]; then
  125. if $(arch | grep arm > /dev/null); then
  126.   echo "Updating files for the ARM processor..."
  127.   echo "updating makedat_lnx32.txt file..."
  128.   pushd internal/c >/dev/null
  129.   cat > makedat_lnx32.txt <<EOF
  130. objcopy -Ibinary -Oelf32-littlearm -Barm
  131. EOF
  132.   echo "updating makedat_lnx64.txt file..."
  133.   cat > makedat_lnx64.txt <<EOF
  134. objcopy -Ibinary -Oelf64-littlearm -Barm
  135. EOF
  136.   popd >/dev/null
  137. fi
  138.  
  139. echo "Building library 'LibQB'"
  140. pushd internal/c/libqb/os/lnx >/dev/null
  141. rm -f libqb_setup.o
  142. ./setup_build.sh
  143. popd >/dev/null
  144.  
  145. echo "Building library 'FreeType'"
  146. pushd internal/c/parts/video/font/ttf/os/lnx >/dev/null
  147. rm -f src.o
  148. ./setup_build.sh
  149. popd >/dev/null
  150.  
  151. echo "Building library 'Core:FreeGLUT'"
  152. pushd internal/c/parts/core/os/lnx >/dev/null
  153. rm -f src.a
  154. ./setup_build.sh
  155. popd >/dev/null
  156.  
  157. echo "Building 'QB64'"
  158. cp -r ./internal/source/* ./internal/temp/
  159. pushd internal/c >/dev/null
  160. g++ -no-pie -w qbx.cpp libqb/os/lnx/libqb_setup.o parts/video/font/ttf/os/lnx/src.o parts/core/os/lnx/src.a -lGL -lGLU -lX11 -lpthread -ldl -lrt -D FREEGLUT_STATIC -o ../../qb64
  161. popd
  162.  
  163. if [ -e "./qb64" ]; then
  164.   echo "Done compiling!!"
  165.  
  166.   echo "Creating ./run_qb64.sh script..."
  167.   _pwd=`pwd`
  168.   echo "#!/bin/sh" > ./run_qb64.sh
  169.   echo "cd $_pwd" >> ./run_qb64.sh
  170.   echo "./qb64 &" >> ./run_qb64.sh
  171.  
  172.   chmod +x ./run_qb64.sh
  173.   #chmod -R 777 ./
  174.   echo "Adding QB64 menu entry..."
  175.   cat > ~/.local/share/applications/qb64.desktop <<EOF
  176. [Desktop Entry]
  177. Name=QB64 Programming IDE
  178. GenericName=QB64 Programming IDE
  179. Exec=$_pwd/run_qb64.sh
  180. Icon=$_pwd/$QB64_ICON_PATH/$QB64_ICON_NAME
  181. Terminal=false
  182. Type=Application
  183. Categories=Development;IDE;
  184. Path=$_pwd
  185. StartupNotify=false
  186. EOF
  187.  
  188.   echo "Running QB64..."
  189.   ./qb64 &
  190.   echo "QB64 is located in this folder:"
  191.   echo "`pwd`"
  192.   echo "There is a ./run_qb64.sh script in this folder that should let you run qb64 if using the executable directly isn't working."
  193.   echo
  194.   echo "You should also find a QB64 option in the Programming/Development section of your menu you can use."
  195. else
  196.   ### QB64 didn't compile
  197.   echo "It appears that the qb64 executable file was not created, this is usually an indication of a compile failure (You probably saw lots of error messages pop up on the screen)"
  198.   echo "Usually these are due to missing packages needed for compilation. If you're not running a distro supported by this compiler, please note you will need to install the packages listed above."
  199.   echo "If you need help, please feel free to post on the QB64 Forums detailing what happened and what distro you are using."
  200.   echo "Also, please tell them the exact contents of this next line:"
  201.   echo "DISTRO: $DISTRO"
  202. fi
  203. echo
  204. echo "Thank you for using the QB64 installer."
  205.  



Thanks,

2
Programs / Converting MIDI to WAV and MP3 (BASH Script)
« on: December 19, 2021, 07:20:03 pm »
Awhile back I ran into issues where my MIDI file collection needed to be converted into an acceptable file format to be able to play it in QB64, as the only valid files are: WAV, OGG or MP3 file types.

So below is a BASH Shell script that converts a MIDI file into BOTH a .wav and a .mp3 file.

You will need to have installed:

Zenity - Used for the BASH GUI
timidity - To convert MIDI to WAV (Software synthesizer)
ffmpeg -  To convert timidity WAV to MP3 files.

Except for Zenity, timidity and ffmpeg I believe exists on all OS's, Since I only run Linux and macOS, I can't guarantee that this will run on Windows, but the principle behind what the script does should apply. I haven't completely tested it yet on my macOS, but I have installed the three requirements above. If I have any issues with it, I will post an update (not an edit). I know not all features of Zenity work on a macOS system. So I may create a command-line version.

Now I can convert all my Christmas MIDI files into WAV and MP3 files.

Merry Christmas.

Code: Bash: [Select]
  1. #!/bin/bash
  2. #
  3. # MIDI to WAV and MP3 Converter -- Shell Script -- George McGinn 2021
  4. #Version 1.0 -- December 19, 2021
  5. #
  6. # convertMIDI - Script to convert a MIDI file into both a .WAV and .MP3
  7. #               audio formats. Uses Zenity to retrieve the MIDI file,
  8. #               create the output files, show progress, and other messages.
  9. #
  10. # NOTES: This script needs the following installed:
  11. #        Zenity - Script's GUI
  12. #        timidity - Converts the MIDI to a WAV format
  13. #        ffmpeg - Converts a MIDI/WAV to MP3 format
  14. #
  15. # USEAGE:
  16. #   This script can be invoked from a File Manager or from a terminal
  17. #   session. When started, it defaults to your $HOME/Music directory.
  18. #   Select the location of your MIDI file. You will be able to change
  19. #   the directory. Select your MID or MIDI file then click [OK]. Next
  20. #   The output for the WAV and MP3 files will default to your $HOME/Music
  21. #   directory. You can change this location. Enter the file name WITHOUT
  22. #   any extensions. The .wav and .mp3 will be added to the file name
  23. #   you provide. The script will create both files.
  24. #
  25. #   If you select directory(ies) that require ROOT access, the script will
  26. #   ask you for your password and then do the conversions as stated above.
  27. #   There is no need to start this script with sudo.
  28. #
  29.  
  30. # Change directory to Home/Music
  31.  
  32. cd $HOME/Music
  33.  
  34. # Get the MIDI path/file name
  35. mid=$(zenity --file-selection)
  36. if [ $? = 1 ];
  37.         then exit
  38. fi
  39.  
  40.  
  41. # Get save path/file name
  42. wav=$(zenity --file-selection --save --confirm-overwrite)
  43. if [ $? = 1 ];
  44.         then exit
  45. fi
  46.  
  47. # see if current user has write permissions by creating an empty file
  48. > "$wav:".wav
  49. > "$wav".mp3
  50.  
  51. # if so, delete the empty files and do the conversion and show progress bar
  52. if [ $?  -eq 0 ]; then
  53.         rm "$wav:".wav
  54.         rm "$wav".mp3
  55.  
  56.         timidity "$mid" -Ow -o "$wav".wav  | zenity --progress --pulsate --auto-close --text "Converting to WAV..."
  57.         timidity "$mid" -Ow -o - | ffmpeg -i - -acodec libmp3lame -ab 64k "$wav".mp3 | zenity --progress --pulsate --auto-close --text "Converting to MP3..."
  58.  
  59. # Tell us the conversion is done
  60.         zenity --info --text "Conversion complete!"
  61.  
  62. # if not, get root password, run command as root
  63. else
  64. # Get the users password
  65.         passwd=$(zenity --password)
  66.  
  67. # Do the conversion and show a progress bar
  68.         echo $passwd|sudo -S timidity "$mid" -Ow -o "$wav".wav | zenity --progress --pulsate --auto-close --text "Converting to WAV..."
  69.         echo $passwd|sudo -S timidity "$mid" -Ow -o - | ffmpeg -i - -acodec libmp3lame -ab 64k "$wav".mp3 | zenity --progress --pulsate --auto-close --text "Converting to MP3..."
  70.  
  71.         if [ $? = 1 ];
  72.                 then exit
  73.         fi
  74.  
  75. # Tell us the conversion is done
  76.         zenity --info --text "Conversion complete!"
  77. fi
  78.  

3
Programs / Baseball/Softball Statistical Record-keeping System Pre-Release
« on: December 15, 2021, 02:25:29 pm »
I am posting the pre-release of my Baseball/Softball Statistical System for your input on this. I’ve been working on this for more than 4 months, and I need new eyes to spot things I can’t see. I also hope that some of you find it useful. The final release will have more features that can be used for advanced game record-keeping and will include a suite of Sabermetric tools. Any comments from what works, what doesn’t, clarity needed in my HELP and other documentation, and how to make this work with other relational databases like MariaDB and SQLite will be very helpful.

This Linux-only (for now) application records and produces baseball or softball offensive, defensive and pitching statistics and reports for players and for multiple teams. This can be used if you manage/coach one or more youth baseball teams, run a single baseball/softball league, or play a game like Strat-O-Matic Baseball.

This is a pre-release, as I still have some more features to code. But it appears stable enough to unleash on all of you.

Originally I was going to write just a small program for myself, but some others I know wanted to use it as well, and what started off as a tutorial on using MySQL (or just SQL) with QB64 turned into a large application that includes QB64 code, C++ functions, MySQL, HTML, CSS, JavaScript, and Zenity among others.

I have been also working on getting the code in the WIKI (MySQL Client) by Galleon working, but I will be taking that program in another direction, and those who are waiting for that tutorial will have it, probably by the end of January (I hope!).

This is now an example of using various tools in Linux to create a slick-looking application based on QB64. About a month ago, the QB64 code alone topped 7,000 lines of code, with all the code going above 10,000 lines, so this is a substantial application.

The Readme file on my GitHub is quite extensive (and still a work in progress), but there should be enough information there that you can run this application. Also, when you start up this application, on the ABOUT/Splash Screen, there is a link to a menu where you can read all the HELP files for each function/feature to familiarize yourself with the system.

I have tested this on Ubuntu, Linux Mint, and Q4OS (before I added the ability for the application to adapt to Dark/Light/Standard desktop themes), so you may have to tweak the colors of your Dark Theme in the /help/baseballStyle.css file. The rest works automatically.

I know some of you use a different relational DB then MySQL, and I am interested in hearing from you so I can add the ability to use different DB’s transparent to the user.

I have attached the ZIP file with all the source code and files needed to run this application, but I do suggest that you visit my GitHub listed below to read what is documented.

Here is the link to the pre-release: https://github.com/GeorgeMcGinn/baseballStats/releases/tag/v0.27.0

Here is the link to the files on GitHub: https://github.com/GeorgeMcGinn/baseballStats

 

4
If you think the original Hamurabi game was hard, I've made it more challenging!

In this revised version from the one created by David Ahl, feeding your kingdom just got harder.

The original game's mechanics have remained the same -  that is you have to plant, feed a growing population of people. The can be hit with a plague and rats have been known to eat parts of your bushels.

You still need to provide each person 20 bushels to feed them, and 1 person can plant 10 acres. And you still need 2 bushels to plant an acre.

Here are the new updates to this classic game:
  • You now have to deal with newborns. Each year, you can have up to 10 newborns. These add to the overall population, but they are not available to plant your fields.
  • Able bodies (Planters) are the people who can plant your harvest. If no plagues (or disasters) hit, there could be a larger population, with less people to plant your harvest.
  • Disasters - The current game still has plagues that wipe out 1/2 of your population. I've now added disasters that wipe out 1/3 of your population. And yes, you can get hit by both a plague and a disaster at the same time. The plague wipes out first, then the disaster takes 1/3 of those remaining. Both not only reduces the total population, but also able-bodied people to plant. This is to ensure some of the newborns survive plagues and disasters.
  • Insects (pestilence) have been added as a force affecting your harvest. This part has changed. You can have rat and insect damage, but they now work differently. Rats only eat bushels in storage, while insects only affect the harvest. And yes, I've seen in my testing insects wipe out entire harvests. Rats can do some damage, but I left the original in this game, and rats in my testing have never eaten an entire storage of grain!
All other parameters of the game, right now, are the same.

Remember, when you allocate bushels to feed, it is your entire population (newborns + planters). I have caught myself using the wrong number and starving a few people.

Also, you can choose whether to play with the QB64 Screen, or change the code to play in a terminal. This game should work on all OS's (Windows, Mac and Linux), or wherever you compile your QB64 programs!

Good Luck!

PS: I am developing an InForm version of this game, where you can see, in real time, what your changes do to your values before you commit them. The original game written back in the 1960's and 70's does not provide that. In the spirit of those of us who played the original game when it first came out, I haven't done those updates to this version. But the InForm game will be even more challenging.

Code: QB64: [Select]
  1. _TITLE "Hamurabi - King of Babylon and Ruler of the Ancient Kingdom of Sumeria"
  2.  
  3. ' *** Choose your console/screen type below (comment/uncomment)
  4. '$CONSOLE:ONLY
  5. 'SCREEN 0
  6. SCREEN _NEWIMAGE(800, 600, 32)
  7.  
  8.  
  9. ' ***
  10. ' *** DISPLAY INTRODUCTION TO THE GAME
  11. ' ***
  12. PRINT TAB(32); "HAMURABI"
  13. PRINT "You are the ruler of the ancient kingdom of Sumeria."
  14. PRINT "Your people call you 'Hamurabi the Wise'."
  15. PRINT "Your task is for the next 10 years is to develop"
  16. PRINT "a stable economy by the wise management of your"
  17. PRINT "resources. You will be beset from time to time"
  18. PRINT "by natural events."
  19. PRINT "The only help I can give you is the fact that it"
  20. PRINT "takes 1 bushel of grain as seed to plant two acres."
  21. PRINT "May you judge well, alknowing Hamurabi!"
  22. PRINT "***********HAMURABI IS HERE***********"
  23.  
  24. HamurabiInit:
  25.     DIM AS DOUBLE STARVED, PEOPLE_DIED, PCT_STARVED, YEAR, POPULATION, BUSHELS, HARVESTED
  26.     DIM AS DOUBLE RATS_ATE, PESTILENCE, PRICE, ACRES, IMMIGRATED, C
  27.     DIM AS DOUBLE PI
  28.     DIM AS INTEGER PLAGUE_PCT, PLAGUE, ACRES_BUY, ACRES_SELL, ACRES_PLANTED, BUSHELS_FEED
  29.  
  30.     STARVED = 0 '*** D=0
  31.     PEOPLE_DIED = 0 '*** D1=0
  32.     PCT_STARVED = 0 '*** P1=0
  33.     YEAR = 0 '*** Z=0
  34.     POPULATION = 95 '*** P=95
  35.     BUSHELS = 2800 '*** S=2800
  36.     HARVESTED = 3000 '*** H=3000
  37.     RATS_ATE = HARVESTED - BUSHELS '*** E=H-S
  38.     PESTILENCE = 0 '*** NEW FIELD
  39.     PRICE = 3 '*** Y=3
  40.     ACRES = HARVESTED / PRICE '*** A=H/Y
  41.     IMMIGRATED = 5 '*** I=5
  42.     C = 1 '*** C=1  VARIABLE USED FOR ALL RANDOM NUMBER GENERATORS
  43.     PI = 0
  44.     NEWBORN = 0
  45.     PLANTERS = 0 '*** The number of people able to plant fields (Excludes New Borns)
  46.  
  47.  
  48. PlayGame:
  49.     CLS
  50.     PRINT: PRINT
  51.     PRINT "HAMURABI, I beg to report to you!"
  52.     PRINT
  53.     YEAR = YEAR + 1
  54.     PRINT "In year "; FORMAT$(STR$(YEAR), "##"); ", "; FORMAT$(STR$(STARVED), "#,###"); " People starved, "; FORMAT$(STR$(NEWBORN), "##"); " New Borns, and "; FORMAT$(STR$(IMMIGRATED), "##"); " migrated into the city."
  55.     POPULATION = POPULATION + IMMIGRATED + NEWBORN
  56.     IF YEAR = 1 THEN PLANTERS = POPULATION ELSE PLANTERS = PLANTERS + IMMIGRATED
  57.  
  58. CheckForPlague:
  59. ' *** check for plague and if found, reduce population by 1/2. (15% chance of plague)
  60.     PLAGUE_PCT = (10 * RND(1))
  61.     DISASTER_PCT = (10 * RND(1))
  62.     PRINT
  63.     IF PLAGUE_PCT >= 8.5 AND YEAR > 1 THEN
  64.         PLAGUE = INT(POPULATION / 2)
  65.         POPULATION = PLAGUE
  66.         PLANTERS = INT(PLANTERS / 2)
  67.         PRINT "A horrible plague struck! Half the people died."
  68.         PRINT "Half, or "; FORMAT$(STR$(PLAGUE), "#,###"); " people died of the plague."
  69.         PRINT
  70.     END IF
  71.  
  72.     PRINT
  73.     IF DISASTER_PCT >= 8.5 AND YEAR > 1 THEN
  74.         DISASTER = INT(POPULATION / 3)
  75.         POPULATION = DISASTER
  76.         PLANTERS = INT(PLANTERS / 3)
  77.         PRINT "A horrible disaster struck! One-Third the people died."
  78.         PRINT "One-third, or "; FORMAT$(STR$(DISASTER), "#,###"); " people died from the disaster."
  79.         PRINT
  80.     END IF
  81.  
  82. Display_Population:
  83.     PRINT "Our Population is now "; FORMAT$(STR$(POPULATION), "#,###")
  84.     PRINT "Able-bodied people to plant the fields is now "; FORMAT$(STR$(PLANTERS), "#,###")
  85.     PRINT "The city owns "; FORMAT$(STR$(ACRES), "#,###"); " acres, "
  86.     PRINT "You havested "; FORMAT$(STR$(PRICE), "#,###"); " bushels per acre"
  87.     PRINT "Rats destroyed "; FORMAT$(STR$(RATS_ATE), "#,###"); " bushels. "
  88.     PRINT "Insects destroyed "; FORMAT$(STR$(PESTILENCE), "#,###"); " bushels."
  89.     PRINT "You have "; FORMAT$(STR$(BUSHELS), "#,###"); " bushels in storage."
  90.     PRINT
  91.     IF YEAR = 11 THEN GOTO PlayEvaluation
  92.     C = INT(10 * RND(1))
  93.     PRICE = C + 17
  94.     PRINT "Land is trading at "; FORMAT$(STR$(PRICE), "#,###"); " bushels per acre."
  95.  
  96. BuyLand:
  97.     INPUT "How much land (in acres) do you wish to buy "; ACRES_BUY
  98.     IF ACRES_BUY < 0 THEN GOTO FedUp
  99.     IF PRICE * ACRES_BUY <= BUSHELS THEN
  100.         IF ACRES_BUY = 0 THEN GOTO SellLand
  101.         ACRES = ACRES + ACRES_BUY
  102.         BUSHELS = BUSHELS - PRICE * ACRES_BUY
  103.         C = 0
  104.         GOTO FeedPopulation
  105.     END IF
  106.     GOSUB NotEnoughGrain
  107.     GOTO BuyLand
  108.  
  109. SellLand:
  110.     INPUT "How many acres of land do you wish to sell "; ACRES_SELL
  111.     IF ACRES_SELL < 0 THEN GOTO FedUp
  112.     IF ACRES_SELL < ACRES THEN
  113.         ACRES = ACRES - ACRES_SELL
  114.         BUSHELS = BUSHELS + PRICE * ACRES_SELL
  115.         C = 0
  116.         GOTO FeedPopulation
  117.     END IF
  118.     GOSUB NotEnoughAcres
  119.     GOTO SellLand
  120.  
  121. FeedPopulation:
  122.     INPUT "How many bushels do you wish to set aside for food "; BUSHELS_FEED
  123.     IF BUSHELS_FEED < 0 THEN GOTO FedUp
  124.     IF BUSHELS_FEED = 0 THEN
  125.         GOSUB NotEnoughGrain
  126.         GOTO FeedPopulation
  127.     END IF
  128. ' *** TRYING TO USE MORE GRAIN THAN IS IN SILOS?
  129.     IF BUSHELS_FEED <= BUSHELS THEN
  130.         BUSHELS = BUSHELS - BUSHELS_FEED
  131.         C = 1
  132.         GOTO AcresToPlant
  133.     END IF
  134.     GOSUB NotEnoughGrain
  135.     GOTO FeedPopulation
  136.  
  137. AcresToPlant:
  138.     INPUT "How many acres do you wish to plant "; ACRES_PLANTED
  139. ' *** TRYING TO PLANT MORE ACRES THAN YOU OWN?
  140.     IF ACRES_PLANTED = 0 THEN GOTO HarvestCrops
  141.     IF ACRES_PLANTED < 0 THEN GOTO FedUp
  142. ' *** ENOUGH GRAIN FOR SEED (TWO BUSHELS PER ACRE)?
  143.     IF ACRES_PLANTED <= ACRES THEN
  144.         IF INT(ACRES_PLANTED / 2) <= BUSHELS THEN
  145. ' *** ENOUGH PEOPLE TO TEND THE CROPS?
  146.             IF ACRES_PLANTED < 10 * PLANTERS + 1 THEN
  147.                 BUSHELS = BUSHELS - INT(ACRES_PLANTED / 2)
  148.                 GOTO HarvestCrops
  149.             ELSE
  150.                 PRINT "But you only have "; FORMAT$(STR$(PLANTERS), "#,###"); " people to tend the fields!, Now then, "
  151.                 GOTO AcresToPlant
  152.             END IF
  153.         ELSE
  154.             GOSUB NotEnoughGrain
  155.             GOTO AcresToPlant
  156.         END IF
  157.     END IF
  158.     GOSUB NotEnoughAcres
  159.     GOTO AcresToPlant
  160.  
  161. HarvestCrops:
  162. ' *** A BOUNTIFUL HARVEST!
  163.     GOSUB Randomizer
  164.     PRICE = C
  165.     HARVESTED = ACRES_PLANTED * PRICE
  166.  
  167. ' *** Provides a 50-50 chance of no damage due to Rats and Insects
  168.     GOSUB Randomizer
  169.     IF C MOD 2 = 0 THEN
  170.         BUSHELS = BUSHELS + HARVESTED
  171.         GOTO PopulationControl
  172.     END IF
  173.  
  174. ' *** Rats eat the existing store of Bushels, before the harvest is added
  175.     RATS_ATE = 0
  176.     RATS_ATE = INT(BUSHELS / C)
  177.  
  178. ' *** Insects eat at the crops in the field, and reduce the harvest, and
  179. ' *** can sometimes wipe out an entire year's harvest!
  180.     GOSUB Randomizer
  181.     PESTILENCE = 0
  182.     INSECTS_PCT = (10 * RND(1))
  183.     IF INSECTS_PCT >= 6 THEN PESTILENCE = INT(HARVESTED / C)
  184.  
  185.     BUSHELS = BUSHELS + HARVESTED - (RATS_ATE + PESTILENCE)
  186.     IF BUSHELS < 0 THEN BUSHELS = 0
  187.  
  188. PopulationControl:
  189. ' *** Determine births and those who moved to the city
  190.  
  191. ' *** LET'S HAVE SOME BABIES (Change to a random-generated number from 0-20)
  192. '   NEWBORN = INT(C * (20 * ACRES + BUSHELS) / POPULATION / 100 + 1)
  193. '    GOSUB Randomizer
  194.     NEWBORN = INT(10 * RND(1)) ' *** No more than 10 newborns in a year
  195.  
  196. ' *** LET'S HAVE SOME IMMIGRATION
  197.     GOSUB Randomizer
  198.     IMMIGRATED = INT(C * (20 * ACRES + BUSHELS) / POPULATION / 100 + 1)
  199.  
  200. ' *** HOW MANY PEOPLE HAD FULL TUMMIES?
  201.     C = INT(BUSHELS_FEED / 20)
  202.     IF POPULATION < C THEN
  203.         STARVED = 0
  204.         GOTO PlayGame
  205.     END IF
  206.  
  207. ' *** STARVED ENOUGH FOR IMPEACHMENT (Greater than 45% of population)?
  208.     STARVED = POPULATION - C
  209.     IF STARVED > .45 * POPULATION THEN GOTO StarvedMSG
  210.     PCT_STARVED = ((YEAR - 1) * PCT_STARVED + STARVED * 100 / POPULATION) / YEAR
  211.     POPULATION = C
  212.     PEOPLE_DIED = PEOPLE_DIED + STARVED '*** D1=D1+D
  213.     GOTO PlayGame
  214.  
  215. ' ***
  216. ' *** Game processing routines
  217. ' ***
  218.  
  219. StarvedMSG:
  220.     PRINT
  221.     PRINT "You starved "; FORMAT$(STR$(STARVED), "###"); " people in this year!!!"
  222.  
  223. ExtremeMismangement:
  224.     PRINT "Due to extreme mismanagement you have been impeached and thrown out of office."
  225.     PRINT "You have failed to honor your promise or lacked courage or commitment."
  226.     PRINT "The people have declared you a National Fink!!!!"
  227.     GOTO endProg
  228.  
  229. FedUp:
  230.     PRINT
  231.     PRINT "HAMURABI: I cannot do what you wish."
  232.     PRINT "Get yourself another steward!!!!!"
  233.     GOTO endProg
  234.  
  235. PlayEvaluation:
  236.     PRINT "In your 10-year term of office, "; FORMAT$(STR$(PCT_STARVED), "##.##");
  237.     PRINT " percent of the population"
  238.     PRINT "starved per year on average,";
  239.     PRINT " or a total of "; FORMAT$(STR$(PEOPLE_DIED), "###");
  240.     PRINT " people died!!"
  241.     PRINT
  242.  
  243. DeterminePlay:
  244.     LAND_PER_PERSON = ACRES / POPULATION
  245.     PRINT "You started with 10 acres per person and ended with "; FORMAT$(STR$(LAND_PER_PERSON), "##.##");
  246.     PRINT " arces per person."
  247.     PRINT
  248.     IF PCT_STARVED > 33 THEN GOTO ExtremeMismangement
  249.     IF LAND_PER_PERSON < 7 THEN GOTO ExtremeMismangement
  250.     IF PCT_STARVED > 10 THEN GOTO HeavyHanded
  251.     IF LAND_PER_PERSON < 9 THEN GOTO HeavyHanded
  252.     IF PCT_STARVED > 3 THEN GOTO MediocurePlay
  253.     IF LAND_PER_PERSON < 10 THEN GOTO MediocurePlay
  254.     PRINT "A fantastic performance! Charlemange, Disraeli, and"
  255.     PRINT "Jefferson combined could not have done better!"
  256.     GOTO endProg
  257.  
  258. HeavyHanded:
  259.     PRINT "Your heavy-handed performance smacks of Nero and Ivan IV."
  260.     PRINT "The remaining people find you an unpleasant ruler, and,"
  261.     PRINT "frankly, hate your guts!!"
  262.     GOTO endProg
  263.  
  264. MediocurePlay:
  265.     PRINT "Your performance could have been somewhat better, but"
  266.     PRINT "really wasn't too bad at all. "; INT(POPULATION * .8 * RND(1)); " people"
  267.     PRINT "would dearly like to see you assassinated but we all have our"
  268.     PRINT "trivial problems."
  269.     GOTO endProg
  270.  
  271. NotEnoughGrain:
  272.     PRINT " HAMURABI: Think again. You have only"
  273.     PRINT BUSHELS; " bushels of grain. Now then,"
  274.     RETURN
  275.  
  276. NotEnoughAcres:
  277.     PRINT "HAMURABI: Think again. You own only "; ACRES; " acres. Now Then,"
  278.     RETURN
  279.  
  280. Randomizer:
  281.     C = INT(RND(1) * 5) + 1
  282.     RETURN
  283.  
  284. endProg:
  285.     PRINT
  286.     FOR N = 1 TO 10
  287.         PRINT CHR$(7);
  288.     NEXT N
  289.     PRINT "So long, for now."
  290.     PRINT
  291.     END
  292.    
  293. FUNCTION FORMAT$ (text AS STRING, template AS STRING)
  294. '-----------------------------------------------------------------------------
  295. ' *** Return a formatted string to a variable
  296. '
  297.     d = _DEST: s = _SOURCE
  298.     n = _NEWIMAGE(80, 80, 0)
  299.     _DEST n: _SOURCE n
  300.     PRINT USING template; VAL(text)
  301.     FOR i = 1 TO 79
  302.         t$ = t$ + CHR$(SCREEN(1, i))
  303.     NEXT
  304.     IF LEFT$(t$, 1) = "%" THEN t$ = MID$(t$, 2)
  305.     FORMAT$ = _TRIM$(t$)
  306.     _DEST d: _SOURCE s
  307.     _FREEIMAGE n
  308.  
 

5
InForm-based programs / EBAC Calculator
« on: October 14, 2021, 04:36:45 pm »
This is a rework of a post I made a few months ago.

I converted my EBAC Calculator from Zenity to now use InForm, and uses many of it's features.

I've included all the files needed to compile it, and have tested it on Linux and MAC OSX. It should also run on Windows (I don't have a Windows OS installed).

Below is the main program for those who want to look at it, but you will need the files/directories in the .ZIP file if you want to compile it. You do not need InForm to compile and use the program. Just the files provided.

Here's the main source:
Code: QB64: [Select]
  1. REM $TITLE: ebacCalculator.bas Version 1.0  04/01/2021 - Last Update: 10/14/2021
  2. _TITLE "ebacCalculator.bas"
  3. ' ebacCalculator.bas    Version 2.0  10/14/2021
  4. '-----------------------------------------------------------------------------------
  5. '       PROGRAM: ebacCalculator.bas
  6. '        AUTHOR: George McGinn
  7. '
  8. '  DATE WRITTEN: 04/01/2021
  9. '       VERSION: 2.0
  10. '       PROJECT: Estimated Blood-Alcohol Content Calculator
  11. '
  12. '   DESCRIPTION: Program shows many of the functions of using InForm while using
  13. '                most of the original code from the Zenity project. This can now
  14. '                run on all systems (Linux, MAC and Windows).
  15. '
  16. ' Written by George McGinn
  17. ' Copyright (C)2021 by George McGinn - All Rights Reserved
  18. ' Version 1.0 - Created 04/01/2021
  19. ' Version 2.0 - Created 10/14/2021
  20. '
  21. ' CHANGE LOG
  22. '-----------------------------------------------------------------------------------
  23. ' 04/01/2021 v1.0  GJM - New Program (TechBASIC and C++ Versions).
  24. ' 06/19/2021 v1.5  GJM - Updated to use Zenity and SHELL commands to run on Linux with
  25. '                        a simple GUI.
  26. ' 10/14/2021 v2.0  GJM - Updated to use InForm GUI in place of Zenity an SHELL commands.
  27. '                        Can now run on any OS
  28. '-----------------------------------------------------------------------------------
  29. '  Copyright (C)2021 by George McGinn.  All Rights Reserved.
  30. '
  31. ' untitled.bas by George McGinn is licensed under a Creative Commons
  32. ' Attribution-NonCommercial 4.0 International. (CC BY-NC 4.0)
  33. '
  34. ' Full License Link: https://creativecommons.org/licenses/by-nc/4.0/legalcode
  35. '
  36. '-----------------------------------------------------------------------------------
  37. ' PROGRAM NOTES
  38. '
  39. ': This program uses
  40. ': InForm - GUI library for QB64 - v1.3
  41. ': Fellippe Heitor, 2016-2021 - fellippe@qb64.org - [member=2]FellippeHeitor[/member]
  42. ': https://github.com/FellippeHeitor/InForm
  43. '-----------------------------------------------------------------------------------
  44.  
  45. ': Controls' IDs: ------------------------------------------------------------------
  46. DIM SHARED maleRB AS LONG
  47. DIM SHARED femaleRB AS LONG
  48. DIM SHARED AgreeCB AS LONG
  49. DIM SHARED AGREEBT AS LONG
  50. DIM SHARED ebacFRM AS LONG
  51. DIM SHARED weightLB AS LONG
  52. DIM SHARED nbrdrinksLB AS LONG
  53. DIM SHARED timeLB AS LONG
  54. DIM SHARED EnterInformationLB AS LONG
  55. DIM SHARED WeightTB AS LONG
  56. DIM SHARED nbrDrinksTB AS LONG
  57. DIM SHARED TimeTB AS LONG
  58. DIM SHARED CancelBT AS LONG
  59. DIM SHARED HELPBT AS LONG
  60. DIM SHARED QUITBT AS LONG
  61. DIM SHARED displayResults AS LONG
  62. DIM SHARED informationLB AS LONG
  63.  
  64. ': User-defined Variables: ---------------------------------------------------------
  65. DIM SHARED AS STRING HELPFile
  66. DIM SHARED AS INTEGER l, SOBER, legalToDrive
  67. DIM SHARED AS SINGLE B, OZ, Wt, EBAC
  68. DIM SHARED numeric(255)
  69.  
  70. DIM SHARED AS STRING helpcontents, prt_text
  71.  
  72.  
  73.  
  74. ': External modules: ---------------------------------------------------------------
  75. '$INCLUDE:'InForm/InForm.bi'
  76. '$INCLUDE:'InForm/xp.uitheme'
  77. '$INCLUDE:'ebacCalculator.frm'
  78.  
  79.  
  80.  
  81. ': Event procedures: ---------------------------------------------------------------
  82. SUB __UI_BeforeInit
  83.  
  84.  
  85. SUB __UI_OnLoad
  86.  
  87. ' *** Initialize Variables
  88.     A = 0
  89.     Wt = 0
  90.     B = .0
  91.     T = 0: St = 0
  92.     I = 0
  93.     Bdl = 1.055
  94.     OZ = .5
  95.     SOBER = False: legalToDrive = False
  96.     HELPFile = "EBACHelp.txt"
  97.     displayDisclaimer
  98.  
  99.  
  100. SUB __UI_BeforeUpdateDisplay
  101.     'This event occurs at approximately 60 frames per second.
  102.     'You can change the update frequency by calling SetFrameRate DesiredRate%
  103.  
  104.  
  105. SUB __UI_BeforeUnload
  106.     'If you set __UI_UnloadSignal = False here you can
  107.     'cancel the user's request to close.
  108.  
  109.  
  110. SUB __UI_Click (id AS LONG)
  111.     SELECT CASE id
  112.         CASE maleRB
  113.             Sex = "M"
  114.  
  115.         CASE femaleRB
  116.             Sex = "F"
  117.  
  118.         CASE AGREEBT
  119.             Answer = MessageBox("Do you want to perform another calculation?             ", "", MsgBox_YesNo + MsgBox_Question)
  120.             IF Answer = MsgBox_Yes THEN
  121.                 Control(AgreeCB).Value = False
  122.                 Control(AGREEBT).Disabled = True
  123.             ELSE
  124.                 Answer = MessageBox("Thank You for using EBAC Calculator. Please Don't Drink and Drive.", "", MsgBox_Ok + MsgBox_Information)
  125.                SYSTEM
  126.             END IF
  127.  
  128.         CASE CancelBT
  129.             ResetForm
  130.  
  131.         CASE OKBT
  132.             IF Control(maleRB).Value = False AND Control(femaleRB).Value = False THEN
  133.                 Answer = MessageBox("Invalid: You must select either M (male) or F (female). Please Correct.", "", MsgBox_Ok + MsgBox_Information)
  134.                 EXIT SUB
  135.             END IF
  136.             A = Control(nbrDrinksTB).Value
  137.             Wt = Control(WeightTB).Value
  138.             T = Control(TimeTB).Value
  139.             calcEBAC
  140.             Control(QUITBT).Disabled = True
  141.             ResetList displayResults
  142.             Text(displayResults) = prt_text
  143.  
  144.         CASE HELPBT
  145.             ResetList displayResults
  146.             IF _FILEEXISTS(HELPFile) THEN
  147.                 DIM fh AS LONG
  148.                 fh = FREEFILE
  149.                 OPEN HELPFile FOR INPUT AS #fh
  150.                 DO UNTIL EOF(fh)
  151.                     LINE INPUT #fh, helpcontents
  152.                     AddItem displayResults, helpcontents
  153.                 LOOP
  154.                 CLOSE #fh
  155.                 Control(displayResults).LastVisibleItem = 0
  156.             ELSE
  157.                 Answer = MessageBox("HELP File " + HELPFile$ + " Not Found                             ", "", MsgBox_Ok + MsgBox_Question)
  158.                 SYSTEM 1
  159.             END IF
  160.  
  161.         CASE QUITBT
  162.             Answer = MessageBox("Are you sure you want to QUIT?                     ", "", MsgBox_YesNo + MsgBox_Question)
  163.             IF Answer = MsgBox_Yes THEN
  164.                 Answer = MessageBox("Thank You for using EBAC Calculator. Please Don't Drink and Drive.", "", MsgBox_Ok + MsgBox_Information)
  165.                 SYSTEM
  166.             END IF
  167.  
  168.     END SELECT
  169.  
  170. SUB __UI_MouseEnter (id AS LONG)
  171.  
  172. SUB __UI_MouseLeave (id AS LONG)
  173.  
  174. SUB __UI_FocusIn (id AS LONG)
  175.  
  176. SUB __UI_FocusOut (id AS LONG)
  177.     'This event occurs right before a control loses focus.
  178.     'To prevent a control from losing focus, set __UI_KeepFocus = True below.
  179.  
  180. SUB __UI_MouseDown (id AS LONG)
  181.  
  182. SUB __UI_MouseUp (id AS LONG)
  183.  
  184. SUB __UI_KeyPress (id AS LONG)
  185.     'When this event is fired, __UI_KeyHit will contain the code of the key hit.
  186.     'You can change it and even cancel it by making it = 0
  187.  
  188. SUB __UI_TextChanged (id AS LONG)
  189.     SELECT CASE id
  190.  
  191.         CASE WeightTB
  192.             Control(AgreeCB).Value = False
  193.             Control(AGREEBT).Disabled = True
  194.  
  195.         CASE nbrDrinksTB
  196.             Control(AgreeCB).Value = False
  197.             Control(AGREEBT).Disabled = True
  198.  
  199.         CASE TimeTB
  200.             Control(AgreeCB).Value = False
  201.             Control(AGREEBT).Disabled = True
  202.  
  203.     END SELECT
  204.  
  205. SUB __UI_ValueChanged (id AS LONG)
  206.     SELECT CASE id
  207.  
  208.         CASE maleRB
  209.             Control(AgreeCB).Value = False
  210.             Control(AGREEBT).Disabled = True
  211.  
  212.         CASE femaleRB
  213.             Control(AgreeCB).Value = False
  214.             Control(AGREEBT).Disabled = True
  215.  
  216.         CASE AgreeCB
  217.             IF Control(AgreeCB).Value = True THEN
  218.                 Control(AGREEBT).Disabled = False
  219.                 Control(QUITBT).Disabled = False
  220.             ELSE
  221.                 Control(AGREEBT).Disabled = True
  222.                 Control(QUITBT).Disabled = True
  223.             END IF
  224.  
  225.     END SELECT
  226.  
  227. SUB __UI_FormResized
  228.  
  229. '$INCLUDE:'InForm/InForm.ui'
  230.  
  231.  
  232. ': User FUNCTIONS/SUBROUTINES: ---------------------------------------------------------------
  233.  
  234. SUB displayDisclaimer
  235.  
  236. '    prt_text = "*** DISCLAIMER ***" + CHR$(10)
  237.     prt_text = "Unless otherwise separately undertaken by the Licensor, to the extent" + CHR$(10)
  238.     prt_text = prt_text + "possible, the Licensor offers the Licensed Material as-is and" + CHR$(10)
  239.     prt_text = prt_text + "as-available, and makes no representations or warranties of any kind" + CHR$(10)
  240.     prt_text = prt_text + "concerning the Licensed Material, whether express, implied, statutory," + CHR$(10)
  241.     prt_text = prt_text + "or other. This includes, without limitation, warranties of title," + CHR$(10)
  242.     prt_text = prt_text + "merchantability, fitness for a particular purpose, non-infringement," + CHR$(10)
  243.     prt_text = prt_text + "absence of latent or other defects, accuracy, or the presence or absence" + CHR$(10)
  244.     prt_text = prt_text + "of errors, whether or not known or discoverable. Where disclaimers of" + CHR$(10)
  245.     prt_text = prt_text + "warranties are not allowed in full or in part, this disclaimer may not" + CHR$(10)
  246.     prt_text = prt_text + "apply to You." + CHR$(10) + CHR$(10)
  247.  
  248.     prt_text = prt_text + "To the extent possible, in no event will the Licensor be liable to You" + CHR$(10)
  249.     prt_text = prt_text + "on any legal theory (including, without limitation, negligence) or" + CHR$(10)
  250.     prt_text = prt_text + "otherwise for any direct, special, indirect, incidental, consequential," + CHR$(10)
  251.     prt_text = prt_text + "punitive, exemplary, or other losses, costs, expenses, or damages" + CHR$(10)
  252.     prt_text = prt_text + "arising out of this Public License or use of the Licensed Material, even" + CHR$(10)
  253.     prt_text = prt_text + "if the Licensor has been advised of the possibility of such losses," + CHR$(10)
  254.     prt_text = prt_text + "costs, expenses, or damages. Where a limitation of liability is not" + CHR$(10)
  255.     prt_text = prt_text + "allowed in full or in part, this limitation may not apply to You." + CHR$(10) + CHR$(10)
  256.  
  257.     prt_text = prt_text + "The disclaimer of warranties and limitation of liability provided above" + CHR$(10)
  258.     prt_text = prt_text + "shall be interpreted in a manner that, to the extent possible, most" + CHR$(10)
  259.     prt_text = prt_text + "closely approximates an absolute disclaimer and waiver of all liability." + CHR$(10)
  260.  
  261.     Answer = MessageBox(prt_text, "*** DISCLAIMER ***", MsgBox_YesNo + MsgBox_Question)
  262.     IF Answer = MsgBox_No THEN
  263.         Answer = MessageBox("Sorry you don't agree. Please Don't Drink and Drive.", "", MsgBox_Ok + MsgBox_Information)
  264.         SYSTEM
  265.     END IF
  266.  
  267.  
  268.  
  269. SUB ResetForm
  270.     Control(nbrDrinksTB).Value = 0
  271.     Control(WeightTB).Value = 0
  272.     Control(TimeTB).Value = 0
  273.     Control(AgreeCB).Value = False
  274.     Control(AGREEBT).Disabled = True
  275.     Control(maleRB).Value = False
  276.     Control(femaleRB).Value = False
  277.     ResetList displayResults
  278.     Sex = ""
  279.  
  280.  
  281. SUB calcEBAC
  282. '-------------------------------------------------------------
  283. ' *** Convert Drinks into Fluid Ounces of EtOH (Pure Alcohol).
  284. ' *** A is number of drinks. 1 drink is about .6 FLoz of alcohol
  285.     FLoz = A * OZ
  286.     legalToDrive = False
  287.  
  288. '-----------------------------------------------------
  289. ' *** Set/calculate EBAC values based on Sex
  290.     SELECT CASE Sex
  291.         CASE "M"
  292.             B = .017
  293.             EBAC = 7.97 * FLoz / Wt - B * T
  294.         CASE "F"
  295.             B = .019
  296.             EBAC = 9.86 * FLoz / Wt - B * T
  297.     END SELECT
  298.  
  299.     IF EBAC < 0 THEN EBAC = 0
  300.  
  301. '----------------------------------------------------------------------------------------------
  302. ' *** Populate the EBAC string with the EBAC value formatted to 3 decimal places for FORM output
  303.     prt_text = "ESTIMATED BLOOD ALCOHOL CONTENT (EBAC) in g/dL = " + strFormat$(STR$(EBAC), "###.###") + CHR$(10) + CHR$(10)
  304.  
  305.  
  306. '-----------------------------------------------------------------------------------------
  307. ' *** Based on EBAC range values, populate the FORM output string with the approriate text
  308.     SELECT CASE EBAC
  309.         CASE .500 TO 100.9999
  310.             prt_text = prt_text + "*** ALERT: CALL AN AMBULANCE, DEATH LIKELY" + CHR$(10)
  311.             prt_text = prt_text + "Unconsious/coma, unresponsive, high likelihood of death. It is illegal" + CHR$(10) + _
  312.                                   "to operate a motor vehicle at this level of intoxication in all states." + CHR$(10)
  313.         CASE .400 TO .4999
  314.             prt_text = prt_text + "*** ALERT: CALL AN AMBULANCE, DEATH POSSIBLE" + CHR$(10)
  315.             prt_text = prt_text + "Onset of coma, and possible death due to respiratory arrest. It is illegal" + CHR$(10) + _
  316.                                   "to operate a motor vehicle at this level of intoxication in all states." + CHR$(10)
  317.         CASE .350 TO .3999
  318.             prt_text = prt_text + "*** ALERT: CALL AN AMBULANCE, SEVERE ALCOHOL POISONING" + CHR$(10)
  319.             prt_text = prt_text + " Coma is possible. This is the level of surgical anesthesia. It is illegal" + CHR$(10) + _
  320.                                   "to operate a motor vehicle at this level of intoxication in all states." + CHR$(10)
  321.         CASE .300 TO .3499
  322.             prt_text = prt_text + "*** ALERT: YOU ARE IN A DRUNKEN STUP0R, AT RISK TO PASSING OUT" + CHR$(10)
  323.             prt_text = prt_text + "STUPOR. You have little comprehension of where you are. You may pass out" + CHR$(10) + _
  324.                                   "suddenly and be difficult to awaken. It is illegal to operate a motor" + CHR$(10) + _
  325.                                   "vehicle at this level of intoxication in all states." + CHR$(10)
  326.         CASE .250 TO .2999
  327.             prt_text = prt_text + "*** ALERT: SEVERLY IMPAIRED - DRUNK ENOUGH TO CAUSE SEVERE INJURY/DEATH TO SELF" + CHR$(10)
  328.             prt_text = prt_text + "All mental, physical and sensory functions are severely impaired." + CHR$(10) + _
  329.                                   "Increased risk of asphyxiation from choking on vomit and of seriously injuring" + CHR$(10) + _
  330.                                   "yourself by falls or other accidents. It is illegal to operate a motor" + CHR$(10) + _
  331.                                   "vehicle at this level of intoxication in all states." + CHR$(10)
  332.         CASE .200 TO .2499
  333.             prt_text = prt_text + "YOU ARE EXTREMELY DRUNK" + CHR$(10)
  334.             prt_text = prt_text + "Feeling dazed/confused or otherwise disoriented. May need help to" + CHR$(10) + _
  335.                                   "stand/walk. If you injure yourself you may not feel the pain. Some" + CHR$(10) + _
  336.                                   "people have nausea and vomiting at this level. The gag reflex" + CHR$(10) + _
  337.                                   "is impaired and you can choke if you do vomit. Blackouts are likely" + CHR$(10) + _
  338.                                   "at this level so you may not remember what has happened. It is illegal" + CHR$(10) + _
  339.                                   "to operate a motor vehicle at this level of intoxication in all states." + CHR$(10)
  340.         CASE .160 TO .1999
  341.             prt_text = prt_text + "YOUR ARE SEVERLY DRUNK - ENOUGH TO BECOME VERY SICK" + CHR$(10)
  342.             prt_text = prt_text + "Dysphoria* predominates, nausea may appear. The drinker has the appearance" + CHR$(10) + _
  343.                                   "of a 'sloppy drunk.' It is illegal to operate a motor vehicle at this level" + CHR$(10) + _
  344.                                   "of intoxication in all states." + CHR$(10) + CHR$(10) + _
  345.                                   "* Dysphoria: An emotional state of anxiety, depression, or unease." + CHR$(10)
  346.         CASE .130 TO .1599
  347.             prt_text = prt_text + "YOU ARE VERY DRUNK - ENOUGH TO LOSE PHYSICAL & MENTAL CONTROL" + CHR$(10)
  348.             prt_text = prt_text + "Gross motor impairment and lack of physical control. Blurred vision and major" + CHR$(10) + _
  349.                                   "loss of balance. Euphoria is reduced and dysphoria* is beginning to appear." + CHR$(10) + _
  350.                                   "Judgment and perception are severely impaired. It is illegal to operate a " + CHR$(10) + _
  351.                                   "motor vehicle at this level of intoxication in all states." + CHR$(10) + CHR$(10)
  352.             prt_text = prt_text + "* Dysphoria: An emotional state of anxiety, depression, or unease." + CHR$(10)
  353.         CASE .100 TO .1299
  354.             prt_text = prt_text + "YOU ARE LEGALLY DRUNK" + CHR$(10)
  355.             prt_text = prt_text + "Significant impairment of motor coordination and loss of good judgment." + CHR$(10) + _
  356.                                   "Speech may be slurred; balance, vision, reaction time and hearing will be" + CHR$(10) + _
  357.                                   "impaired. Euphoria. It is illegal to operate a motor vehicle at this level" + CHR$(10) + _
  358.                                   "of intoxication in all states." + CHR$(10)
  359.         CASE .070 TO .0999
  360.             prt_text = prt_text + "YOU MAY BE LEGALLY DRUNK" + CHR$(10)
  361.             prt_text = prt_text + "Slight impairment of balance, speech, vision, reaction time, and hearing." + CHR$(10) + _
  362.                                   "Euphoria. Judgment and self-control are reduced, and caution, reason and" + CHR$(10) + _
  363.                                   "memory are impaired (in some* states .08 is legally impaired and it is illegal" + CHR$(10) + _
  364.                                   "to drive at this level). You will probably believe that you are functioning" + CHR$(10) + _
  365.                                   "better than you really are." + CHR$(10) + CHR$(10)
  366.             prt_text = prt_text + "(*** As of July, 2004 ALL states had passed .08 BAC Per Se Laws. The final" + CHR$(10) + _
  367.                                   "one took effect in August of 2005.)" + CHR$(10)
  368.         CASE .040 TO .0699
  369.             prt_text = prt_text + "YOU MAY BE LEGALLY BUZZED" + CHR$(10)
  370.             prt_text = prt_text + "Feeling of well-being, relaxation, lower inhibitions, sensation of warmth." + CHR$(10) + _
  371.                                   "Euphoria. Some minor impairment of reasoning and memory, lowering of caution." + CHR$(10) + _
  372.                                   "Your behavior may become exaggerated and emotions intensified (Good emotions" + CHR$(10) + _
  373.                                   "are better, bad emotions are worse)" + CHR$(10)
  374.         CASE .020 TO .0399
  375.             prt_text = prt_text + "YOU MAY BE OK TO DRIVE, BUT IMPAIRMENT BEGINS" + CHR$(10)
  376.             prt_text = prt_text + "No loss of coordination, slight euphoria and loss of shyness. Depressant effects" + CHR$(10) + _
  377.                                   "are not apparent. Mildly relaxed and maybe a little lightheaded." + CHR$(10)
  378.         CASE .000 TO .0199
  379.             prt_text = prt_text + "YOU ARE OK TO DRIVE" + CHR$(10)
  380.     END SELECT
  381.  
  382. '-----------------------------------------------------------
  383. '*** Determine if Drunk (>.08 EBAC) and calculate:
  384. '***    - When user will be less than .08
  385. '***    - How long it will take to become completely sober
  386.     IF EBAC > .08 THEN
  387.         SOBER = False
  388.         CEBAC = EBAC
  389.         st = T
  390.         DO UNTIL SOBER = True
  391.             T = T + 1
  392.             IF CEBAC > .0799 THEN I = I + 1
  393.  
  394.             SELECT CASE Sex
  395.                 CASE "M"
  396.                     B = .017
  397.                     CEBAC = 7.97 * FLoz / Wt - B * T
  398.                 CASE "F"
  399.                     B = .019
  400.                     CEBAC = 9.86 * FLoz / Wt - B * T
  401.             END SELECT
  402.  
  403.             IF legalToDrive = False THEN
  404.                 IF CEBAC < .08 THEN
  405.                     prt_text = prt_text + CHR$(10) + CHR$(10) + "It will take about " + strFormat$(STR$(I), "##") + " hours from your last drink to be able to drive." + CHR$(10)
  406.                     legalToDrive = True
  407.                 END IF
  408.             END IF
  409.  
  410.             IF CEBAC <= 0 THEN
  411.                 prt_text = prt_text + "It will take about " + strFormat$(STR$(T - st), "##") + " hours from your last drink to be completely sober."
  412.                 SOBER = True
  413.             END IF
  414.         LOOP
  415.     END IF
  416.  
  417.  
  418.  
  419. FUNCTION strFormat$ (text AS STRING, template AS STRING)
  420. '-----------------------------------------------------------------------------
  421. ' *** Return a formatted string to a variable
  422. '
  423.     d = _DEST: s = _SOURCE
  424.     n = _NEWIMAGE(80, 80, 0)
  425.     _DEST n: _SOURCE n
  426.     PRINT USING template; VAL(text)
  427.     FOR i = 1 TO 79
  428.         t$ = t$ + CHR$(SCREEN(1, i))
  429.     NEXT
  430.     IF LEFT$(t$, 1) = "%" THEN t$ = MID$(t$, 2)
  431.     strFormat$ = _TRIM$(t$)
  432.     _DEST d: _SOURCE s
  433.     _FREEIMAGE n
  434.  
  435.  

And the Form file:
Code: QB64: [Select]
  1. ': This form was generated by
  2. ': InForm - GUI library for QB64 - v1.3
  3. ': Fellippe Heitor, 2016-2021 - fellippe@qb64.org - [member=2]FellippeHeitor[/member]
  4. ': https://github.com/FellippeHeitor/InForm
  5. '-----------------------------------------------------------
  6. SUB __UI_LoadForm
  7.  
  8.     DIM __UI_NewID AS LONG, __UI_RegisterResult AS LONG
  9.  
  10.     __UI_NewID = __UI_NewControl(__UI_Type_Form, "ebacFRM", 618, 630, 0, 0, 0)
  11.     __UI_RegisterResult = 0
  12.     SetCaption __UI_NewID, "EBAC - ESTIMATED BLOOD ALCOHOL CONTENT CALCULATOR"
  13.     Control(__UI_NewID).Font = SetFont("Fonts/arial.ttf", 16)
  14.     Control(__UI_NewID).HasBorder = False
  15.  
  16.     __UI_NewID = __UI_NewControl(__UI_Type_Label, "SexLB", 40, 26, 232, 64, 0)
  17.     __UI_RegisterResult = 0
  18.     SetCaption __UI_NewID, "Sex:"
  19.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 14)
  20.     Control(__UI_NewID).HasBorder = False
  21.     Control(__UI_NewID).VAlign = __UI_Middle
  22.  
  23.     __UI_NewID = __UI_NewControl(__UI_Type_Label, "weightLB", 99, 25, 173, 91, 0)
  24.     __UI_RegisterResult = 0
  25.     SetCaption __UI_NewID, "Weight (lbs):"
  26.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 14)
  27.     Control(__UI_NewID).HasBorder = False
  28.     Control(__UI_NewID).VAlign = __UI_Middle
  29.  
  30.     __UI_NewID = __UI_NewControl(__UI_Type_Label, "nbrdrinksLB", 138, 25, 134, 121, 0)
  31.     __UI_RegisterResult = 0
  32.     SetCaption __UI_NewID, "Number of drinks:"
  33.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 14)
  34.     Control(__UI_NewID).HasBorder = False
  35.     Control(__UI_NewID).VAlign = __UI_Middle
  36.  
  37.     __UI_NewID = __UI_NewControl(__UI_Type_Label, "timeLB", 202, 25, 70, 151, 0)
  38.     __UI_RegisterResult = 0
  39.     SetCaption __UI_NewID, "Time (hrs) from first drink:"
  40.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 14)
  41.     Control(__UI_NewID).HasBorder = False
  42.     Control(__UI_NewID).VAlign = __UI_Middle
  43.  
  44.     __UI_NewID = __UI_NewControl(__UI_Type_Label, "EnterInformationLB", 440, 31, 16, 17, 0)
  45.     __UI_RegisterResult = 0
  46.     SetCaption __UI_NewID, "Enter information about your or your friend:"
  47.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 18)
  48.     Control(__UI_NewID).HasBorder = False
  49.     Control(__UI_NewID).VAlign = __UI_Middle
  50.  
  51.     __UI_NewID = __UI_NewControl(__UI_Type_TextBox, "WeightTB", 50, 23, 278, 92, 0)
  52.     __UI_RegisterResult = 0
  53.     Control(__UI_NewID).Font = SetFont("", 16)
  54.     Control(__UI_NewID).HasBorder = True
  55.     Control(__UI_NewID).Min = -32768
  56.     Control(__UI_NewID).Max = 32767
  57.     Control(__UI_NewID).CanHaveFocus = True
  58.     Control(__UI_NewID).BorderSize = 1
  59.     Control(__UI_NewID).NumericOnly = __UI_NumericWithBounds
  60.  
  61.     __UI_NewID = __UI_NewControl(__UI_Type_TextBox, "nbrDrinksTB", 50, 23, 278, 121, 0)
  62.     __UI_RegisterResult = 0
  63.     Control(__UI_NewID).Font = SetFont("", 16)
  64.     Control(__UI_NewID).HasBorder = True
  65.     Control(__UI_NewID).Min = -32768
  66.     Control(__UI_NewID).Max = 32767
  67.     Control(__UI_NewID).CanHaveFocus = True
  68.     Control(__UI_NewID).BorderSize = 1
  69.     Control(__UI_NewID).NumericOnly = __UI_NumericWithBounds
  70.  
  71.     __UI_NewID = __UI_NewControl(__UI_Type_TextBox, "TimeTB", 50, 25, 277, 151, 0)
  72.     __UI_RegisterResult = 0
  73.     Control(__UI_NewID).Font = SetFont("", 16)
  74.     Control(__UI_NewID).HasBorder = True
  75.     Control(__UI_NewID).Min = -32768
  76.     Control(__UI_NewID).Max = 32767
  77.     Control(__UI_NewID).CanHaveFocus = True
  78.     Control(__UI_NewID).BorderSize = 1
  79.     Control(__UI_NewID).NumericOnly = __UI_NumericWithBounds
  80.  
  81.     __UI_NewID = __UI_NewControl(__UI_Type_Button, "CancelBT", 99, 30, 435, 99, 0)
  82.     __UI_RegisterResult = 0
  83.     SetCaption __UI_NewID, "&Cancel"
  84.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 14)
  85.     Control(__UI_NewID).HasBorder = False
  86.     Control(__UI_NewID).CanHaveFocus = True
  87.  
  88.     __UI_NewID = __UI_NewControl(__UI_Type_Button, "OKBT", 99, 30, 435, 63, 0)
  89.     __UI_RegisterResult = 0
  90.     SetCaption __UI_NewID, "&OK"
  91.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 14)
  92.     Control(__UI_NewID).HasBorder = False
  93.     Control(__UI_NewID).CanHaveFocus = True
  94.  
  95.     __UI_NewID = __UI_NewControl(__UI_Type_Button, "HELPBT", 99, 30, 435, 134, 0)
  96.     __UI_RegisterResult = 0
  97.     SetCaption __UI_NewID, "&HELP"
  98.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 14)
  99.     Control(__UI_NewID).HasBorder = False
  100.     Control(__UI_NewID).CanHaveFocus = True
  101.  
  102.     __UI_NewID = __UI_NewControl(__UI_Type_Button, "QUITBT", 99, 30, 435, 170, 0)
  103.     __UI_RegisterResult = 0
  104.     SetCaption __UI_NewID, "&QUIT"
  105.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 14)
  106.     Control(__UI_NewID).HasBorder = False
  107.     Control(__UI_NewID).CanHaveFocus = True
  108.  
  109.     __UI_NewID = __UI_NewControl(__UI_Type_Label, "informationLB", 210, 17, 22, 194, 0)
  110.     __UI_RegisterResult = 0
  111.     SetCaption __UI_NewID, "Information Display"
  112.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 14)
  113.     Control(__UI_NewID).HasBorder = False
  114.     Control(__UI_NewID).VAlign = __UI_Middle
  115.     Control(__UI_NewID).BorderSize = 1
  116.  
  117.     __UI_NewID = __UI_NewControl(__UI_Type_ListBox, "displayResults", 576, 320, 20, 213, 0)
  118.     __UI_RegisterResult = 0
  119.     Control(__UI_NewID).Font = SetFont("Fonts/Courier New.ttf", 12)
  120.     Control(__UI_NewID).HasBorder = True
  121.     Control(__UI_NewID).CanHaveFocus = True
  122.     Control(__UI_NewID).BorderSize = 2
  123.  
  124.     __UI_NewID = __UI_NewControl(__UI_Type_Button, "AGREEBT", 99, 31, 495, 574, 0)
  125.     __UI_RegisterResult = 0
  126.     SetCaption __UI_NewID, "&AGREE"
  127.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 14)
  128.     Control(__UI_NewID).HasBorder = False
  129.     Control(__UI_NewID).CanHaveFocus = True
  130.     Control(__UI_NewID).Disabled = True
  131.  
  132.     __UI_NewID = __UI_NewControl(__UI_Type_CheckBox, "AgreeCB", 564, 23, 26, 544, 0)
  133.     __UI_RegisterResult = 0
  134.     SetCaption __UI_NewID, "I agree that this programand its results are not legally binding."
  135.     Control(__UI_NewID).HasBorder = False
  136.     Control(__UI_NewID).CanHaveFocus = True
  137.  
  138.     __UI_NewID = __UI_NewControl(__UI_Type_RadioButton, "maleRB", 40, 23, 277, 64, 0)
  139.     __UI_RegisterResult = 0
  140.     SetCaption __UI_NewID, "M"
  141.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 14)
  142.     Control(__UI_NewID).HasBorder = False
  143.     Control(__UI_NewID).CanHaveFocus = True
  144.  
  145.     __UI_NewID = __UI_NewControl(__UI_Type_RadioButton, "femaleRB", 40, 23, 322, 64, 0)
  146.     __UI_RegisterResult = 0
  147.     SetCaption __UI_NewID, "F"
  148.     Control(__UI_NewID).Font = SetFont("Fonts/Arial Black.ttf", 14)
  149.     Control(__UI_NewID).HasBorder = False
  150.     Control(__UI_NewID).CanHaveFocus = True
  151.  
  152.  
  153. SUB __UI_AssignIDs
  154.     ebacFRM = __UI_GetID("ebacFRM")
  155.     SexLB = __UI_GetID("SexLB")
  156.     weightLB = __UI_GetID("weightLB")
  157.     nbrdrinksLB = __UI_GetID("nbrdrinksLB")
  158.     timeLB = __UI_GetID("timeLB")
  159.     EnterInformationLB = __UI_GetID("EnterInformationLB")
  160.     WeightTB = __UI_GetID("WeightTB")
  161.     nbrDrinksTB = __UI_GetID("nbrDrinksTB")
  162.     TimeTB = __UI_GetID("TimeTB")
  163.     CancelBT = __UI_GetID("CancelBT")
  164.     OKBT = __UI_GetID("OKBT")
  165.     HELPBT = __UI_GetID("HELPBT")
  166.     QUITBT = __UI_GetID("QUITBT")
  167.     informationLB = __UI_GetID("informationLB")
  168.     displayResults = __UI_GetID("displayResults")
  169.     AGREEBT = __UI_GetID("AGREEBT")
  170.     AgreeCB = __UI_GetID("AgreeCB")
  171.     maleRB = __UI_GetID("maleRB")
  172.     femaleRB = __UI_GetID("femaleRB")
  173.  

Here is the complete ZIP file, that contains all the source, fonts, and text files needed to run the program: 

6
InForm-based programs / Word Search
« on: October 13, 2021, 11:37:20 am »
A couple of days ago I went through Fellippe's video and recreated his program, so I have zipped it up and is available.

However, I have made some improvements to it, namely:
  • Added a QUIT button, as I found out on MAC OSX, there is no X button to close the form, and the red dot is greyed out.
  • Formatted the search results using @SMcNeill' format string function he wrote and updated for me (https://www.qb64.org/forum/index.php?topic=4031.msg133716#msg133716)
  • Removed all the code not needed (You need to leave all the generated SUBs in, but can remove statements not used)
The zip file contains:
  • bible.txt - The text version of the King James Bible from the Gutenberg Project
  • countWords.bas - The original console version from the video
  • wordSearch.bas - The source code originally generated by InForm, with the updates from countWords and my additional changes
  • bibleSearch.bas - Shows what the code would/should look like after removing all the SELECT/CASE statements not needed
  • wordSearch.frm - The form file generated by InForm
  • wordSearch - A Linux Binary file, which after compiling, is the only file needed for distribution (unless you need to supply Font files)
  • InForm - A folder with all the files necessary to compile the programs in QB64 or edit the form in InForm
You will also notice that there is no form named bibleSearch.frm. That's because I use the wordSearch.frm in that program. Bear in mind that if you edit wordSearch.frm in InForm, it will create a new wordSearch form and BASIC program, or if the BASIC program already exists, will update your version without wiping out the code you placed in it.

Below is a screen print of my modified form while processing a search. When the search completes, the message changes to say "Search completed ...".
 
wordSearch4.png


Here is the Zip file:
 
 

7
As I promised, I conducted testing of both the development release (Build ef4dffb) and the stable release (Build 3043116) to see if I could replicate both the zombie and orphan issues I have been having while testing the DEBUG feature.

My conclusion is that zombie (and sometimes orphan processes) occur in both releases, and have nothing to do with the DEBUG updates.

I ran separate tests, one set with the stable release, the same programs in the development release (both without DEBUG and the third with DEBUG) and I get the same results. Every time I compile and run programs from the IDE, it creates a zombie process.

My computer setup is as follows:  Dell Optiplex 990, with Intel® Coreâ„¢ i5-2400 CPU @ 3.10GHz × 4, 32GB of RAM (Crucial RAM 4x8GB DDR3 1600 MHz CL11 Desktop Memory), running the latest updates of Linux Ubuntu 20.04.2 LTS. My primary hard drive is 500GB with a USB ProBox 4-bay HD storage device with 4 more SATA hard drives totaling 16TB.

After my last report where orphan processes were running just over 50 hours, I have not repeated this test (I plan on it, but wanted to reproduce the zombie process first).

The code I used for my testing is in this post (It was modified from a program by bplus) and all it does is display the character, binary number, ASCII code and hexadecimal code for ASCII 32 to 126. All display was to QB64's console. No compiles were done outside the IDE. No execution was launched from outside the IDE. Everything during the 3 tests outlined above were all done with the IDE.

I have looked at a test runs that I conducted outside of the IDE, where I wrote the code in the Geany Editor and used both the compile function from Geany and compiled on the command line using both QB64 directly and my BASH script I wrote, and doing more than 30 compiles and test runs of a program that integrates mySQL and BASH scripts providing args to them, I have not been able to reproduce the issues outlined here.

Common to all three types of testing and watching the progress, only after the third run (compile and execute from the IDE), 2 Zombie processes showed up! And from that point on, each successive run created a new zombie process.

I have provided in this post both screen prints of HTOP showing the zombie processes, and a log from my terminal showing the commands and results, such as MEMSTAT, PTREE and PS. I only provided one set of results, as they were the same across the three sets of testing I conducted.

In the three test sessions I performed, closing out QB64 did close out all the zombie processes. However, in the past as I have reported, this is not always the case. QB64 left orphans of itself and my system thought they were still running. With no active QB64 IDE or compiled code running, my screen prints from last week on Discord showed orphan processes that were still running (they were orphans because QB64 was closed down more than 24 hours before those screen prints were taken), even though QB64 was terminated normally. I even had PIDs of the program I was testing still running, even though everything was closed out properly more than 24 hours prior.

My system is running as a server that manages my devices in my house, so my system runs for weeks on end with no performance degradation, or any other issues. Only when QB64 is running, and I am doing many test runs and code changes using the IDE do I get severe system issues after many days.

I think it is time that someone looks into why this is happening. Before I did this test, I had both zombie and orphan processes, which crashed my machine before I could screen print and run my terminal commands to document them. As I discussed on Discord, I had closed out normally QB64, and all the programs I was running and testing over those three days ended normally.

And I do not accept as a solution to not run my system or development the way I do. It is not my behavior when coding or running my system as a server that is causing the issue, otherwise I would have similar issues with mySQL or Apache 2 Server.

Below are the screen prints from HTOP, and a log of commands I ran in terminal to show how these processes are tied in with each other. I also ran a MEMSTAT just to show what other programs are being used by QB64.

Here are the results from my Terminal commands:
Quote
(base) gjmcginn@optiplex990:~$ pidof qb64
18952
(base) gjmcginn@optiplex990:~$ memstat -p 18952
 586892k: PID 18952 (/home/gjmcginn/qb64-development/qb64)
      4k(      4k): /memfd:xshmfence 18952
      4k(      4k): /memfd:xshmfence 18952
  15004k(  15004k): anon_inode:i915.gem 18952
   1284k(   1284k): /home/gjmcginn/.cache/mesa_shader_cache/index 18952
   7024k(   6352k): /home/gjmcginn/qb64-development/qb64 18952
    148k(     88k): /usr/lib/x86_64-linux-gnu/libdrm_intel.so.1.0.0 18952
    480k(    272k): /usr/lib/x86_64-linux-gnu/libGLX_mesa.so.0.0.0 18952
    676k(    584k): /usr/lib/x86_64-linux-gnu/libzstd.so.1.4.4 18952
   1916k(    964k): /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28 18952
    108k(     72k): /usr/lib/x86_64-linux-gnu/libgcc_s.so.1 18952
    184k(    140k): /usr/lib/x86_64-linux-gnu/ld-2.31.so 18952
    540k(    128k): /usr/lib/x86_64-linux-gnu/libGL.so.1.7.0 18952
    456k(    332k): /usr/lib/x86_64-linux-gnu/libGLU.so.1.3.1 18952
    144k(    108k): /usr/lib/x86_64-linux-gnu/libGLX.so.0.0.0 18952
    228k(     56k): /usr/lib/x86_64-linux-gnu/libglapi.so.0.0.0 18952
    704k(    252k): /usr/lib/x86_64-linux-gnu/libGLdispatch.so.0.0.0 18952
     20k(      4k): /usr/lib/x86_64-linux-gnu/libX11-xcb.so.1.0.0 18952
     24k(      8k): /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0 18952
     32k(      8k): /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0 18952
     84k(     44k): /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0 18952
     32k(     12k): /usr/lib/x86_64-linux-gnu/libXfixes.so.3.1.0 18952
     28k(     12k): /usr/lib/x86_64-linux-gnu/libXxf86vm.so.1.0.0 18952
    100k(     60k): /usr/lib/x86_64-linux-gnu/libbsd.so.0.10.0 18952
   1976k(   1504k): /usr/lib/x86_64-linux-gnu/libc-2.31.so 18952
     24k(      8k): /usr/lib/x86_64-linux-gnu/libdl-2.31.so 18952
     80k(     40k): /usr/lib/x86_64-linux-gnu/libdrm.so.2.4.0 18952
     60k(     28k): /usr/lib/x86_64-linux-gnu/libdrm_radeon.so.1.0.1 18952
     44k(     20k): /usr/lib/x86_64-linux-gnu/libdrm_nouveau.so.2.0.0 18952
    184k(    112k): /usr/lib/x86_64-linux-gnu/libexpat.so.1.6.11 18952
   1340k(    668k): /usr/lib/x86_64-linux-gnu/libm-2.31.so 18952
     56k(     28k): /usr/lib/x86_64-linux-gnu/libnss_files-2.31.so 18952
     44k(     20k): /usr/lib/x86_64-linux-gnu/libpciaccess.so.0.11.1 18952
    124k(     68k): /usr/lib/x86_64-linux-gnu/libpthread-2.31.so 18952
     28k(      8k): /usr/lib/x86_64-linux-gnu/libxcb-dri2.so.0.0.0 18952
     24k(      4k): /usr/lib/x86_64-linux-gnu/libxcb-dri3.so.0.0.0 18952
    116k(     36k): /usr/lib/x86_64-linux-gnu/libxcb-glx.so.0.0.0 18952
     20k(      4k): /usr/lib/x86_64-linux-gnu/libxcb-present.so.0.0.0 18952
     20k(      4k): /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0.0.0 18952
     40k(     12k): /usr/lib/x86_64-linux-gnu/libxcb-sync.so.1.0.0 18952
     40k(     12k): /usr/lib/x86_64-linux-gnu/libxcb-xfixes.so.0.0.0 18952
    168k(     80k): /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0 18952
   2056k(      4k): /usr/lib/x86_64-linux-gnu/libxshmfence.so.1.0.0 18952
    112k(     68k): /usr/lib/x86_64-linux-gnu/libz.so.1.2.11 18952
   1268k(    556k): /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0 18952
  14588k(   9596k): /usr/lib/x86_64-linux-gnu/dri/i965_dri.so 18952
--------
 638528k (  38672k)
(base) gjmcginn@optiplex990:~$ pstree -A -p -s 18952
systemd(1)---systemd(1519)---qb64(18952)-+-qb64(18983)
                                         |-qb64(19010)
                                         |-qb64(19035)
                                         |-qb64(19061)
                                         |-qb64(19322)
                                         |-qb64(19345)
                                         |-qb64(19374)
                                         |-qb64(19399)
                                         |-qb64(19427)
                                         |-{qb64}(18953)
                                         |-{qb64}(18954)
                                         |-{qb64}(18955)
                                         |-{qb64}(18958)
                                         |-{qb64}(18959)
                                         |-{qb64}(18960)
                                         `-{qb64}(18961)
(base) gjmcginn@optiplex990:~$ ps ax | grep qb64
  18952 ?        Sl     2:05 ./qb64
  18983 ?        Z      0:00 [qb64] <defunct>
  19010 ?        Z      0:00 [qb64] <defunct>
  19035 ?        Z      0:00 [qb64] <defunct>
  19061 ?        Z      0:00 [qb64] <defunct>
  19322 ?        Z      0:00 [qb64] <defunct>
  19345 ?        Z      0:00 [qb64] <defunct>
  19374 ?        Z      0:00 [qb64] <defunct>
  19399 ?        Z      0:00 [qb64] <defunct>
  19427 ?        Z      0:00 [qb64] <defunct>
  20077 pts/3    S+     0:00 grep --color=auto qb64
(base) gjmcginn@optiplex990:~$ pstree -A -p -g -s -t 18952
systemd(1,1)---systemd(1519,1519)---qb64(18952,1924)-+-qb64(18983,1924)
                                                     |-qb64(19010,1924)
                                                     |-qb64(19035,1924)
                                                     |-qb64(19061,1924)
                                                     |-qb64(19322,1924)
                                                     |-qb64(19345,1924)
                                                     |-qb64(19374,1924)
                                                     |-qb64(19399,1924)
                                                     |-qb64(19427,1924)
                                                     |-{qb64:disk$0}(18958,1924)
                                                     |-{qb64:disk$1}(18959,1924)
                                                     |-{qb64:disk$2}(18960,1924)
                                                     |-{qb64:disk$3}(18961,1924)
                                                     |-{qb64}(18953,1924)
                                                     |-{qb64}(18954,1924)
                                                     `-{qb64}(18955,1924)
(base) gjmcginn@optiplex990:~$


Below are the two HTOP screen prints showing basically the same info above:
  [ You are not allowed to view this attachment ]  
  [ You are not allowed to view this attachment ]  

Here is a screen shot of my system details:
  [ You are not allowed to view this attachment ]  

Listing of System Details from my Terminal:
Quote
(base) gjmcginn@optiplex990:~$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.2 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
(base) gjmcginn@optiplex990:~$ hostnamectl
   Static hostname: optiplex990
   Pretty hostname: optiPlex990
         Icon name: computer-desktop
           Chassis: desktop
        Machine ID: 88fa40fc6c1047309a1ad45fbe33b289
           Boot ID: 5d3ddf0e33af417281ac967e0fb6154a
  Operating System: Ubuntu 20.04.2 LTS
            Kernel: Linux 5.11.0-25-lowlatency
      Architecture: x86-64
(base) gjmcginn@optiplex990:~$

Here is the code I was running and compiling in the IDE:
Code: QB64: [Select]
  1. _TITLE "ASCII-BIN-HEX Table" ' b+ 2021-08-04
  2. SCREEN _NEWIMAGE(900, 450, 32)
  3. count = 0
  4. PRINT "CHARACTER, BINARY, ASCII, and HEX TABLE": PRINT
  5. FOR i = 32 TO 126 ' looks OK
  6.    count = count + 1
  7.    IF count = 4 THEN
  8.        PRINT " " + CHR$(i); " "; AscBin$(i); VAL("&b" + AscBin$(i)); " "; "0x" + HEX$(i)
  9.        count = 0
  10.    ELSE
  11.        PRINT " " + CHR$(i); " "; AscBin$(i); VAL("&b" + AscBin$(i)); " "; "0x" + HEX$(i),
  12.    END IF
  13.  
  14.  
  15. FUNCTION AscBin$ (integerBase10 AS INTEGER) 'any integer < 256  ie all ascii
  16.     DIM j AS INTEGER
  17.     AscBin$ = STRING$(8, "0")
  18.     WHILE j <= 8
  19.         IF (integerBase10 AND 2 ^ j) > 0 THEN MID$(AscBin$, 8 - j, 1) = "1" + AscBin$
  20.         j = j + 1
  21.     WEND

8
QB64 Discussion / INPUT from a file failing on a comma in the record
« on: July 22, 2021, 04:40:03 pm »
Hello,

I am running into an issue were I am reading a record from a file, and part of the record there is a coma. I am not getting the entire record.

The file was created after a mySQL select returned a number of rows. I piped them to a file to test various ways to process them.

After the INPUT #1, qString$, the results are truncated from the comma on. It is not until I do another INPUT #1, qString$ that I get the rest of the record.

Here is one of the records, and the result from my program.

Record (TAB Delimited, but not the issue here as it still occurs when I change the TAB to a pipe):
Quote
7   Blondel père et fils   Frédérique Citeaux   24, place Kléber   Strasbourg   67000   France

This is what I am getting:
Quote
Length of qString$:  47
7   Blondel père et fils   Frédérique Citeaux   24

After the next INPUT, I get (With the results):
Quote
Length of qString$:  37
place Kléber   Strasbourg   67000   France

If I put the entire record in quotes, it works.

Is this a bug? Shouldn't I get the entire record, commas and all, as they are strings?

(And the answer is not to put the record in Quotes, as the results from mySQL does not do that as far as I know!)


9
QB64 Discussion / Zombie Procecsses Getting Out of Hand
« on: July 18, 2021, 03:11:29 pm »
@FellippeHeitor @SpriggsySpriggs

EDIT: I have been informed that there are commits that address zombie processes. I have been running these from the 8109b81 build, and the issues below are from that.

While testing the new development build, including the $DEBUG enhancements, I have been also watching my PIDs closer than I normally do.

What I have noticed is that Zombie processes are getting out of control.

I just checked my PIDs, and I have more than 100 zombie processes from both QB64 and mysqlPGM, a program I was testing until today. I've attached some screen shots of what I am seeing.

I also know that @Richard had an issue where his IDE froze up while running a test over multiple days. I am willing to bet his issue has to do with zombie processes. I was also having IDE issues, and noticed these in my htop display.

I have to take an issue with @luke in that zombie process are harmless (he implied this). A zombie process is the result of a program spawning off one or more child processes, and does not wait for its status (waitpid(pid, &status, 0)). the parent does not wait and when the child process ends, it stays in the system process table. I realize that many people contribute to this project, so some issues may get overlooked.

While some say that these processes are benign,  I disagree. They at least take up PID's, which there are a limited number of them. Also, some of the child processes are still running, as the parent process hasn't check their status to kill them when they are done. This takes up clock cycles (the CPU does check all zombie's to see if they need resources).

I have also noticed system slowdowns due to tasks not getting a PID immediately.

This needs to be fixed. Telling us to just quit the IDE does not clear all the issues (I've had to manually kill PID's after terminating the QB64 IDE).

Below shows both the Zombie processes (S=Z) as well as a program that hasn't run since yesterday (mysqlPGM). Some of these processes have run for more than 36 hours!

  [ You are not allowed to view this attachment ]  
  [ You are not allowed to view this attachment ]  

Edited: Added a pstree and a ps piped grep showing more about the processes. I have 159 processes running/zombies currently.
  [ You are not allowed to view this attachment ]  
  [ You are not allowed to view this attachment ]  

Update: I noticed something else. When checking into some of the processes more, I noticed that for one (and probably many of them) the PGID for the processes below do not have a process, yet instead of showing up a an OPRHAN, they are in a SL status.

Quote
(base) gjmcginn@optiplex990:~$ ps jp 223051
   PPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND
   1334  223051  207117    6511 pts/0     248264 Sl    1000  23:20 ./mysqlPGM
(base) gjmcginn@optiplex990:~$ ps jp 207315
   PPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND
   1334  207315  207117    6511 pts/0     248270 Sl    1000  91:45 ./qb64
(base) gjmcginn@optiplex990:~$ ps jp 207117
   PPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND
(base) gjmcginn@optiplex990:~$ ps a | grep 207117
 248284 pts/0    S+     0:00 grep --color=auto 207117

10
QB64 Discussion / QB64 Command Line Compiler Script
« on: June 27, 2021, 12:15:23 pm »
EDITED 6/27/21: I updated the script (now version 1.1) to allow -c "--help" to execute the help option of the compiler. This will help adding in the replacement compiler option function.

This script will compile a QB64 program via the terminal (command line). It allows you to pass additional compiler switches as well as the directory and program source.

This script runs on Linux, and @SpriggsySpriggs has offered to create a Window's version of this. I will be testing this script on macOS, and will post that script here when it's done.

Some usage conventions are required to use this script:
   1) You need to update your PATH variable to where the qb64 binary resides (in Linux, it is in the /etc/environment file)
   2) Currently this may not work as ROOT for Linux users (There are issues if qb64 is executed from a ROOT directory)
   
This is what my file "environment" looks like with the qb64 directory added:
   PATH="/home/gjmcginn/qb64:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
   
Once you update your PATH, you will need to reboot your system for the changes to take effect.
   
This script will take up to 3 arguments, each proceeded by a switch, which tells the script where to place them. The switches are:
   -c (Provide additional compiler options besides the -c and -o)
   -d (The directory where both the binary will be created and where the source file is located)
   -p (The source file without the .bas extension - the script adds this)
   
   Note: The script has a -r switch. This is to replace the compiler options and will be implemented in Version 2.
   
The default compiler switches applied to all compiles are: -c -x and -o.
   -x                         Compile instead of edit and output the result to the console
   -o <output file>    Write output executable to <output file>

To see all the switches for qb64, you can use just "-c --help" with this script and it will display them in the terminal program.
   
The syntax for executing this script is:
   compileqb64.sh -c "compiler options" -d "source directory" -p "source code"

For example:
   compileqb64.sh -c "-w -e" -d "/home/gjmcginn/SourceCode/basic" -p "EBAC Calculator"
   
This example adds -w and -e to the compiler options, sets up the directory, and provides the <file> to be compiled. Things to remember:
   1) If there are more than one compiler options, they must be enclosed in quotes
   2) If either your directory or file name has spaces, they too must be enclosed in quotes. (You can always use quotes,regardless)
   3) Do not add the / at the end of the directory name from -d. The script will do this for you.

The script will do some rudimentary error checking, and will display in the terminal program its progress. The script is well commented.

Save as compileqb64.sh (Or any name you wish to run it as):
Code: Bash: [Select]
  1. #!/bin/bash
  2.  
  3. #QB64 Compiler -- Shell Script -- George McGinn 2021
  4. #Version 1.5 -- June 28, 2021
  5. #
  6. # compileqb64 - script to compile QB64 source code from any directory
  7. #
  8. # This script takes in up to 3 arguments for use in compiling QB64 from
  9. # the command line. At least two arguments must be present to compile,
  10. # or the script will not work right. The arguments passed are:
  11. #       -c Compiler Options (Add to default) (In quotes)
  12. #   -r Compiler Options (Replace default) (In quotes)
  13. #       -d Source Code/Object Directory Name
  14. #       -p Program File Name (without the .bas extension)
  15. #
  16. # Syntax for compileqb64 is:
  17. #       compileqb64 -c "compiler options" -d "source directory" -p "source code"
  18. # or:
  19. #   compileqb64 -c "--help"
  20. #
  21. # By using switches (-a, -d, -p) this script will parse out the argument
  22. # values, and load the variables based on the values passed. Note that the
  23. # script will append the .bas to the source code <filename>.
  24. #
  25. # Both switches -c and -r populate compiler options, but in a different way.
  26. # The -c switch tells the script to "append" the arguments passed to the ones
  27. # used as default (the -c and -o).
  28. #
  29. # The -r tells the script to replace the default with the ones provided. This may be
  30. # used if you want to compile only to get the C++ code, or start the IDE with or
  31. # without a program loaded.
  32. #
  33. # If you use -c "--help" then the compiler will display the HELP text.
  34. #
  35. # The script, based on what was passed, will build and execute the compile statment.
  36. # The script does a check to see if the source file exists. If it does, it completes
  37. # the compile. If the directory or file does not exist, it errors out.
  38. #
  39. # The process in Version 1.x cannot run as ROOT and will need to be tested.
  40. #
  41.  
  42. # FUNCTION: Test to see if the source code exists (True if the FILE exists and is a regular file (not a directory or device))
  43. is_file() {
  44.         if [ ! -f $FILE ];    
  45.         then
  46.                 echo && echo "*** ERROR: $FILE does not exist. Please fix and retry. Script Terminated."
  47.                 exit 2
  48.         fi
  49. }
  50.  
  51. ### Start of script
  52.  
  53. # Make sure we're not running as root (To be tested for future versions)
  54. if [ $EUID == "0" ]; then
  55.   echo "*** ERROR: You are trying to run this script as root. This is highly unrecommended. Script Terminated."
  56.   exit 1
  57. fi
  58.  
  59. echo "Starting QB64 Command Line Compiler..."
  60. echo
  61.  
  62. # Display the number of arguments passed and their values
  63. echo "Number of arguments passed: $#"
  64. echo "Arguments: $@"
  65.  
  66. # If no compiler options are found, display error message, qb64 help and terminate
  67. if [ $# == 0 ]; then                                                                                           
  68.         echo "*** ERROR: No Compiler Options passed. Make sure you use one of the ones below. Script terminated."
  69.         echo "qb64 --help"
  70.         echo
  71.         qb64 --help
  72.         exit 1
  73. fi
  74.  
  75. # Parse out the arguments based on associated switches
  76. while getopts c:d:p:r: option
  77.         do
  78.         case "${option}"
  79.                 in
  80.                 c) compiler_options_append=${OPTARG}
  81.                    option_c=1;;
  82.                 r)
  83.                    compiler_options_replace=${OPTARG}
  84.                    option_r=1;;
  85.                 d) source_directory=${OPTARG};;
  86.                 p) qb64_program=${OPTARG};;
  87.         esac
  88. done
  89.  
  90. # Build the QB64 Source and Object variables for qb64 command line
  91. if [ "$compiler_options_append" == "--help" ] || [ "$compiler_options_replace" == "--help" ]; then      # Display and execute the qb64 compiler help text
  92.         echo
  93.         echo "qb64 --help"
  94.         echo
  95.         qb64 --help
  96. else                                                                                                   
  97.         if [ "$source_directory" == "" ]; then                          # If source directory isn't provided, then set current working directory as source directory    
  98.                 source_directory="$PWD"
  99.         fi
  100.         qb64_object=$source_directory"/""$qb64_program"
  101.         qb64_source=$source_directory"/""$qb64_program".bas
  102.         FILE=$qb64_source
  103.         is_file "$FILE"                                     # Check to make sure directory/file exists and is readable (not a device or directory only)
  104.         echo
  105.         if [ "$option_c" = 1 ]; then                                                    # Display and the qb64 command line compiler options passed to script
  106.                 echo "Compiler Options (Append): "$compiler_options_append
  107.         elif [ "$option_r" = 1 ]; then
  108.                 echo "Compiler Options (Replace): "$compiler_options_replace
  109.         fi
  110.         echo "Source Code Directory: "$source_directory
  111.         echo "Object Filename: "$qb64_object
  112.         echo "Source Code Filename: "$qb64_source
  113.         echo
  114.  
  115. # Logic to determine the type of process (compile or load QB64 IDE) and execute qb64 binary
  116.         if [ "$compiler_options_append" == "" ] && [ "$option_c" != 1 ]; then   # Check for compiler_options_append equal to NULL, execute replace if so  
  117.                 if [ "$compiler_options_replace" == "" ]; then                                      # If compiler_options_replace is also NULL, then load source into QB64 IDE and edit
  118.                         echo "Editing (QB64 IDE) "$qb64_source" ..."
  119.                         qb64 "$qb64_source"
  120.                         exit 0                                                                          # Exit script after QB64 IDE shuts down
  121.                 else                                                                                    # Execute replace compiler options
  122.                         echo "qb64 $compiler_options_replace -o $qb64_object $qb64_source"
  123.                         echo
  124.                         echo "Compiling "$qb64_source" ..."
  125.                         qb64 "$compiler_options_replace" -o "$qb64_object" "$qb64_source"
  126.                 fi
  127.         else                                                                                            # Eexecute append compiler options
  128.                 if [ "$compiler_options_append" != "" ]; then
  129.                         echo "qb64 -x -w $compiler_options_append -o $qb64_object $qb64_source"
  130.                         echo
  131.                         echo "Compiling "$qb64_source" ..."
  132.                         qb64 -x -w "$compiler_options_append" -o "$qb64_object" "$qb64_source"
  133.                 else
  134.                         echo "qb64 -x -w -o $qb64_object $qb64_source"
  135.                         echo
  136.                         echo "Compiling "$qb64_source" ..."
  137.                         qb64 -x -w -o "$qb64_object" "$qb64_source"
  138.                 fi
  139.         fi
  140.  
  141. # Check for successful compiled completion and display appropriate message
  142.         if [ $? != 0 ]; then                                                               
  143.                 echo ""
  144.                 echo "*** ERROR: Program did not compile successfully. Please fix and retry. Script Terminated."
  145.                 exit 1
  146.         else
  147.                 echo
  148.                 echo "Program \"$qb64_program.bas\" compiled successfully."
  149.         fi
  150. fi
  151.  

11
Here is the text-based version o the Estimated Blood Alcohol program.

For more on this (most of it will apply, see post: https://www.qb64.org/forum/index.php?topic=4003.msg133420#msg133420)

Code: QB64: [Select]
  1. _TITLE "EBAC Calculator"
  2. '------------------------------------------------------------------------------------------------
  3. ' EBAC Calculator v1.0 by George McGinn, MAY, 2021
  4. ' Copyright (C)2021 by George McGinn/Linux Software Systems
  5. '                      All Rights Reserved.
  6. '
  7. ' Program is designed to run as an App in iTunes to run specifically
  8. ' on an iPhone so those who would like to know their esitmate BAC and
  9. ' how long it will take to get to a level to drive safely and legally.
  10. '
  11. ' Blood alcohol content (BAC) can be estimated by a method developed by
  12. ' Swedish professor Erik Widmark in the 1920s.
  13. '
  14. ' Gives the estimated BAC (EBAC), algorhithm reduced as:
  15. '    EBAC=A/(r*Wt)*1.055-B*T (verified by Wiki source listed below)
  16. ' Where:
  17. '    EBAC: Estimated Blood Alcohol Content (%)
  18. '        A: Alcohol consumed (in ounces to grams) or FLoz
  19. '        r: Ratio of body water to total weight (men: .68, women: .55)
  20. '      Wt: Body weight (in pounds to kilograms)
  21. '        B: Rate alcohol metabolized (men: .019/hr, women: .017/hr)
  22. '        T: Time alcohol in blood or time since consumption began
  23. '    1.055: Constant value of density of blood
  24. '
  25. ' The formula can also be reduced as follows (called the 8/10 formula):
  26. '    For Men:   EBAC = 7.97*A/Wt-B*T
  27. '    For Women: EBAC = 9.86*A/Wt-B*T
  28. '
  29. ' Factors 7.97 and 9.86 are derived from "r" and 1.055.
  30. ' Also, this formula is geared to fluid ounces and pounds, not
  31. ' grams and kilograms. While the suggested values were 8 and 10,
  32. ' testing showed the results were not accurate. So I reworked it
  33. ' and found that 7.97 and 9.86 gives better results.
  34. '
  35. ' It will be this reduced formula the program will use.
  36. '
  37. ' Each shot, wine glass and bottle/can of beer contains .6oz of
  38. ' alcohol. User records the number of drinks, which will then be
  39. ' converted to ounces (drinks * .6)
  40. '
  41. ' *** Formulas created/translated by George McGinn using the following sources:
  42. '    * Blood alcohol content can be estimated by a method developed
  43. '      by Swedish professor Erik Widmark [sv] in the 1920s.
  44. '      (https://web.archive.org/web/20031202155933/http://www.dui-law.com/810art.htm)
  45. '    * https://www.ou.edu/police/faid/blood-alcohol-calculator
  46. '    * https://www.gambonelaw.com/faqs/the-widmark-formula-and-calculating-your-bac-level/
  47. '    * https://en.wikipedia.org/wiki/Blood_alcohol_content
  48. '    * https://en.wikipedia.org/wiki/Binge_drinking
  49. '    * https://en.wikipedia.org/wiki/Alcohol_intoxication
  50. '    * https://en.wikipedia.org/wiki/Breathalyzer
  51. '    * https://ndaa.org/wp-content/uploads/toxicology_final.pdf
  52. '    * http://njlaw.rutgers.edu/collections/courts/supreme/a-96-06.doc.html
  53. '    * https://www.researchgate.net/profile/Alan-Jones-14/publication/318055507_Profiles_in_Forensic_Toxicology_Professor_Erik_Widmark_1889-1945/links/595794330f7e9ba95e0fd91d/Profiles-in-Forensic-Toxicology-Professor-Erik-Widmark-1889-1945.pdf?origin=publication_detail
  54. '    * https://www.cdc.gov/alcohol
  55. '------------------------------------------------------------------------------------------------
  56. '
  57. ' PROGRAM NOTES:
  58. ' --------------
  59. ' This blood alcohol content or BAC, for short, calculator can estimate
  60. ' your blood alcohol levels. Metabolism, body fat percentage and
  61. ' medication are other factors that can affect the rate of absorption
  62. ' by the body, and these are not considered in this calculation.
  63. '
  64. ' Blood alcohol content (BAC) or blood alcohol level is the
  65. ' concentration of alcohol in the bloodstream. It is usually measured
  66. ' as mass per volume. For example, a Blood alcohol content BAC of
  67. ' 0.04% means 0.4% (permille) or 0.04 grams of alcohol per 100 grams
  68. ' of individual’s blood. Use this BAC Calculator for informational
  69. ' purposes only, and not to drink and drive or drink and work.
  70. '
  71. ' Important Note: There is no BAC calculator that is 100% accurate.
  72. ' This is due to the number of factors that come into play regarding
  73. ' the consumption and alcohol processing rates of different people.
  74. ' Factors include the gender of the drinker (biologic, not identity),
  75. ' their differing metabolism rates, various health issues, and the
  76. ' combination of medications and supplements that might be taken by
  77. ' the drinker, drinking frequency, amount of food in the stomach and
  78. ' small intestine and when it was eaten, elapsed time, and other
  79. ' factors. The best that can be done is a rough estimation of the
  80. ' bloodstreams alcohol content or the BAC level based on known inputs.
  81. '
  82. ' Every state in the U.S. has a legal Blood Alcohol (BAC) limit of
  83. ' 0.05% or 0.08%, (depending on the state you are driving in). Most
  84. ' states also have lower legal BAC limits for young and inexperienced
  85. ' drivers, professional drivers and commercial drivers. Sentences for
  86. ' drunk driving include imprisonment, large fines, lengthy drivers
  87. ' license suspension and/or revocation, house arrest, community
  88. ' service, DUI schools, alcohol treatment programs, vehicle forfeiture
  89. ' and ignition interlock restrictions.
  90. '
  91. '------------------------------------------------------------------------------------------------
  92. ' Program Copyright (C)2021 by George McGinn/Pyramid Software Systems
  93. ' All Rights Reserved.
  94. '
  95. ' EBAC Calculator by George McGinn is licensed under a Creative Commons
  96. ' Attribution-NonCommercial 4.0 International License.
  97. '
  98. ' Full License Link: https://creativecommons.org/licenses/by-nc/4.0/
  99. '
  100. '
  101. ' You are free to (For non-commerical purposes only):
  102. '     Share          - copy and redistribute the material in any medium or format.
  103. '     Adapt          - remix, transform, and build upon the material.
  104. '     Attribution    - You must give appropriate credit, provide a link to
  105. '     the license, and indicate if changes were made. You may do so in any
  106. '     reasonable manner, but not in any way that suggests the licensor
  107. '     endorses you or your use.
  108. '     Non Commercial - You may not use the material for commercial purposes.
  109. '
  110. ' *** None of this code is considered in the Public Domain. Rights granted under CC 4.0
  111. '     are outlined as above and the disclaimer below:
  112. '
  113. ' *** DISCLAIMER ***
  114. ' Unless otherwise separately undertaken by the Licensor, to the extent possible,
  115. ' the Licensor offers the Licensed Material as-is and as-available, and makes no
  116. ' representations or warranties of any kind concerning the Licensed Material, whether
  117. ' express, implied, statutory, or other. This includes, without limitation, warranties
  118. ' of title, merchantability, fitness for a particular purpose, non-infringement, absence
  119. ' of latent or other defects, accuracy, or the presence or absence of errors, whether or
  120. ' not known or discoverable. Where disclaimers of warranties are not allowed in full or
  121. ' in part, this disclaimer may not apply to You.
  122. '
  123. ' To the extent possible, in no event will the Licensor be liable to You on any legal theory
  124. ' (including, without limitation, negligence) or otherwise for any direct, special, indirect,
  125. ' incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages
  126. ' arising out of this Public License or use of the Licensed Material, even if the Licensor has
  127. ' been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation
  128. ' of liability is not allowed in full or in part, this limitation may not apply to You.
  129. '
  130. ' The disclaimer of warranties and limitation of liability provided above shall be interpreted
  131. ' in a manner that, to the extent possible, most closely approximates an absolute disclaimer and
  132. '  waiver of all liability.
  133. '------------------------------------------------------------------------------------------------
  134.  
  135.  
  136. '--------------------------------
  137. '*** Initialize SCREEN
  138. 'SCREEN 12
  139. SCREEN _NEWIMAGE(800, 600, 32)
  140.  
  141. '*** Setup Font Type and Size
  142. fontpath$ = "Verdana.ttf"
  143. font& = _LOADFONT(fontpath$, 8, "")
  144.  
  145.  
  146. QBMain:
  147. DIM B, OZ AS SINGLE
  148.  
  149. '*** Setup constant variables
  150. A = 0
  151. Wt = 0
  152. B = .0
  153. T = 0: St = 0
  154. I = 0
  155. Bdl = 1.055
  156. OZ = .5
  157. TRUE = 1: FALSE = 0
  158. SOBER = FALSE
  159.  
  160. '*** Get INPUT for values for calculations
  161. PRINT "BLOOD ALCOHOL CALCULATOR"
  162. PRINT "------------------------"
  163. INPUT "YOUR SEX (M/F): "; SEX$
  164. SEX$ = UCASE$(SEX$)
  165. IF SEX$ <> "M" AND SEX$ <> "F" THEN GOTO QBMain
  166. INPUT "YOUR WEIGHT (lbs): "; Wt
  167. INPUT "NUMBER OF DRINKS: "; A
  168. INPUT "TIME (HRS) SINCE CONSUMPTION BEGAN: "; T
  169.  
  170. '*** Convert Drinks into Fluid Ounces of EtOH (Pure Alcohol).
  171. '*** A is number of drinks. 1 drink is about .6 FLoz of alcohol
  172. FLoz = A * OZ
  173.  
  174. '*** Set/calculate EBAC values based on SEX$
  175.     CASE "M"
  176.         B = .017
  177.         EBAC = 7.97 * FLoz / Wt - B * T
  178.     CASE "F"
  179.         B = .019
  180.         EBAC = 9.86 * FLoz / Wt - B * T
  181.  
  182. IF EBAC < 0 THEN EBAC = 0
  183.  
  184. '*** DISPLAY RESULTS
  185. PRINT USING "ESTIMATED BLOOD ALCOHOL CONTENT (EBAC) in g/dL = #.###"; EBAC
  186.  
  187.  
  188. '*** IF DRUNK DISPLAY WARNING (.10 WAS DRUNK IN 1984, .08 IN 2003/2004)
  189.     CASE .500 TO 1.9999
  190.         PRINT: PRINT "*** ALERT: CALL AN AMBULANCE, DEATH LIKELY"
  191.         PRINT "Unconsious/coma, unresponsive, high likelihood of death. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  192.     CASE .400 TO .4999
  193.         PRINT: PRINT "*** ALERT: CALL AN AMBULANCE, DEATH POSSIBLE"
  194.         PRINT "Onset of coma, and possible death due to respiratory arrest. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  195.     CASE .350 TO .3999
  196.         PRINT: PRINT "*** ALERT: CALL AN AMBULANCE, SEVERE ALCOHOL POISONING"
  197.         PRINT " Coma is possible. This is the level of surgical anesthesia. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  198.     CASE .300 TO .3499
  199.         PRINT: PRINT "*** ALERT: YOU ARE IN A DRUNKEN STUP0R, AT RISK TO PASSING OUT"
  200.         PRINT "STUPOR. You have little comprehension of where you are. You may pass out suddenly and be difficult to awaken. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  201.     CASE .250 TO .2999
  202.         PRINT: PRINT "*** ALERT: SEVERLY IMPAIRED - DRUNK ENOUGH TO CAUSE SEVERE INJURY/DEATH TO SELF"
  203.         PRINT "All mental, physical and sensory functions are severely impaired. Increased risk of asphyxiation from choking on vomit and of seriously injuring yourself by falls or other accidents. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  204.     CASE .200 TO .2499
  205.         PRINT: PRINT "YOU ARE EXTREMELY DRUNK"
  206.         PRINT "Feeling dazed/confused or otherwise disoriented. May need help to stand/walk. If you injure yourself you may not feel the pain. Some people have nausea and vomiting at this level. The gag reflex is impaired and you can choke if you do vomit. Blackouts are likely at this level so you may not remember what has happened. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  207.     CASE .160 TO .1999
  208.         PRINT: PRINT "YOUR ARE SEVERLY DRUNK - ENOUGH TO BECOME VERY SICK"
  209.         PRINT "Dysphoria predominates, nausea may appear. The drinker has the appearance of a 'sloppy drunk.' It is illegal to operate a motor vehicle at this level of intoxication in all states."
  210.         PRINT: PRINT "* Dysphoria: An emotional state of anxiety, depression, or unease."
  211.     CASE .130 TO .1599
  212.         PRINT: PRINT "YOU ARE VERY DRUNK - ENOUGH TO LOSE PHYSICAL & MENTAL CONTROL"
  213.         PRINT "Gross motor impairment and lack of physical control. Blurred vision and major loss of balance. Euphoria is reduced and dysphoria* is beginning to appear. Judgment and perception are severely impaired. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  214.         PRINT: PRINT "* Dysphoria: An emotional state of anxiety, depression, or unease."
  215.     CASE .100 TO .1299
  216.         PRINT: PRINT "YOU ARE LEGALLY DRUNK"
  217.         PRINT "Significant impairment of motor coordination and loss of good judgment. Speech may be slurred; balance, vision, reaction time and hearing will be impaired. Euphoria. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  218.     CASE .070 TO .0999
  219.         PRINT: PRINT "YOU MAY BE LEGALLY DRUNK"
  220.         PRINT "Slight impairment of balance, speech, vision, reaction time, and hearing. Euphoria. Judgment and self-control are reduced, and caution, reason and memory are impaired (in some* states .08 is legally impaired and it is illegal to drive at this level). You will probably believe that you are functioning better than you really are."
  221.         PRINT: PRINT "(*** As of July, 2004 ALL states had passed .08 BAC Per Se Laws. The final one took effect in August of 2005.)"
  222.     CASE .040 TO .0699
  223.         PRINT: PRINT "YOU MAY BE LEGALLY BUZZED"
  224.         PRINT "Feeling of well-being, relaxation, lower inhibitions, sensation of warmth. Euphoria. Some minor impairment of reasoning and memory, lowering of caution. Your behavior may become exaggerated and emotions intensified (Good emotions are better, bad emotions are worse)"
  225.     CASE .020 TO .0399
  226.         PRINT: PRINT "YOU MAY BE OK TO DRIVE, BUT IMPAIRMENT BEGINS"
  227.         PRINT "No loss of coordination, slight euphoria and loss of shyness. Depressant effects are not apparent. Mildly relaxed and maybe a little lightheaded."
  228.     CASE .000 TO .0199
  229.         PRINT: PRINT "YOU ARE OK TO DRIVE"
  230.  
  231.  
  232. '*** Determine if Drunk (>.08 EBAC) and calculate:
  233. '***    - When user will be less than .08
  234. '***    - How long it will take to become completely sober
  235. IF EBAC > .08 THEN
  236.     SOBER = FALSE
  237.     CEBAC = EBAC
  238.     St = T
  239.     DO UNTIL SOBER = TRUE
  240.         T = T + 1
  241.         IF CEBAC > .0799 THEN I = I + 1
  242.  
  243.         SELECT CASE SEX$
  244.             CASE "M"
  245.                 B = .015
  246.                 CEBAC = 7.97 * FLoz / Wt - B * T
  247.             CASE "F"
  248.                 B = .015
  249.                 CEBAC = 9.86 * FLoz / Wt - B * T
  250.         END SELECT
  251.  
  252.         IF legalToDrive = FALSE THEN
  253.             IF CEBAC < .08 THEN
  254.                 IF I > 9 THEN
  255.                     PRINT USING "It will take ## hours from your last drink to be able to drive."; I
  256.                 ELSE
  257.                     PRINT USING "It will take # hours from your last drink to be able to drive."; I
  258.                 END IF
  259.                 legalToDrive = TRUE
  260.             END IF
  261.         END IF
  262.  
  263.         IF CEBAC <= 0 THEN
  264.             IF T - St > 9 THEN
  265.                 PRINT USING "It will take you ## hours from your last drink to be completely sober."; T - St
  266.             ELSE
  267.                 PRINT USING "It will take you # hours from your last drink to be completely sober."; T - St
  268.             END IF
  269.             SOBER = TRUE
  270.         END IF
  271.     LOOP
  272.  
  273.  

12
Programs / Estimated Blood Alcohol Calculator (LINUX/Zenity Only)
« on: June 20, 2021, 11:16:12 pm »
This program was originally written by me in Objective-C for mobile devices. That is until Apple decided to ban all these programs from the iTunes store. (From their 6/7 update: 4.3: Added drinking game apps as a saturated category.).

After learning Zenity, I decided to convert this program to QB64 and give this GUI a test, and I am pleased with the results.

Back when I was a police officer, this formula, in a more advanced form, was used by defense attorneys in the 70's through parts of the 90's when defending their clients on DUI charges. I can tell you that a breathlizer does not accurately measure blood alcohol content, a requirement to convict someone in court. What it does measure is the amount of alcohol that is leaving the body. Which is why the must draw blood to get an accurate BAC figure, which is done today, but wasn't standard back when I was in law enforcement.

I offer this program as a novelty, and if you host parties, you could use it to guide your decision on guests who may drink too much. I do. However, remember that when I created this, I used only the averages for males and females. Many factors are specific to an individual such as metabolism rate, which your doctor can tell you what it is after conducting tests. The comments in the program and the help file lists some of the many factors that are not considered by this program.

The program itself is well documented and lots of comments to help anyone looking to understand how Zenity works with QB64. I use both pipecom and SHELL to serve the GUI, and I am using most of the funtionality of Zenity with some exceptions.

This program will only run on Linux. I have a version for all platforms that uses the QB64 screen for input and output. I will post this program seperately.

To run this program, there is a HELP file that must be loaded in the same directory as the binary executable. The program, due to the constraints of Zenity's Text Information Dialog, the output into the GUI can only come from this file. Also, the program will write out the results of the calculation to a temporary file called "tempfile" that resides in the same directory as the executable. The program removes this file when it ends. If the file somehow exists when the program starts, it will be replaced. So make sure you do not have a file by that name in the directory you plan to run this.

Attached to this post is a compressed file that has both the source code and the help file. I also have the latest pipecom utility by Spriggs in this archive as well. This is for those who do not want to cut/paste a 400+ line program (150 lines consists of the comments at the beginning of the program).

Since this may still be a commercially viable program for me (in that I plan to market it for free), it is provided under the Creative Commons Attribution License. You are free to do what you want with it as long as: 1) I am credited with it, and 2) For your protection, keep the disclaimer intact.

Enjoy. Those who wish to learn about Zenity will find this program very educational.


*** You can find the latest version of Pipecom here: https://www.qb64.org/forum/index.php?topic=3641.msg129938#msg129938

Code: QB64: [Select]
  1. _TITLE "ebacCalculator.bas"
  2. '------------------------------------------------------------------------------------------------
  3. ' EBAC Calculator v1.0 by George McGinn, APRIL, 2021
  4. ' Copyright (C)2021 by George McGinn
  5. '                      All Rights Reserved.
  6. '
  7. ' 6/19/2021 - Updated To use Zenity and SHELL commands to run on Linux with a simple GUI. (GJM)
  8. '
  9. ' Original code designed to run as an App in iTunes to run specifically
  10. ' on an iPhone so those who would like to know their esitmate BAC and
  11. ' how long it will take to get to a level to drive safely and legally.
  12. '
  13. ' Modified to run on the Desktop for use at home. You can judge the amount of drinks your guests
  14. ' have had and use this program to help in deciding who can drive and approximately how long
  15. ' someone needs to wait before they could possibly drive.
  16. '
  17. ' *** There is no warranty (See Disclaimer) as to the fitness or accuracy of the results.
  18. ' *** While every effort has been made to provide accurate results, other factors not considered
  19. ' *** also play a role in determining one's Blood Alcohol Content.
  20. '
  21. ' Blood alcohol content (BAC) can be estimated by a method developed by Swedish professor
  22. ' Erik Widmark in the 1920s.
  23. '
  24. ' Gives the estimated BAC (EBAC), algorhithm reduced as:
  25. '    EBAC=A/(r*Wt)*1.055-B*T (verified by Wiki source listed below)
  26. ' Where:
  27. '    EBAC: Estimated Blood Alcohol Content (%)
  28. '        A: Alcohol consumed (in ounces to grams) or FLoz
  29. '        r: Ratio of body water to total weight (men: .68, women: .55)
  30. '      Wt: Body weight (in pounds to kilograms)
  31. '        B: Rate alcohol metabolized (men: .019/hr, women: .017/hr)
  32. '        T: Time alcohol in blood or time since consumption began
  33. '    1.055: Constant value of density of blood
  34. '
  35. ' The formula can also be reduced as follows (called the 8/10 formula):
  36. '    For Men:   EBAC = 7.97*A/Wt-B*T
  37. '    For Women: EBAC = 9.86*A/Wt-B*T
  38. '
  39. ' Factors 7.97 and 9.86 are derived from "r" and 1.055 among other factors.
  40. ' Also, this formula is geared to fluid ounces and pounds, not
  41. ' grams and kilograms. While the suggested values were 8 and 10,
  42. ' testing showed the results were not accurate. So I reworked it
  43. ' and found that 7.97 and 9.86 gives better results.
  44. '
  45. ' It will be this reduced formula the program will use.
  46. '
  47. ' Each shot, wine glass and bottle/can of beer contains .6oz of
  48. ' alcohol. User records the number of drinks, which will then be
  49. ' converted to ounces (drinks * .6)
  50. '
  51. ' *** Formulas created/translated by George McGinn using the following sources:
  52. '    * Blood alcohol content can be estimated by a method developed
  53. '      by Swedish professor Erik Widmark [sv] in the 1920s.
  54. '      (https://web.archive.org/web/20031202155933/http://www.dui-law.com/810art.htm)
  55. '    * https://www.ou.edu/police/faid/blood-alcohol-calculator
  56. '    * https://www.gambonelaw.com/faqs/the-widmark-formula-and-calculating-your-bac-level/
  57. '    * https://en.wikipedia.org/wiki/Blood_alcohol_content
  58. '    * https://en.wikipedia.org/wiki/Binge_drinking
  59. '    * https://en.wikipedia.org/wiki/Alcohol_intoxication
  60. '    * https://en.wikipedia.org/wiki/Breathalyzer
  61. '    * https://ndaa.org/wp-content/uploads/toxicology_final.pdf
  62. '    * http://njlaw.rutgers.edu/collections/courts/supreme/a-96-06.doc.html
  63. '    * https://www.researchgate.net/profile/Alan-Jones-14/publication/318055507_Profiles_in_Forensic_Toxicology_Professor_Erik_Widmark_1889-1945/links/595794330f7e9ba95e0fd91d/Profiles-in-Forensic-Toxicology-Professor-Erik-Widmark-1889-1945.pdf?origin=publication_detail
  64. '    * https://www.cdc.gov/alcohol
  65. '------------------------------------------------------------------------------------------------
  66. '
  67. ' PROGRAM NOTES:
  68. ' --------------
  69. ' This blood alcohol content or BAC, for short, calculator can estimate
  70. ' your blood alcohol levels. Metabolism, body fat percentage and
  71. ' medication are some of the other factors that can affect the rate of absorption
  72. ' by the body, and these are not considered in this calculation.
  73. '
  74. ' Blood alcohol content (BAC) or blood alcohol level is the
  75. ' concentration of alcohol in the bloodstream. It is usually measured
  76. ' as mass per volume. For example, a Blood alcohol content BAC of
  77. ' 0.04% means 0.4% (permille) or 0.04 grams of alcohol per 100 grams
  78. ' of individuals blood. Use this BAC Calculator for informational
  79. ' purposes only, and not to drink and drive or drink and work.
  80. '
  81. ' Important Note: There is no BAC calculator that is 100% accurate.
  82. ' This is due to the number of factors that come into play regarding
  83. ' the consumption and alcohol processing rates of different people.
  84. ' Other factors not considered here include:
  85. '    * Overall health and wellness
  86. '    * Body type
  87. '    * Metabolism (Program uses an Average for Males & Females)
  88. '    * Alcohol tolerance
  89. '    * What kind of alcohol is consumed (Program uses average drink of 40% ETOH)
  90. '    * Medications
  91. '    * Amount of food eaten
  92. '    * Emotional, mental state
  93. '
  94. ' The best that can be done is a rough estimation of the
  95. ' bloodstreams alcohol content or the BAC level based on known inputs.
  96. '
  97. ' Every state in the U.S. has a legal Blood Alcohol (BAC) limit of 0.05% or 0.08%,
  98. ' (depending on the state you are driving in). Most states also have lower legal
  99. ' BAC limits for young and inexperienced drivers, professional drivers and commercial
  100. ' drivers. Sentences for drunk driving include imprisonment, large fines, lengthy drivers
  101. ' license suspension and/or revocation, house arrest, community service, DUI schools,
  102. ' alcohol treatment programs, vehicle forfeiture and ignition interlock restrictions.
  103. '
  104. '------------------------------------------------------------------------------------------------
  105. ' Program Copyright (C)2021 by George McGinn
  106. ' All Rights Reserved.
  107. '
  108. ' EBAC Calculator by George McGinn is licensed under a Creative Commons
  109. ' Attribution-NonCommercial 4.0 International License.
  110. '
  111. ' Full License Link: https://creativecommons.org/licenses/by-nc/4.0/
  112. '
  113. '
  114. ' You are free to (For non-commerical purposes only):
  115. '     Share          - copy and redistribute the material in any medium or format.
  116. '     Adapt          - remix, transform, and build upon the material.
  117. '     Attribution    - You must give appropriate credit, provide a link to
  118. '                      the license, and indicate if changes were made. You may do so in any
  119. '                      reasonable manner, but not in any way that suggests the licensor
  120. '                      endorses you or your use.
  121. '     Non Commercial - You may not use the material for commercial purposes.
  122. '
  123. ' *** None of this code is considered in the Public Domain. Rights granted under CC 4.0
  124. '     are outlined as above and the disclaimer below:
  125. '
  126. ' *** DISCLAIMER ***
  127. ' Unless otherwise separately undertaken by the Licensor, to the extent possible,
  128. ' the Licensor offers the Licensed Material as-is and as-available, and makes no
  129. ' representations or warranties of any kind concerning the Licensed Material, whether
  130. ' express, implied, statutory, or other. This includes, without limitation, warranties
  131. ' of title, merchantability, fitness for a particular purpose, non-infringement, absence
  132. ' of latent or other defects, accuracy, or the presence or absence of errors, whether or
  133. ' not known or discoverable. Where disclaimers of warranties are not allowed in full or
  134. ' in part, this disclaimer may not apply to You.
  135. '
  136. ' To the extent possible, in no event will the Licensor be liable to You on any legal theory
  137. ' (including, without limitation, negligence) or otherwise for any direct, special, indirect,
  138. ' incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages
  139. ' arising out of this Public License or use of the Licensed Material, even if the Licensor has
  140. ' been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation
  141. ' of liability is not allowed in full or in part, this limitation may not apply to You.
  142. '
  143. ' The disclaimer of warranties and limitation of liability provided above shall be interpreted
  144. ' in a manner that, to the extent possible, most closely approximates an absolute disclaimer and
  145. ' waiver of all liability.
  146. '------------------------------------------------------------------------------------------------
  147.  
  148.  
  149. '--------------------------------
  150. '*** Initialize
  151.  
  152. '*** If You comment the line below out, you will see the [DEBUG] PRINT statements in the QB64 Window. You can add your own PRINT statements if needed
  153. SCREEN _NEWIMAGE(500, 700, 32)
  154.  
  155. DIM SHARED AS SINGLE B, OZ, Wt
  156. DIM SHARED numeric(255)
  157. DIM SHARED AS INTEGER TRUE, FALSE, SOBER
  158. DIM SHARED AS STRING Weight, Drinks, TimeElapsed
  159. DIM SHARED AS STRING cmd, stdout, stderr, stdbutton
  160. DIM SHARED AS LONG result
  161. DIM SHARED AS STRING prt_text
  162.  
  163. '--------------------------------
  164. '*** Setup NUMERIC Check Table
  165. FOR I = 48 TO 57
  166.     numeric(I) = -1
  167.  
  168. EBACMain:
  169. '--------------------------------
  170. '*** Setup constant variables
  171.     A = 0
  172.     Wt = 0
  173.     B = .0
  174.     T = 0: St = 0
  175.     I = 0
  176.     Bdl = 1.055
  177.     OZ = .5
  178.     TRUE = -1: FALSE = 0
  179.     SOBER = FALSE
  180.  
  181.  
  182. EBACForm:
  183. '--------------------------------
  184. '*** Produce the Input Form
  185.     stdout = ""
  186.     cmd = "zenity --forms --title=" + CHR$(34) + "EBAC Blood Alcohol Calculator" + CHR$(34) + _
  187.           " --text=" + CHR$(34) + "Enter information about your friend." + CHR$(34) + _
  188.           " --add-entry=" + CHR$(34) + "Sex (M or F)" + CHR$(34) + _
  189.           " --add-entry=" + CHR$(34) + "Weight (lbs)" + CHR$(34) + _
  190.           " --add-entry=" + CHR$(34) + "Number of drinks" + CHR$(34) + _
  191.           " --add-entry=" + CHR$(34) + "Time (hrs) from first drink" + CHR$(34) + _
  192.           " --extra-button=HELP --extra-button=QUIT"
  193.  
  194.     result = pipecom(cmd, stdout, stderr)
  195.  
  196.     stdbutton = LEFT$(stdout, 4)
  197.  
  198.     IF result = 1 AND stdbutton = "QUIT" THEN GOTO endPROG
  199.  
  200.     IF result = 1 AND stdbutton = "HELP" THEN
  201.         cmd = "zenity --text-info " + _
  202.               " --title=" + CHR$(34) + "HELP/ABOUT: EBAC Calculator" + CHR$(34) + _
  203.               " --filename=" + "EBACHelp.txt" + _
  204.               " --width=525 --height=600"
  205.         SHELL (cmd)
  206.         GOTO EBACForm
  207.     END IF
  208.  
  209.     IF result <> 0 THEN
  210.         SHELL ("zenity --error --text=" + CHR$(34) + "Main Form did not load. Program Terminated." + CHR$(34) + " --width=175 --height=100")
  211.         GOTO endPROG
  212.     END IF
  213.  
  214. '----------------------------------------------------------
  215. '*** Populate QB64 variables from the form's stdout results
  216.  
  217. '--------------------------------------------------
  218. '*** Get and Validate Sex Input
  219.     Sex = MID$(stdout, 1, INSTR(stdout, "|") - 1)
  220.     Sex = UCASE$(Sex)
  221.     IF Sex <> "M" AND Sex <> "F" THEN
  222.         SHELL ("zenity --warning --text=" + CHR$(34) + "SEX must be either M or F." + CHR$(34) + " --width=175 --height=100")
  223.         GOTO EBACForm
  224.     END IF
  225.  
  226. '---------------------------------------------------
  227. '*** Get and Validate Weight Input
  228.     stdout = MID$(stdout, INSTR(stdout, "|") + 1)
  229.     Weight = MID$(stdout, 1, INSTR(stdout, "|") - 1)
  230.     IF ISNUMERIC(Weight) THEN
  231.         Wt = VAL(Weight)
  232.     ELSE
  233.         SHELL ("zenity --warning --text=" + CHR$(34) + "Weight must be numeric." + CHR$(34) + " --width=175 --height=100")
  234.         GOTO EBACForm
  235.     END IF
  236.  
  237.  
  238. '-----------------------------------------------------
  239. '*** Get and Validate Number of Drinks Input
  240.     stdout = MID$(stdout, INSTR(stdout, "|") + 1)
  241.     Drinks = MID$(stdout, 1, INSTR(stdout, "|") - 1)
  242.     IF ISNUMERIC(Drinks) THEN
  243.         A = VAL(Drinks)
  244.     ELSE
  245.         SHELL ("zenity --warning --text=" + CHR$(34) + "Number of drinks must be numeric." + CHR$(34) + " --width=175 --height=100")
  246.         GOTO EBACForm
  247.     END IF
  248.  
  249. '-------------------------------------------------------------------
  250. '*** Get and Validate Time Since First Drink (Time Elapsed) Input
  251.     TimeElapsed = MID$(stdout, INSTR(stdout, "|") + 1)
  252.     l = LEN(TimeElapsed)
  253.     TimeElapsed$ = LEFT$(TimeElapsed, l - 1)
  254.     IF ISNUMERIC(TimeElapsed) THEN
  255.         T = VAL(TimeElapsed)
  256.     ELSE
  257.         SHELL ("zenity --warning --text=" + CHR$(34) + "Time since first drink must be numeric." + CHR$(34) + " --width=175 --height=100")
  258.         GOTO EBACForm
  259.     END IF
  260.  
  261. '--------------------------------------------------------------------------------------------------------
  262. '*** Calculate the value of the Estimated Blood Alcohol Content (EBAC) and check for sucessful completion
  263.     result = calcEBAC
  264.     IF result <> 0 THEN
  265.         SHELL ("zenity --error --text=" + CHR$(34) + "Calulating the EBAC results failed. Program Terminated" + CHR$(34) + " --width=175 --height=100")
  266.         GOTO endPROG
  267.     END IF
  268.  
  269. '---------------------------------------------------------------------------------------------------------------------------------------------
  270. '*** Create a temp file for the Zenity Information Box and write out prt_text (This box cannot have text passed to it unless it is in a file)
  271.     OPEN "tempfile" FOR OUTPUT AS #1
  272.     PRINT #1, USING "ESTIMATED BLOOD ALCOHOL CONTENT (EBAC) in g/dL = #.###"; EBAC
  273.     PRINT #1, prt_text
  274.     CLOSE #1
  275.  
  276. displayEBAC:
  277. '------------------------------------------------------------------
  278. '*** Prepare the Zenity command and execute, check for good return
  279.  
  280.     cmd = "zenity --text-info " + _
  281.           " --title=" + CHR$(34) + "EBAC Blood Alcohol Calculator" + CHR$(34) + _
  282.           " --width=525 --height=400" + _
  283.           " --filename=tempfile" + _
  284.           " --checkbox=" + CHR$(34) + "I agree that this program and its results are not legally binding." + CHR$(34)
  285.  
  286.     result = SHELL(cmd)
  287.  
  288.     IF result = 1 THEN
  289.         result = SHELL("zenity --warning --text=" + CHR$(34) + "You must agree to the terms of use. Please check the confirmation box." + CHR$(34) + " --width=175 --height=100")
  290.         GOTO displayEBAC
  291.     END IF
  292.  
  293.     result = SHELL("zenity --question --text=" + CHR$(34) + "Do you want to run another calculation?" + CHR$(34) + " --width=175 --height=100")
  294.     IF result = 0 THEN
  295.         SHELL ("rm tempfile")
  296.         GOTO EBACForm
  297.     END IF
  298.  
  299. endPROG:
  300.     SHELL ("rm tempfile")
  301.     result = SHELL("zenity --info --text=" + CHR$(34) + "Thank You for using EBAC Calculator. Please Don't Drink and Drive." + CHR$(34) + " --width=175 --height=100")
  302.     END
  303.  
  304.  
  305. FUNCTION calcEBAC
  306. '-------------------------------------------------------------
  307. '*** Convert Drinks into Fluid Ounces of EtOH (Pure Alcohol).
  308. '*** A is number of drinks. 1 drink is about .6 FLoz of alcohol
  309.     FLoz = A * OZ
  310.  
  311. '-----------------------------------------------------
  312. '*** Set/calculate EBAC values based on Sex
  313.     SELECT CASE Sex
  314.         CASE "M"
  315.             B = .017
  316.             EBAC = 7.97 * FLoz / Wt - B * T
  317.         CASE "F"
  318.             B = .019
  319.             EBAC = 9.86 * FLoz / Wt - B * T
  320.     END SELECT
  321.  
  322.     IF EBAC < 0 THEN EBAC = 0
  323.  
  324. '----------------------------------------------------------------------------------------------
  325. '*** Populate the EBAC string with the EBAC value formatted to 3 decimal places for FORM output
  326. '    prt_text = "ESTIMATED BLOOD ALCOHOL CONTENT (EBAC) in g/dL = " + EBAC_ST$ + CHR$(10) + CHR$(10)
  327.     prt_text = "" + CHR$(10)
  328.  
  329. '-----------------------------------------------------------------------------------------
  330. '*** Based on EBAC range values, populate the FORM output string with the approriate text
  331.     SELECT CASE EBAC
  332.         CASE .500 TO 1.9999
  333.             prt_text = prt_text + "*** ALERT: CALL AN AMBULANCE, DEATH LIKELY" + CHR$(10)
  334.             prt_text = prt_text + "Unconsious/coma, unresponsive, high likelihood of death. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  335.         CASE .400 TO .4999
  336.             prt_text = prt_text + "*** ALERT: CALL AN AMBULANCE, DEATH POSSIBLE" + CHR$(10)
  337.             prt_text = prt_text + "Onset of coma, and possible death due to respiratory arrest. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  338.         CASE .350 TO .3999
  339.             prt_text = prt_text + "*** ALERT: CALL AN AMBULANCE, SEVERE ALCOHOL POISONING" + CHR$(10)
  340.             prt_text = prt_text + " Coma is possible. This is the level of surgical anesthesia. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  341.         CASE .300 TO .3499
  342.             prt_text = prt_text + "*** ALERT: YOU ARE IN A DRUNKEN STUP0R, AT RISK TO PASSING OUT" + CHR$(10)
  343.             prt_text = prt_text + "STUPOR. You have little comprehension of where you are. You may pass out suddenly and be difficult to awaken. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  344.         CASE .250 TO .2999
  345.             prt_text = prt_text + "*** ALERT: SEVERLY IMPAIRED - DRUNK ENOUGH TO CAUSE SEVERE INJURY/DEATH TO SELF" + CHR$(10)
  346.             prt_text = prt_text + "All mental, physical and sensory functions are severely impaired. Increased risk of asphyxiation from choking on vomit and of seriously injuring yourself by falls or other accidents. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  347.         CASE .200 TO .2499
  348.             prt_text = prt_text + "YOU ARE EXTREMELY DRUNK" + CHR$(10)
  349.             prt_text = prt_text + "Feeling dazed/confused or otherwise disoriented. May need help to stand/walk. If you injure yourself you may not feel the pain. Some people have nausea and vomiting at this level. The gag reflex is impaired and you can choke if you do vomit. Blackouts are likely at this level so you may not remember what has happened. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  350.         CASE .160 TO .1999
  351.             prt_text = prt_text + "YOUR ARE SEVERLY DRUNK - ENOUGH TO BECOME VERY SICK" + CHR$(10)
  352.             prt_text = prt_text + "Dysphoria predominates, nausea may appear. The drinker has the appearance of a 'sloppy drunk.' It is illegal to operate a motor vehicle at this level of intoxication in all states." + CHR$(10) + CHR$(10)
  353.             prt_text = prt_text + "* Dysphoria: An emotional state of anxiety, depression, or unease."
  354.         CASE .130 TO .1599
  355.             prt_text = prt_text + "YOU ARE VERY DRUNK - ENOUGH TO LOSE PHYSICAL & MENTAL CONTROL" + CHR$(10)
  356.             prt_text = prt_text + "Gross motor impairment and lack of physical control. Blurred vision and major loss of balance. Euphoria is reduced and dysphoria* is beginning to appear. Judgment and perception are severely impaired. It is illegal to operate a motor vehicle at this level of intoxication in all states." + CHR$(10) + CHR$(10)
  357.             prt_text = prt_text + "* Dysphoria: An emotional state of anxiety, depression, or unease."
  358.         CASE .100 TO .1299
  359.             prt_text = prt_text + "YOU ARE LEGALLY DRUNK" + CHR$(10)
  360.             prt_text = prt_text + "Significant impairment of motor coordination and loss of good judgment. Speech may be slurred; balance, vision, reaction time and hearing will be impaired. Euphoria. It is illegal to operate a motor vehicle at this level of intoxication in all states."
  361.         CASE .070 TO .0999
  362.             prt_text = prt_text + "YOU MAY BE LEGALLY DRUNK" + CHR$(10)
  363.             prt_text = prt_text + "Slight impairment of balance, speech, vision, reaction time, and hearing. Euphoria. Judgment and self-control are reduced, and caution, reason and memory are impaired (in some* states .08 is legally impaired and it is illegal to drive at this level). You will probably believe that you are functioning better than you really are." + CHR$(10) + CHR$(10)
  364.             prt_text = prt_text + "(*** As of July, 2004 ALL states had passed .08 BAC Per Se Laws. The final one took effect in August of 2005.)"
  365.         CASE .040 TO .0699
  366.             prt_text = prt_text + "YOU MAY BE LEGALLY BUZZED" + CHR$(10)
  367.             prt_text = prt_text + "Feeling of well-being, relaxation, lower inhibitions, sensation of warmth. Euphoria. Some minor impairment of reasoning and memory, lowering of caution. Your behavior may become exaggerated and emotions intensified (Good emotions are better, bad emotions are worse)"
  368.         CASE .020 TO .0399
  369.             prt_text = prt_text + "YOU MAY BE OK TO DRIVE, BUT IMPAIRMENT BEGINS" + CHR$(10)
  370.             prt_text = prt_text + "No loss of coordination, slight euphoria and loss of shyness. Depressant effects are not apparent. Mildly relaxed and maybe a little lightheaded."
  371.         CASE .000 TO .0199
  372.             prt_text = prt_text + "YOU ARE OK TO DRIVE" + CHR$(10)
  373.     END SELECT
  374.  
  375. '-----------------------------------------------------------
  376. '*** Determine if Drunk (>.08 EBAC) and calculate:
  377. '***    - When user will be less than .08
  378. '***    - How long it will take to become completely sober
  379.     IF EBAC > .08 THEN
  380.         SOBER = FALSE
  381.         CEBAC = EBAC
  382.         st = T
  383.         DO UNTIL SOBER = TRUE
  384.             T = T + 1
  385.             IF CEBAC > .0799 THEN I = I + 1
  386.  
  387.             SELECT CASE Sex
  388.                 CASE "M"
  389.                     B = .017
  390.                     CEBAC = 7.97 * FLoz / Wt - B * T
  391.                 CASE "F"
  392.                     B = .019
  393.                     CEBAC = 9.86 * FLoz / Wt - B * T
  394.             END SELECT
  395.  
  396.             IF legalToDrive = FALSE THEN
  397.                 IF CEBAC < .08 THEN
  398.                     prt_text = prt_text + CHR$(10) + CHR$(10) + "It will take about " + STR$(I) + " hours from your last drink to be able to drive." + CHR$(10)
  399.                     legalToDrive = TRUE
  400.                 END IF
  401.             END IF
  402.  
  403.             IF CEBAC <= 0 THEN
  404.                 prt_text = prt_text + "It will take about " + STR$(T - st) + " hours from your last drink to be completely sober."
  405.                 SOBER = TRUE
  406.             END IF
  407.         LOOP
  408.     END IF
  409.  
  410.  
  411.  
  412. FUNCTION ISNUMERIC (A$)
  413. '-----------------------------------------------------
  414. '*** Numeric Check of a STRING
  415.     l = LEN(A$)
  416.     FOR I = 1 TO l
  417.         ACODE = ASC(A$, I)
  418.         IF numeric(ACODE) THEN
  419.             ISNUMERIC = TRUE
  420.         ELSE
  421.             ISNUMERIC = FALSE
  422.             EXIT FUNCTION
  423.         END IF
  424.     NEXT I
  425.  
  426.  
  427. '$INCLUDE:'pipecomqb64.bas'
  428.  

 

13
QB64 Discussion / Zenity and QB64
« on: June 18, 2021, 04:08:23 pm »
I'm not sure if this is me, QB64, Zenity, pipecom, or a mixture of all.

I took an example from the Zenity documentation, and it is presenting me with garbage. Here is the code from the documentation, my QB64 code, and a screen print of what I am getting.

I originally had all the parameters in, but I removed the "--title" and the ">> addr.csv" and reordered it the same way as the code given to me by Spriggs, with no changes in my results.

The commented out part works fine (It is Spriggs code that was provided).

From Zenity Documentation (just the portion of the BASH script that is the call to Zenity):
Code: [Select]
zenity --forms --title="Add Friend" \
--text="Enter information about your friend." \
--separator="," \
--add-entry="First Name" \
--add-entry="Family Name" \
--add-entry="Email" \
--add-calendar="Birthday" >> addr.csv

QB64:
Code: QB64: [Select]
  1. '$CONSOLE:ONLY
  2. '_DEST _CONSOLE
  3. DIM AS STRING email, dates, other, form, birthday, firstname, lastname
  4.  
  5. 'form = pipecom_lite("zenity --forms --add-entry=" + CHR$(34) + "Email" + CHR$(34) + _
  6. '                    " --add-calendar=" + CHR$(34) + "Pick date" + CHR$(34) + _
  7. '                    " --text=" + CHR$(34) + "This is a form made in zenity" + CHR$(34) + _
  8. '                    " --add-entry=" + CHR$(34) + "Ultimate Haxxor" + CHR$(34) _
  9. '                    )
  10.  
  11.  
  12. form = pipecom_lite( _
  13.                     "zenity --forms --add-entry=" + CHR$(34) + "First Name" + CHR$(34) + _
  14.                     "--add-calendar=" + CHR$(34) + "Birthday" + CHR$(34) + _
  15.                     "--text=" + CHR$(34) + "Enter information about your friend." + CHR$(34) + _
  16.                     "--add-entry=" + CHR$(34) + "Last Name" + CHR$(34) + _
  17.                     "--add-entry=" + CHR$(34) + "Email" + CHR$(34) _
  18.                     )
  19.  
  20.  
  21.  
  22. 'email = MID$(form, 1, INSTR(form, "|") - 1)
  23. 'PRINT email
  24. 'form = MID$(form, INSTR(form, "|") + 1)
  25. 'dates = MID$(form, 1, INSTR(form, "|") - 1)
  26. 'PRINT dates
  27. 'other = MID$(form, INSTR(form, "|") + 1)
  28. 'PRINT other
  29.  
  30. '$INCLUDE:'pipecomqb64.bas'

Here is the run results:
  [ You are not allowed to view this attachment ]  

14
QB64 Discussion / PRINT USING Bug?
« on: June 01, 2021, 08:09:01 pm »
In researching for the post on 128bit numbers, I've isolated the following code and believe that this is a bug.

I am running on Linux Ubuntu 20.04.2 LTS, and screen print is attached.

I am print the following number: 10.349449797507

And regardless of whether I use FLOAT, DOUBLE or SINGLE type, if my program prints this out with a USING mask, I get garbage after the end of the number.

There are occasions where your mask must be larger than a number because a program may not know how big or small the number you are to PRINT.

This should not happen. The rest of the mask after the last digit should be all ZEROES.

The screen print shows the various values printed after the valid end of the number.

Code: QB64: [Select]
  1. DIM result AS _FLOAT
  2. DIM answer AS DOUBLE
  3. DIM result2 AS SINGLE
  4.  
  5.  
  6. result = 10.349449797507
  7. answer = 10.349449797507
  8. result2 = 10.349449797507
  9.  
  10. PRINT USING "The value is:  ###.#########################"; result
  11. PRINT USING "The value is:  ###.#########################"; answer
  12. PRINT USING "The value is:  ###.#########################"; result2

  [ You are not allowed to view this attachment ]  

15
Programs / Poem Generator
« on: May 27, 2021, 09:39:43 pm »
This is a simple poem generator, with some grammar/vocabulary rules.

There is no limit to how this program can grow.

I also attached the source, just in case you do not want the 3 or so spaces that are inserted when selecting/copying the source from the code box.

It is well commented. Have fun.

Code: QB64: [Select]
  1. _TITLE "Poem Generator"
  2. '*******************************************************************************
  3. '*** Poem Generator
  4. '*** By George McGinn - May 27, 2021
  5. '***
  6. '***
  7. '*** About the AI system
  8. '***    Since writing poems has specific rules, which can easily break grammar
  9. '***    rules, the AI will impose just the basic grammar syntax, like adding a
  10. '***    "an" when required, and not ending sentences with words such as
  11. '***    "like" which happens now. They will have a special modifier tag as with
  12. '***    the tables in use, one of them can be used to finish the sentence.
  13. '***
  14. '***    However, poems do not follow strict sentence structure either, and like
  15. '***    at the end of a line, since there is no period, it may be a pause where
  16. '***    the first words on the next continues the thought. This will be
  17. '***    built into the modifier tag. It will also check the words ahead of it to
  18. '***    see if they are on the modifier list for the word "like" and others like
  19. '***    it.
  20. '***
  21. '***    So due to the special circumstances on meter and rhyme and even the
  22. '***    structure of the poem, the AI system will rely heavily on rule and word
  23. '***    tables that will provide it the words, apply modifiers, check for any
  24. '***    grammar changes, and will have a way to keep the poem on one theme.
  25. '***
  26. '***    And for this system to work properly, the vocabulary must grow to
  27. '***    proportions where each word has associated tags for use with other words
  28. '***    to help the AI engine to keep the poem on target.
  29. '***
  30. '*******************************************************************************
  31.  
  32.  
  33. 'SCREEN 12
  34. SCREEN _NEWIMAGE(800, 600, 32)
  35. DEFINT A-Z
  36.  
  37.  
  38. '***************************************************************
  39. '*** Initialize variables/arrays (comments to prevent confusion)
  40. '***
  41. x = 0 '* Index to poem length (# lines)
  42. i = 0 '* Index to loading Arrays
  43.  
  44. cr$ = CHR$(10) '* Add a Carriage-Return character
  45.  
  46. Author$ = "By QB64 Program" '* Name of Programmer running code
  47.  
  48. DIM article$(35), noun$(60), verb$(46), adjective$(46)
  49. DIM colormodifier$(28), colortable$(8), nounmodifiers$(14)
  50. DIM connectives$(151), conective_extended$(34)
  51.  
  52.  
  53. '**************************************************
  54. '*** Load Arrays from Data Statements
  55. '***
  56.  
  57. GOSUB LoadWordArrays
  58.  
  59.  
  60. '**************************************************
  61. '*** Pick a 2- to 3-word title
  62. '***
  63. ta$ = article$(INT(RND * 35) + 1)
  64. b$ = LCASE$(noun$(INT(RND * 60) + 1)) '** Pick a primary noun
  65. b1$ = LCASE$(noun$(INT(RND * 60) + 1)) '** Pick a noun-color modifier
  66. c$ = LCASE$(verb$(INT(RND * 46) + 1)) '** Pick a primary verb
  67. c1$ = LCASE$(verb$(INT(RND * 46) + 1)) '** Pick a verb modifier
  68. d$ = LCASE$(adjective$(INT(RND * 46) + 1)) '** Pick an adjective
  69. bc$ = LCASE$(colormodifier$(INT(RND * 28) + 1)) '** Pick a modifier for a color
  70. color$ = LCASE$(colortable$(INT(RND * 8) + 1)) '** Pick a color as a modifier
  71. nounmod$ = LCASE$(nounmodifiers$(INT(RND * 14) + 1)) '** Pick a non-color noun modifier
  72.  
  73. IF LEFT$(b$, 1) = "@" OR LEFT$(b1$, 1) = "@" THEN GOSUB CheckForCapitalization
  74. IF RIGHT$(b$, 1) = "*" OR RIGHT$(b$, 1) = "+" THEN GOSUB CheckForModifierAfter
  75. IF LEFT$(b$, 1) = "*" OR LEFT$(b$, 1) = "+" THEN GOSUB CheckForModifierBefore
  76. tb$ = b$
  77.  
  78. Title$ = ta$ + " " + tb$
  79.  
  80.  
  81. '**************************************************
  82. '*** Create the poem, 16 lines in 4 4-line stanzas
  83. '***
  84.  
  85. PRINT SPACE$(3) + Title$
  86. PRINT SPACE$(3) + Author$
  87.  
  88.  
  89. '*** NOTE: b1 & c1 placeholders for future use as modifiers, or
  90. '***       to initially use b1 & c1 as modifiers themselves.
  91. FOR x = 1 TO 16
  92.     a$ = LCASE$(article$(INT(RND * 35) + 1)) '** Pick an Article
  93.     b$ = LCASE$(noun$(INT(RND * 60) + 1)) '** Pick a primary noun
  94.     b1$ = LCASE$(noun$(INT(RND * 60) + 1)) '** Pick a noun-color modifier
  95.     c$ = LCASE$(verb$(INT(RND * 46) + 1)) '** Pick a primary verb
  96.     c1$ = LCASE$(verb$(INT(RND * 46) + 1)) '** Pick a verb modifier
  97.     d$ = LCASE$(adjective$(INT(RND * 46) + 1)) '** Pick an adjective
  98.     bc$ = LCASE$(colormodifier$(INT(RND * 28) + 1)) '** Pick a modifier for a color
  99.     color$ = LCASE$(colortable$(INT(RND * 8) + 1)) '** Pick a color as a modifier
  100.     nounmod$ = LCASE$(nounmodifiers$(INT(RND * 14) + 1)) '** Pick a non-color noun modifier
  101.  
  102.     '*** Check for modifiers to nouns
  103.     IF LEFT$(b$, 1) = "@" OR LEFT$(b1$, 1) = "@" OR LEFT$(bc$, 1) = "@" THEN GOSUB CheckForCapitalization
  104.     IF LEFT$(b$, 1) = "*" OR LEFT$(b$, 1) = "+" THEN GOSUB CheckForModifierBefore
  105.     IF RIGHT$(b$, 1) = "*" OR RIGHT$(b$, 1) = "+" THEN GOSUB CheckForModifierAfter
  106.  
  107.     '*** Capitalize the first word of each sentence or stanza (whether noun or verb)
  108.     r = RND(2) + 1
  109.     IF r = 1 THEN
  110.         z = LEN(a$)
  111.         a$ = UCASE$(LEFT$(a$, 1)) + RIGHT$(a$, z - 1)
  112.         Line$ = a$ + " " + b$ + " " + c$ + " " + d$
  113.     ELSE
  114.         z = LEN(c$)
  115.         c$ = UCASE$(LEFT$(c$, 1)) + RIGHT$(c$, z - 1)
  116.         Line$ = c$ + " " + b$ + " " + d$
  117.     END IF
  118.     IF x MOD 4 = 0 THEN Line$ = Line$ + "." + cr$
  119.     PRINT SPACE$(3) + Line$
  120.  
  121.  
  122. endPROG:
  123. '**************************************************
  124. '*** Print Copyright and Date/Time Stamp and END
  125. '***
  126.  
  127. mnth$ = LEFT$(DATE$, 2): M = VAL(mnth$)
  128. day$ = MID$(DATE$, 4, 2): D = VAL(day$)
  129. day$ = STR$(D) ' eliminate any leading zeros
  130. year$ = RIGHT$(DATE$, 4): Y = VAL(year$)
  131.  
  132.     CASE 1: Month$ = "January"
  133.     CASE 2: Month$ = "February"
  134.     CASE 3: Month$ = "March"
  135.     CASE 4: Month$ = "April"
  136.     CASE 5: Month$ = "May"
  137.     CASE 6: Month$ = "June"
  138.     CASE 7: Month$ = "July"
  139.     CASE 8: Month$ = "August"
  140.     CASE 9: Month$ = "September"
  141.     CASE 10: Month$ = "October"
  142.     CASE 11: Month$ = "November"
  143.     CASE 12: Month$ = "December"
  144.  
  145.  
  146. '*** Copyright Sign (Character, Unicode, UTF-8 Values
  147. '***
  148.  
  149. PRINT: PRINT: PRINT SPACE$(3) + "(C)2021 " + Author$ + " (if it is good), All Rights Reserved"
  150. PRINT SPACE$(3) + "Created " + WeekDay$(M, D, Y) + ", " + Month$ + day$ + ", " + year$ + " at " + Clock$
  151.  
  152.  
  153.  
  154. '***
  155. '*** END OF MAIN PROGRAM
  156. '*******************************************************************
  157.  
  158.  
  159. '*******************************************************************
  160. '*** FUNCTIONS/SUB ROUTINES
  161. '***
  162.  
  163.  
  164. LoadWordArrays:
  165. '**************************************************
  166. '*** Load Arrays from Data Statements
  167. '***
  168.  
  169. '*** Load Articles
  170.     FOR i = 1 TO 35: READ article$(i): NEXT i
  171.  
  172. '*** Load Nouns
  173.     FOR i = 1 TO 60: READ noun$(i): NEXT i
  174.  
  175. '*** Load Verbs
  176.     FOR i = 1 TO 46: READ verb$(i): NEXT i
  177.  
  178. '*** Load Adjectives
  179.     FOR i = 1 TO 46: READ adjective$(i): NEXT i
  180.  
  181. '*** Load Color Modifiers
  182.     FOR i = 1 TO 28: READ colormodifier$(i): NEXT i
  183.  
  184. '*** Load Color Table
  185.     FOR i = 1 TO 7: READ colortable$(i): NEXT i
  186.  
  187. '*** Load Noun Modifiers
  188.     FOR i = 1 TO 14: READ nounmodifiers$(i): NEXT i
  189.  
  190. '*** Load Connectives
  191.     FOR i = 1 TO 151: READ connectives$(i): NEXT i
  192.  
  193. '*** Load Contective Extended
  194.     FOR i = 1 TO 34: READ conective_extended$(i): NEXT i
  195.  
  196.  
  197.  
  198.  
  199. CheckForCapitalization:
  200. '*** Check for modifiers (@=Capitalize Word)
  201. IF LEFT$(b$, 1) = "@" THEN
  202.     z = LEN(b$)
  203.     b$ = RIGHT$(b$, z - 1)
  204.     b$ = UCASE$(LEFT$(b$, 1)) + RIGHT$(b$, z - 2)
  205. IF LEFT$(b1$, 1) = "@" THEN
  206.     z = LEN(b1$)
  207.     b1$ = RIGHT$(b1$, z - 1)
  208.     b1$ = UCASE$(LEFT$(b1$, 1)) + RIGHT$(b1$, z - 2)
  209. IF LEFT$(bc$, 1) = "@" THEN
  210.     z = LEN(bc$)
  211.     bc$ = RIGHT$(bc$, z - 1)
  212.     bc$ = UCASE$(LEFT$(bc$, 1)) + RIGHT$(bc$, z - 2)
  213.  
  214.  
  215.  
  216. CheckForModifierBefore:
  217. '*** Check for modifiers Before
  218.  
  219. '*** "*" the noun needs a color before it
  220. IF LEFT$(b$, 1) = "*" THEN
  221.     z = LEN(b$)
  222.     b$ = RIGHT$(b$, z - 1)
  223.     b$ = color$ + " " + b$
  224.  
  225. '*** "+" the noun needs another noun to follow it (selection from noun modifier)
  226. IF RIGHT$(b$, 1) = "+" THEN
  227.     z = LEN(b$)
  228.     b$ = LEFT$(b$, z - 1)
  229.     b$ = nounmod$ + " " + b$
  230.  
  231.  
  232.  
  233. CheckForModifierAfter:
  234. '*** Check for modifiers after
  235.  
  236. '*** "*" the noun is a color and only color-friendly nouns considered
  237. IF RIGHT$(b$, 1) = "*" THEN
  238.     z = LEN(b$)
  239.     b$ = LEFT$(b$, z - 1)
  240.     b$ = b$ + " " + bc$
  241.  
  242. '*** "+" the noun needs another noun to follow it (selection from noun modifier)
  243. IF RIGHT$(b$, 1) = "+" THEN
  244.     z = LEN(b$)
  245.     b$ = LEFT$(b$, z - 1)
  246.     b$ = b$ + " " + nounmod$
  247.  
  248.  
  249.  
  250.  
  251. '**************************************************
  252. '*** DATA Statements for Poem Generator
  253. '***
  254.  
  255. '*** 35 Articles
  256. articles:
  257. DATA "The","All of the","Most of the","Some of the"
  258. DATA "My","Your","His","Her","Their","Our","Everybody's","Almost all of the"
  259. DATA "That","I knew that the","We knew that the","She knew that the","He knew that the","They knew that the","And the coming","Oh, the","A spring of","Beyond the","Within the","And the","Alone, alone,","I fear","I looked upon","A","But where the","Like","A still and","Alone","All alone, a","The moving","It is"
  260.  
  261.  
  262. '*** 60 Nouns
  263. nouns:
  264. DATA "darkness","morning","morning+","light","feeling","feeling+","beauty","love","hatred","happiness","sadness","anger","frustration","expression","message","ship","lips","mouth","voice","garment","saint","snake","snakes","water","fire","lead","dreams","air","ghost","sails","sleep","river","cloud","@moon","@sun","waters","life","stars","the stars","lightning","beams","beams+","*beard","fool","white*","black*","green*","blue*","yellow*","red*","light beams","*river","*garment","*ship","*snake","*snakes","*sails","voice+","ship+","ocean blue"
  265.  
  266.  
  267. '*** 46 Verbs (lv)
  268. verbs:
  269. DATA "was","had been","will be","could be","might be","should have been","would have been","could have been","drunk","drank","was heavenly","a heavy","blessed","glossy","velvet","flash","kind","coiled","swarm","swarmed","fire","pity","filled","fill","moved","wind","danced","steep","wide","steep and wide","thick","light","roar","loud","more loud","lightning","struck","fell","more horrible","horrible","awful","hit","huge","holds","long","surrounds"
  270.  
  271.  
  272. '*** 46 Adjectives/adverbs
  273. adjectives:
  274. DATA "abstract","mysterious","permanent","unfortunate","was unfortunate"
  275. DATA "intricate","confusing","serene","confusing"
  276. DATA "true","false","fake","a lie","burden"
  277. DATA "a stranger","a friend","an enemy"
  278. DATA "terrible","enchanting","is mine","was yours","is his","is hers","was theirs","was ours"
  279. DATA "fortunate","was understood","mine","is mutual","with an artistic flair","was musical"
  280. DATA "golden pond","blessed","moment","unaware","no","yes","sure"
  281. DATA "like","dreams","between","inbetween","alone","than that","interesting","glossy lake"
  282.  
  283.  
  284. '*** 28 Color modifiers
  285. colormodifiers:
  286. DATA "morning","light","beauty","love","ship","lips","garment","knight","saint","snake","snakes","water","fire","ghost","sails"
  287. DATA "river","cloud","@moon","@sun","waters","stars","lightning","beams","beard","velvet","flash","grass","book"
  288.  
  289.  
  290. '*** 8 Color table entries
  291. colortable:
  292. DATA "red","yellow","blue","green","white","black","orange","purple"
  293.  
  294.  
  295. '*** 14 Noun Modifier Table (Nouns, Verbs/Adverbs, Adjectives)
  296. nounmodifier:
  297. DATA "sunshine","light","glow","fog","of peace","of love","blue","great","unloved","sad","happy","loved","of light","of love"
  298.  
  299. '*** 151 Connectives
  300. connectives:
  301. DATA "I","the","of","and","to","a","in","that","is","was","he","for","it"
  302. DATA "with","as","his","on","be","at","by","i","this","had","not"
  303. DATA "are","but","from","or","have","an","they","which","one","you","were"
  304. DATA "her","all","she","there","would","their","we","him","been","has"
  305. DATA "when","who","will","more","no","if","out","so","said","what","u","its","about"
  306. DATA "into","than","them","can","only","other","new","some","could","time","these"
  307. DATA "two","may","then","do","first","any","my","now","such","like","our"
  308. DATA "over","man","me","even","most","made","after","also","did","many","before","must"
  309. DATA "through","back","years","where","much","your","way","well","down","should"
  310. DATA "because","each","just","those","people","mr","how","too","little"
  311. DATA "state","good","very","make","world","still","own","see","men","work","long"
  312. DATA "get","here","between","both","life","being","under","never","day","same"
  313. DATA "another","know","while","last","might","us","great","old","year","off"
  314. DATA "come","since","against","go","came","right","used","take","three"
  315.  
  316. '*** 34 Extened Connectives:
  317. connectives_extend:
  318. DATA "whoever","nonetheless","therefore","although","consequently","furthermore"
  319. DATA "whereas","nevertheless","whatever","however","besides","henceforward","yet"
  320. DATA "until","alternatively","meanwhile","notwithstanding","whenever"
  321. DATA "moreover","despite","similarly","firstly","secondly","lastly","eventually"
  322. DATA "gradually","finally","thus","hence","accordingly","otherwise","indeed"
  323. DATA "though","unless"
  324.  
  325.  
  326.  
  327.  
  328. '*******************************************************************
  329. '*** FUNCTIONS (FORMAT DATE AND TIME FIELDS)
  330. '***
  331.  
  332.  
  333. FUNCTION WeekDay$ (M, D, Y)
  334.     IF M < 3 THEN M = M + 12: Y = Y - 1 'add 12 to Jan - Feb month, -1 year
  335.     C = Y \ 100: Y = Y MOD 100 'split century and year number
  336.     S1 = (C \ 4) - (2 * C) - 1 'century leap
  337.     S2 = (5 * Y) \ 4 '4 year leap
  338.     S3 = 26 * (M + 1) \ 10 'days in months
  339.     WkDay = (S1 + S2 + S3 + D) MOD 7 'weekday total remainder
  340.     IF WkDay < 0 THEN WkDay = WkDay + 7 'Adjust negative results to 0 to 6
  341.     SELECT CASE WkDay
  342.         CASE 0: day$ = "Sunday"
  343.         CASE 1: day$ = "Monday"
  344.         CASE 2: day$ = "Tuesday"
  345.         CASE 3: day$ = "Wednesday"
  346.         CASE 4: day$ = "Thursday"
  347.         CASE 5: day$ = "Friday"
  348.         CASE 6: day$ = "Saturday"
  349.     END SELECT
  350.     WeekDay$ = day$
  351.  
  352.  
  353. FUNCTION Clock$
  354.     hour$ = LEFT$(TIME$, 2): H% = VAL(hour$)
  355.     min$ = MID$(TIME$, 3, 3)
  356.     IF H% >= 12 THEN ampm$ = " pm" ELSE ampm$ = " am"
  357.     IF H% > 12 THEN
  358.         IF H% - 12 < 10 THEN hour$ = STR$(H% - 12) ELSE hour$ = LTRIM$(STR$(H% - 12))
  359.     ELSEIF H% = 0 THEN hour$ = "12" ' midnight hour
  360.     ELSE: IF H% < 10 THEN hour$ = STR$(H%) ' eliminate leading zeros
  361.     END IF
  362.     Clock$ = hour$ + min$ + ampm$

Pages: [1] 2