Historic frequency based random lotto number generator.

This example is a little program to generate random numbers based on historic lotto results. Each potential result pull is weighted based on past results.

The full project is available on GitHub here.

First, we need to store the historic data. In this case I use an instance of SortedDictionary.

int totalBallsNeeded = 6; //5 plus the extra shot
int doubleBallCount = 104; //52 numbers times 2

SortedDictionary<int, int> lottoNumberFrequencyTable = new SortedDictionary<int, int>();
lottoNumberFrequencyTable.Add(1, 29);
lottoNumberFrequencyTable.Add(2, 34);
//...
lottoNumberFrequencyTable.Add(52, 38);

There is a possible range of 01 to 52 lotto values. I pulled the frequency data from online sources. In this case the key is the lotto number and the value is the frequency.

After the data is stored, we do the actual random number generation with weighted frequency.

The array we link our random numbers to is twice as large as the total number of lotto possibilities. Inside two array index related to one lotto number.

That means for lotto #01 index 0 and index 1 will store the values 0 to 29.
For lotto #02 it will be associated to index 2 and index 3 with values 30 to 64.

//add up the total range of frequencies 
int totalFrequencyCount = 0;

//an array that will hold frequency ranges for all possible balls
//eg: [0][1] is for ball 01 with two associated array entries: [0] = 0 and [1] = 29
//for ball 02 it would be [2] = 30 and [3] = 64 for that range
int[] frequencyBlocks = new int[doubleBallCount];


//keep track of which set of array entries we are working on
int frequencyBlocksCounter = 0;
            
foreach (KeyValuePair<int, int> entry in lottoNumberFrequencyTable.ToArray())
{
    //generate block of numbers for weighted RNG

    //the starting point value for this lotto number
    frequencyBlocks[frequencyBlocksCounter] = totalFrequencyCount++;
                
    //increment the total frequency count variable to prep for the next step
    totalFrequencyCount += entry.Value;

    //the ending point for this lotto number
    frequencyBlocks[frequencyBlocksCounter + 1] = totalFrequencyCount;

    //jump to the next set of array entries
    frequencyBlocksCounter += 2; 
}
            
//fire up a random number generator
Random r = new Random();

//clear our result display text box
textBox1.Text = "";

//due to needing unique numbers, we need to track our successful pulls
int totalBallsSelected = 0;

//a place to store our successful pulls
List<int> selectedBallValues = new List<int>();

//get our six weighted random values with no duplicates
while(totalBallsSelected < totalBallsNeeded)
{
    //get a random number between 1 and the total sample size
    int randInRange = r.Next(1, totalFrequencyCount);

    //get a weighted random number result
    //loop through our custom array
    int currentBall = 1;
    for(int j = 0; j < doubleBallCount; j += 2)
    {
        //find which block of weighted frequency this random number should fit in
        //once found that range will relate back to a lotto number
        if (randInRange >= frequencyBlocks[j] && randInRange < frequencyBlocks[j + 1])
        {
            //don't allow duplicates
            if(!selectedBallValues.Contains(currentBall))
            {
                //save the successful pull into our result class instance
                selectedBallValues.Add(currentBall);
                totalBallsSelected++;
            }
            break; //exit the inner for loop after a successful pull
        }
        else
        {
            //after a successful pull, increment our total result counter
            currentBall++;
        }
    }
}

When we get a random number, it will fit into our double wide array. Looping through each time to find where in the array it should fit. Once that index is found it related back to the actual lotto number. This happens as long as it takes to get 6 entries that are unique.

Posted in General | Tagged , , , , | Comments

Updating the Raspberry PI GIT server.

I took time to refresh my Raspberry PI GIT server. I am still using the v1 board, but with a few upgrades and modifications. It was more to streamline the entire package instead of performance upgrades.

Changes:
– I bought a half-height SD to Micro SD adapter. This makes it stick out less from the case. Sadly it’s not totally flush, but better at least. Along with that I upgraded to a 64GB micro SD card from a 32GB SD card.
– I upgraded the backup drives with 64GB Lexar JumpDrives (S45 LJDS45-64GABNL). They are super compact and had decent reviews. I decided to skip the RAID 01 mirroring approach with these. It simplifies things and there really isn’t any drawback besides maybe hot swap (which I don’t think would work because fstab uses unique drive identifiers).
– I picked up another power supply on a whim when I saw it at the store “Five Below” for a great price. This again streamlines things over my previous setup that was combo type where you would plug in a USB cable into the unit. In this case it’s one single piece. The maximum amp rating on it is 2.4 amps, which is great for $5.
– I drilled vent holes into the top case as seen in the photos. I might add more in the future, but I thought at least a few would be good.

Anything over 32GB will require an extra formatting step detailed here. The current install takes the user directly to the GUI operating system after it is finished setting things up. You need to go into the start (raspberry) button >> “Preferences” >> “Raspberry Pi Configuration” to find options. From there you can switch it up to boot from the command line instead of the GUI.

Once you are at a command prompt you can do this to enable SSH:
– Enter sudo raspi-config in a terminal window
– Select Interfacing Options
– Navigate to and select SSH
– Choose Yes
– Select Ok
– Choose Finish

Once you are setup, you can slim down what NOOBS pre-installs into the OS thanks to this person who made this script.

Download PuTTY for SSH (used for the remote command line interface):
http://www.putty.org/
A Windows installer for everything except PuTTYtel

Download and install Window GIT:
https://git-for-windows.github.io/

Download and install Tortoise GIT:
https://tortoisegit.org/

Linking RP and your client with source code:
Create the local repository by adding a folder to your computer and right-clicking on it and selecting “Git create repository here…” from the context menu. Have it make a standard setup (not bare).

Generate your SSH keys:
Use Puttygen to make the keys, save both the public and private keys. Name the private key with a .ppk extension.
Seems to be optional if you do everything on the same local network.

SSH to your pi:

1. install git to your pi (Should be installed, but doing it won't hurt)
sudo apt-get install git git-core
2. add a user 'git', or you can use other name
sudo adduser --system --shell /bin/bash --gecos 'git version control by pi' --group --home /home/git git
3. set the password for the new user
sudo passwd git
4. use the user 'git' to make an empty repository
su git
cd /home/git
mkdir repo.git
cd repo.git
git --bare init

Back to your working machine where you have a folder you want to push to the new GIT server:
You can use TortoiseGit to set things up.
Right-click on the main folder. Select Git Create Repository here.
Right-click >> TortoiseGIT >> Settings >> Remote…
From there you can add server details.
Remote: A name you want to call it.
URL: something like git@X.X.X.X:repo.git
Where X.X.X.X would be the IP address of the new server on your local network.
The Push URL is the same as the URL.
All of the other options can be left default unless you made a Putty Key earlier.

Setup the backup drives:
Prepare directories that you will mount your drives to.

sudo mkdir /media/usbdrive
sudo chown -R git:git /media/usbdrive
sudo chmod -R 775 /media/usbdrive
sudo setfacl -Rdm g:git:rwx /media/usbdrive
sudo setfacl -Rm g:git:rwx /media/usbdrive
sudo mkdir /media/usbdrive2
sudo chown -R git:git /media/usbdrive2
sudo chmod -R 775 /media/usbdrive2
sudo setfacl -Rdm g:git:rwx /media/usbdrive2
sudo setfacl -Rm g:git:rwx /media/usbdrive2

Figure out your USB drive IDs:
sudo blkid
(or)
ls -l /dev/disk/by-uuid/
You should see your two USB drives (sda1 and sdb1) with identifiers like XXXX-XXXX. Those are the unique IDs that we use in fstab to mount the drives. blkid will give you the type of formatting. In my case it is vfat.

Optionally, you might need different drivers that you can install such as ntfs or exfat:

sudo apt-get install ntfs-3g -y
sudo apt-get install exfat-utils -y

sudo pico /etc/fstab and add a line for each drive:

UUID=AAAA-AAAA  /media/usbdrive vfat    nofail,uid=git,gid=git   0   0
UUID=BBBB-BBBB  /media/usbdrive2 vfat    nofail,uid=git,gid=git   0   0

This should get them mounted without a reboot:
sudo mount -a

Setup crontab tasks:
crontab -e

10 * * * * /usr/bin/rsync -av -delete /home/git/repo.git/ /media/usbdrive/repo.git/ --log-file=/home/git/rc1.log
15 * * * * /usr/bin/rsync -av /home/git/repo.git/ /media/usbdrive2/repo.git/ --log-file=/home/git/rc2.log

I run a rsync task for each backup drive. The first drive will be a true mirror and the second drive will be a mirror but keep *everything* that was ever added in case the main drive ever goes bad and tries to push deletes to the backups. The only issue could be drive space, but I am not using much. If it ever became an issue, I’d just upgrade the drives again.

I switched from Unison to rsync. It’s a lot simpler to use and doesn’t run the risk of back pushing changes (eg. deleting your source code if a backup drive has issues or is accidentally cleared)

That should be about it.

————————————————
Here are some useful commands:
Calculate the size of a directory:
du -sh /home/git/repo.git

To view mail from crontab:
cat /var/spool/mail/pi

Posted in GIT, Raspberry PI | Tagged , , , | Comments

Adjusting Notepad++ to work with an ASP VBScript project.

I have a large project in classic ASP, VBScript, and Javascript. It’s a hassle dealing with it because developer tools don’t support it that well or at all. I recently poked around the open source editor Notepad++ and got it adjusted to work decently well with the project.

Check out Notepad++ on the official website here.

In the past I had used Eclipse with an old VBScript ASP syntax highlighter. It wasn’t perfect, but worked alright overall. The main issue is that the highlighting stopped working every so often, and not to mention Eclipse is bulky and a pain to use for various reasons.

Here is a screenshot of Notepad++ adjusted to work with the project:
notepadpp

Here are my main adjustments:
“View” >> “Folder as Workspace”
“View” >> “Document Map”
“View” >> “Function List”
“Settings” >> “Preferences…” >> “Editing” >> “Display line number”

The function list feature won’t work without modification. My project is broken into a large number of “.asp” files and “.js” files. Neither extensions are linked to a function parser by default.

In this case, you have to modify the two functionlist.xml files. Thanks to some enterprising individuals on sourceforge.net, I was able to find a working parser for vbscript.

Here are the approximate locations of the files on Windows:
C:\Program Files (x86)\Notepad++
C:\Users\UserName\AppData\Roaming\Notepad++

Here are the two sections of xml I added to my functionlist.xml files:

<association langID="16" id="vb_function" />
<association langID="18" id="vb_function" />
<association langID="19" id="javascript_function" />

the langID relates to programming code type extensions. In this case 16 = “.vb”, 18 = “.asp”, and 19 = “.js”. I don’t need “.vb” right now, but I put it in there anyways in case I do open them in the future.

Here is the regex/parser code from the Sourceforge.net discussion that I used:

<parser 
  id="vb_function" 
  displayName="Visual Basic (.NET|Script|for Applications)"  
  commentExpr="(?m:((?&lt;=&apos;).*?$)|((?i:REM)([\t ].*?)?$))"> 
	<classRange
		mainExpr="(?s:(?&lt;SCOPE&gt;(?i:CLASS|TYPE)).*?(?i:END[\t ]\k&lt;SCOPE&gt;))"
		displayMode="node" >
	  <className>
		<nameExpr expr="(?i:CLASS|TYPE)[\t ]+(?:[A-Za-z_][\w]*\b)(?:.*?[\r\n])" />
		<nameExpr expr="[\t ]+(?:[A-Za-z_][\w]*\b)" />
		<nameExpr expr="[A-Za-z_][\w]*" />
	  </className>
	  <function mainExpr="(?m:^[\t ]*(?i:(?:(?:PUBLIC|PRIVATE|PROTECTED|FRIEND|PROTECTED FRIEND)[\t ]+)?(?:(?:STATIC|SHARED|SHADOWS|OVERRIDABLE|OVERRIDES|READONLY|WRITEONLY)[\t ]+)?(?:SUB|FUNCTION|PROPERTY)).*?(?:\(|$))" >
		<functionName>
		  <funcNameExpr expr="(?i:(?:(?:PUBLIC|PRIVATE|PROTECTED|FRIEND|PROTECTED FRIEND)[\t ]+)?(?:STATIC[\t ]+)?(?:SUB|FUNCTION|PROPERTY)).*?(?:\(|$)"/>
		  <funcNameExpr expr="(?i:(?:SUB|FUNCTION|PROPERTY)).*?(?:\(|$)"/>
		  <funcNameExpr expr="(?i:(?:GET|LET|SET)[\t ]+)?[A-Za-z_][\w]*(?=[\t ]*\()"/>
		</functionName>
	  </function>
	</classRange>
	<function 
		mainExpr="^[\t ]*(?i:(?:(?:PUBLIC|PRIVATE|PROTECTED|FRIEND|PROTECTED FRIEND)[\t ]+)?(?:(?:STATIC|(?:DECLARE(?:[\t ]+(ANSI|UNICODE|AUTO))?))[\t ]+)?(?:SUB|FUNCTION|PROPERTY)).*?(?:\(|$)" 
		displayMode="$functionName">
	  <functionName>
		<nameExpr expr="(?i:(?:(?:PUBLIC|PRIVATE|PROTECTED|FRIEND|PROTECTED FRIEND)[\t ]+)?(?:(?:STATIC|(?:DECLARE(?:[\t ]+(?:ANSI|UNICODE|AUTO))?))[\t ]+)?(?:SUB|FUNCTION|PROPERTY)).*?(?:\(|$)"/>
			<nameExpr expr="(?i:(?:SUB|FUNCTION|PROPERTY)).*?(?:\(|$)"/>
			<nameExpr expr="(?i:(?:GET|LET|SET)[\t ]+)?[A-Za-z_][\w]*(?i:[\t ]+(LIB|ALIAS)[\t ]+[\w&quot;\.]+)*(?=[\t ]*\()"/>
	  </functionName>
	</function>
</parser>

If nothing happens, check your xml syntax. I had at first copied the regex xml without the final closing tag. There were no errors displayed by notepad++, but it just didn’t work. After fixing that it seems to be working fine. Notepad++ has very basic window and panel docking functionality. I would have preferred to have the document map and function lists side-by-side, but it only allows for one panel to be docked on each side of the window. Other than that, it looks to be a decent setup. Having syntax highlighting and a function list is a huge time saver.

Posted in ASP, Development Enviroment, Notepad++ | Tagged , , , , , , , | Comments