Our members are dedicated to PASSION and PURPOSE without drama!

BetSoftware 3 library (BetSoftwareLib)

Started by VLS, October 16, 2017, 01:42:24 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

VLS

This thread is dedicated to explaining BetSoftware 3's shared library, named BetSoftwareLib.

Learning our betting framework's inner mechanism is a must for fellow programmers to grasp how to extend it with ease.

The gist/goal being reusing as much of our code as possible to make your programming life easier as well as inter-operating with other people's code correctly since BetSoftware is a common platform for reusing each other's code :nod:
Email/Paypal: betselectiongmail.com
-- Victor

VLS

IModuleMetadata

Indicates module's game name (i.e. Roulette) + module's display name e.g. actual caption featured at the Emitter, Processor or Receiver tab.

Code (csharp) Select
namespace BetSoftware
{
    // Directives
    using System;

    /// <summary>
    /// Module metadata interface.
    /// </summary>
    public interface IModuleMetadata
    {
        /// <summary>
        /// Gets the name of the game.
        /// </summary>
        /// <value>The name of the game.</value>
        string GameName { get; }

        /// <summary>
        /// Gets the display name.
        /// </summary>
        /// <value>The display name.</value>
        string DisplayName { get; }
    }
}
Email/Paypal: betselectiongmail.com
-- Victor

VLS

There are three types of modules:

  • Emitter
  • Processor
  • Receiver

They have specific interfaces and data. Each module type is aggregated by an specific mapper.

Emitter module interface:

Code (csharp) Select
namespace BetSoftware
{
    // Directives
    using System;

    /// <summary>
    /// The emitter module interface.
    /// </summary>
    public interface IEmitterModule
    {
        /// <summary>
        /// Occurs when the on emit event is raised.
        /// </summary>
        event EventHandler<EmitEventArgs> OnEmit;

        /// <summary>
        /// Initializes using the specified history and filePath.
        /// </summary>
        /// <param name="history">Passed history.</param>
        /// <param name="filePath">File path.</param>
        void Init(History history, string filePath);
    }
}


Emit event arguments:

Code (csharp) Select
namespace BetSoftware
{
    // Directives
    using System;

    /// <summary>
    /// Emit event arguments.
    /// </summary>
    public class EmitEventArgs : EventArgs
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="BetSoftware.EmitEventArgs"/> class.
        /// </summary>
        /// <param name="inputString">Input string.</param>
        public EmitEventArgs(string inputString)
        {
            // Set input string
            this.InputString = inputString;
        }

        /// <summary>
        /// Gets or sets the input string.
        /// </summary>
        /// <value>The input string.</value>
        public string InputString { get; set; }

        /// <summary>
        /// Gets or sets the return command.
        /// </summary>
        /// <value>The return command.</value>
        public string ReturnCommand { get; set; }
    }
}


Emitter mapper:

Code (csharp) Select
namespace BetSoftware
{
    // Directives
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    using BetSoftware;

    /// <summary>
    /// Emitter mapper.
    /// </summary>
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class EmitterMapper
    {
        /// <summary>
        /// The emitter container.
        /// </summary>
        private CompositionContainer emitterContainer;

        /// <summary>
        /// Initializes a new instance of the <see cref="BetSoftware.EmitterMapper"/> class.
        /// </summary>
        /// <param name="directoryList">Directory list.</param>
        public EmitterMapper(List<string> directoryList)
        {
            // Set emitter catalog
            var emitterCatalog = new AggregateCatalog();

            // Add catalogs
            foreach (string directoryPath in directoryList)
            {
                // Add current directory catalog
                emitterCatalog.Catalogs.Add(new DirectoryCatalog(directoryPath, "*.dll"));   
            }

            // Set emitter container
            this.emitterContainer = new CompositionContainer(emitterCatalog);

            // Compose parts
            this.emitterContainer.ComposeParts(this);
        }

        /// <summary>
        /// Gets or sets the mapped modules.
        /// </summary>
        /// <value>The mapped modules.</value>
        [ImportMany(typeof(IEmitterModule))]
        public IEnumerable<Lazy<IEmitterModule, IModuleMetadata>> MappedModules { get; set; }
    }
}





Processor module interface:

Code (csharp) Select
namespace BetSoftware
{
    /// <summary>
    /// The emitter module interface.
    /// </summary>
    public interface IProcessorModule
    {
        /// <summary>
        /// Initializes using the specified history and file path.
        /// </summary>
        /// <param name="history">Passed history.</param>
        /// <param name="filePath">File path.</param>
        void Init(History history, string filePath);

        /// <summary>
        /// Processes the specified history and processor data.
        /// </summary>
        /// <param name="history">Passed history.</param>
        /// <param name="processorData">Processor data.</param>
        /// <returns>The bet string to merge.</returns>
        string Process(History history, ProcessorData processorData);
    }
}


Processor data:

Code (csharp) Select
namespace BetSoftware
{
    /// <summary>
    /// Processor data.
    /// </summary>
    public class ProcessorData
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="BetSoftware.ProcessorData"/> class.
        /// </summary>
        /// <param name="result">Passed result.</param>
        /// <param name="betString">Bet string.</param>
        /// <param name="balance">Passed balance.</param>
        /// <param name="command">Passed command.</param>
        /// <param name="commandData">Command data.</param>
        /// <param name="isCommand">If set to <c>true</c> it is a command.</param>
        public ProcessorData(string result, string betString, decimal balance, string command, object commandData, bool isCommand)
        {
            // Set result
            this.Result = result;

            // Set bet string
            this.BetString = betString;

            // Set balance
            this.Balance = balance;

            // Set command
            this.Command = command;

            // Set command data
            this.CommandData = commandData;

            // Set is command flag
            this.IsCommand = isCommand;
        }

        /// <summary>
        /// Gets or sets the result.
        /// </summary>
        /// <value>The result.</value>
        public string Result { get; set; }

        /// <summary>
        /// Gets or sets the bet string.
        /// </summary>
        /// <value>The bet string.</value>
        public string BetString { get; set; }

        /// <summary>
        /// Gets or sets the balance.
        /// </summary>
        /// <value>The balance.</value>
        public decimal Balance { get; set; }

        /// <summary>
        /// Gets or sets the command.
        /// </summary>
        /// <value>The command.</value>
        public string Command { get; set; }

        /// <summary>
        /// Gets or sets the command data.
        /// </summary>
        /// <value>The command data.</value>
        public object CommandData { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance holds a command.
        /// </summary>
        /// <value><c>true</c> if this instance is command; otherwise, <c>false</c>.</value>
        public bool IsCommand { get; set; }
    }
}


Processor mapper:

Code (csharp) Select
namespace BetSoftware
{
    // Directives
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;

    /// <summary>
    /// Processor mapper.
    /// </summary>
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class ProcessorMapper
    {
        /// <summary>
        /// The processor container.
        /// </summary>
        private CompositionContainer processorContainer;

        /// <summary>
        /// Initializes a new instance of the <see cref="BetSoftware.ProcessorMapper"/> class.
        /// </summary>
        /// <param name="directoryList">Directory list.</param>
        public ProcessorMapper(List<string> directoryList)
        {
            // Set processor catalog
            var processorCatalog = new AggregateCatalog();

            // Add catalogs
            foreach (string directoryPath in directoryList)
            {
                // Add current directory catalog
                processorCatalog.Catalogs.Add(new DirectoryCatalog(directoryPath, "*.dll"));   
            }

            // Set processor container
            this.processorContainer = new CompositionContainer(processorCatalog);

            // Compose parts
            this.processorContainer.ComposeParts(this);
        }

        /// <summary>
        /// Gets or sets the mapped modules.
        /// </summary>
        /// <value>The mapped modules.</value>
        [ImportMany(typeof(IProcessorModule))]
        public IEnumerable<Lazy<IProcessorModule, IModuleMetadata>> MappedModules { get; set; }
    }
}





Receiver module interface:

Code (csharp) Select
namespace BetSoftware
{
    /// <summary>
    /// The receiver module interface.
    /// </summary>
    public interface IReceiverModule
    {
        /// <summary>
        /// Initializes using the specified history and file path.
        /// </summary>
        /// <param name="history">Passed history.</param>
        /// <param name="filePath">File path.</param>
        void Init(History history, string filePath);

        /// <summary>
        /// Receives the specified history and receiver data.
        /// </summary>
        /// <param name="history">Passed history.</param>
        /// <param name="receiverData">Receiver data.</param>
        void Receive(History history, ReceiverData receiverData);
    }
}


Receiver data:

Code (csharp) Select
namespace BetSoftware
{
    /// <summary>
    /// Receiver data.
    /// </summary>
    public class ReceiverData
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="BetSoftware.ReceiverData"/> class.
        /// </summary>
        /// <param name="command">Passed command.</param>
        /// <param name="commandData">Command data.</param>
        public ReceiverData(string command, object commandData)
        {
            // Set the command
            this.Command = command;

            // Set the command data
            this.CommandData = commandData;
        }

        /// <summary>
        /// Gets or sets the command.
        /// </summary>
        /// <value>The command.</value>
        public string Command { get; set; }

        /// <summary>
        /// Gets or sets the command data.
        /// </summary>
        /// <value>The command data.</value>
        public object CommandData { get; set; }
    }
}


Receiver mapper:

Code (csharp) Select
namespace BetSoftware
{
    // Directives
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;

    /// <summary>
    /// Receiver mapper.
    /// </summary>
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class ReceiverMapper
    {
        /// <summary>
        /// The receiver container.
        /// </summary>
        private CompositionContainer receiverContainer;

        /// <summary>
        /// Initializes a new instance of the <see cref="BetSoftware.ReceiverMapper"/> class.
        /// </summary>
        /// <param name="directoryList">Directory list.</param>
        public ReceiverMapper(List<string> directoryList)
        {
            // Set receiver catalog
            var receiverCatalog = new AggregateCatalog();

            // Add catalogs
            foreach (string directoryPath in directoryList)
            {
                // Add current directory catalog
                receiverCatalog.Catalogs.Add(new DirectoryCatalog(directoryPath, "*.dll"));   
            }

            // Set receiver container
            this.receiverContainer = new CompositionContainer(receiverCatalog);

            // Compose parts
            this.receiverContainer.ComposeParts(this);
        }

        /// <summary>
        /// Gets or sets the mapped modules.
        /// </summary>
        /// <value>The mapped modules.</value>
        [ImportMany(typeof(IReceiverModule))]
        public IEnumerable<Lazy<IReceiverModule,IModuleMetadata>> MappedModules { get; set; }
    }
}
Email/Paypal: betselectiongmail.com
-- Victor

VLS

Games are derived from the abstract game class:

Code (csharp) Select
namespace BetSoftware
{
    // Directives
    using System.Collections.Generic;
    using System.Drawing;

    /// <summary>
    /// The abstract game class.
    /// </summary>
    public abstract class Game
    {
        /// <summary>
        /// The name of the game.
        /// </summary>
        protected string gameName;

        /// <summary>
        /// Gets the name of the game.
        /// </summary>
        /// <value>The name of the game.</value>
        public string GameName
        { get { return this.gameName; } }

        /// <summary>
        /// The game icon.
        /// </summary>
        protected Icon gameIcon;

        /// <summary>
        /// Gets the game icon.
        /// </summary>
        /// <value>The game icon.</value>
        public Icon GameIcon
        { get { return this.gameIcon; } }

        /// <summary>
        /// The location list.
        /// </summary>
        protected List<Location> locationList;

        /// <summary>
        /// Gets the location list.
        /// </summary>
        /// <value>The location list.</value>
        public List<Location> LocationList
        { get { return this.locationList; } }
    }
}
Email/Paypal: betselectiongmail.com
-- Victor

VLS

Games must provide a game name, game icon and a list of the following location class:

Code (csharp) Select
namespace BetSoftware
{
    // Directives
    using System.Collections.Generic;

    /// <summary>
    /// Location.
    /// </summary>
    public class Location
    {
        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        string Name { get; set; }

        /// <summary>
        /// Gets or sets the payout.
        /// </summary>
        /// <value>The payout.</value>
        decimal Payout { get; set; }

        /// <summary>
        /// Gets or sets the wins with list.
        /// </summary>
        /// <value>The wins with.</value>
        List<string> WinsWith  { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="BetSoftware.Location"/> class.
        /// </summary>
        /// <param name="name">Passed name.</param>
        /// <param name="payout">Passed payout.</param>
        /// <param name="winsWith">Passed wins with.</param>
        public Location(string name, decimal payout, List<string> winsWith)
        {
            // Set name
            this.Name = name;

            // Set payout
            this.Payout = payout;

            // Set wins with list
            this.WinsWith = winsWith;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BetSoftware.Location"/> class.
        /// </summary>
        public Location()
        {
            // Parameterless constructor
        }
    }
}
Email/Paypal: betselectiongmail.com
-- Victor

VLS

This is an implementation of baccarat with 5% Banker commission and ties paying 8 to 1:

Code (csharp) Select
namespace BetSoftware
{
    // Directives
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Reflection;
    using BetSoftware;

    /// <summary>
    /// Baccarat game.
    /// </summary>
    public class Baccarat : Game
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="BetSoftware.Baccarat"/> class.
        /// </summary>
        public Baccarat()
        {
            // Set game name
            this.gameName = "Baccarat";

            // Set game icon
            this.gameIcon = new Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream("Baccarat.ico"));

            // Set location list
            this.locationList = new List<Location>()
            {
                new Location("B", 0.95M, new List<string>{ "B" }),
                new Location("P", 1, new List<string>{ "P" }),
                new Location("T", 8, new List<string>{ "T" }),
            };
        }
    }
}


Payout is defined as a decimal hence 5% banker commission deducted from 1.0 results in 0.95M.
Email/Paypal: betselectiongmail.com
-- Victor

VLS

Roulette makes use of the "WinsWith" field to define different results representing a win for the same defined location.

Code (csharp) Select
namespace BetSoftware
{
    // Directives
    using System.Collections.Generic;
    using System.Drawing;
    using System.Reflection;
    using BetSoftware;

    /// <summary>
    /// Roulette game.
    /// </summary>
    public class Roulette : Game
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="BetSoftware.Roulette"/> class.
        /// </summary>
        public Roulette()
        {
            // Set game name
            this.gameName = "Roulette";

            // Set game icon
            this.gameIcon = new Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream("Roulette.ico"));

            // Set location list
            this.locationList = new List<Location>()
            {
                new Location("B", 1, new List<string>{ "2", "4", "6", "8", "10", "11", "13", "15", "17", "20", "22", "24", "26", "28", "29", "31", "33", "35" }),
                new Location("R", 1, new List<string>{ "1", "3", "5", "7", "9", "12", "14", "16", "18", "19", "21", "23", "25", "27", "30", "32", "34", "36" }),
                new Location("L", 1, new List<string>{ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18" }),
                new Location("H", 1, new List<string>{ "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36" }),
                new Location("E", 1, new List<string>{ "2", "4", "6", "8", "10", "12", "14", "16", "18", "20", "22", "24", "26", "28", "30", "32", "34", "36" }),
                new Location("O", 1, new List<string>{ "1", "3", "5", "7", "9", "11", "13", "15", "17", "19", "21", "23", "25", "27", "29", "31", "33", "35" }),
                new Location("D1", 2, new List<string>{ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12" }),
                new Location("D2", 2, new List<string>{ "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24" }),
                new Location("D3", 2, new List<string>{ "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36" }),
                new Location("C1", 2, new List<string>{ "1", "4", "7", "10", "13", "16", "19", "22", "25", "28", "31", "34" }),
                new Location("C2", 2, new List<string>{ "2", "5", "8", "11", "14", "17", "20", "23", "26", "29", "32", "35" }),
                new Location("C3", 2, new List<string>{ "3", "6", "9", "12", "15", "18", "21", "24", "27", "30", "33", "36" }),
                new Location("1-6", 5, new List<string>{ "1", "2", "3", "4", "5", "6" }),
                new Location("4-9", 5, new List<string>{ "4", "5", "6", "7", "8", "9" }),
                new Location("7-12", 5, new List<string>{ "7", "8", "9", "10", "11", "12" }),
                new Location("10-15", 5, new List<string>{ "10", "11", "12", "13", "14", "15" }),
                new Location("13-18", 5, new List<string>{ "13", "14", "15", "16", "17", "18" }),
                new Location("16-21", 5, new List<string>{ "16", "17", "18", "19", "20", "21" }),
                new Location("19-24", 5, new List<string>{ "19", "20", "21", "22", "23", "24" }),
                new Location("22-27", 5, new List<string>{ "22", "23", "24", "25", "26", "27" }),
                new Location("25-30", 5, new List<string>{ "25", "26", "27", "28", "29", "30" }),
                new Location("28-33", 5, new List<string>{ "28", "29", "30", "31", "32", "33" }),
                new Location("31-36", 5, new List<string>{ "31", "32", "33", "34", "35", "36" }),
                new Location("1-5", 8, new List<string>{ "1", "2", "4", "5" }),
                new Location("2-6", 8, new List<string>{ "2", "3", "5", "6" }),
                new Location("4-8", 8, new List<string>{ "4", "5", "7", "8" }),
                new Location("5-9", 8, new List<string>{ "5", "6", "8", "9" }),
                new Location("7-11", 8, new List<string>{ "7", "8", "10", "11" }),
                new Location("8-12", 8, new List<string>{ "8", "9", "11", "12" }),
                new Location("10-14", 8, new List<string>{ "10", "11", "13", "14" }),
                new Location("11-15", 8, new List<string>{ "11", "12", "14", "15" }),
                new Location("13-17", 8, new List<string>{ "13", "14", "16", "17" }),
                new Location("14-18", 8, new List<string>{ "14", "15", "17", "18" }),
                new Location("16-20", 8, new List<string>{ "16", "17", "19", "20" }),
                new Location("17-21", 8, new List<string>{ "17", "18", "20", "21" }),
                new Location("19-23", 8, new List<string>{ "19", "20", "22", "23" }),
                new Location("20-24", 8, new List<string>{ "20", "21", "23", "24" }),
                new Location("22-26", 8, new List<string>{ "22", "23", "25", "26" }),
                new Location("23-27", 8, new List<string>{ "23", "24", "26", "27" }),
                new Location("25-29", 8, new List<string>{ "25", "26", "28", "29" }),
                new Location("26-30", 8, new List<string>{ "26", "27", "29", "30" }),
                new Location("28-32", 8, new List<string>{ "28", "29", "31", "32" }),
                new Location("29-33", 8, new List<string>{ "29", "30", "32", "33" }),
                new Location("31-35", 8, new List<string>{ "31", "32", "34", "35" }),
                new Location("32-36", 8, new List<string>{ "32", "33", "35", "36" }),
                new Location("1-3", 11, new List<string>{ "1", "2", "3" }),
                new Location("4-6", 11, new List<string>{ "4", "5", "6" }),
                new Location("7-9", 11, new List<string>{ "7", "8", "9" }),
                new Location("10-12", 11, new List<string>{ "10", "11", "12" }),
                new Location("13-15", 11, new List<string>{ "13", "14", "15" }),
                new Location("16-18", 11, new List<string>{ "16", "17", "18" }),
                new Location("19-21", 11, new List<string>{ "19", "20", "21" }),
                new Location("22-24", 11, new List<string>{ "22", "23", "24" }),
                new Location("25-27", 11, new List<string>{ "25", "26", "27" }),
                new Location("28-30", 11, new List<string>{ "28", "29", "30" }),
                new Location("31-33", 11, new List<string>{ "31", "32", "33" }),
                new Location("34-36", 11, new List<string>{ "34", "35", "36" }),
                new Location("0-1", 17, new List<string>{ "0", "1" }),
                new Location("0-2", 17, new List<string>{ "0", "2" }),
                new Location("0-3", 17, new List<string>{ "0", "3" }),
                new Location("0-37", 17, new List<string>{ "0", "37" }),
                new Location("1-2", 17, new List<string>{ "1", "2" }),
                new Location("1-4", 17, new List<string>{ "1", "4" }),
                new Location("2-3", 17, new List<string>{ "2", "3" }),
                new Location("2-5", 17, new List<string>{ "2", "5" }),
                new Location("3-6", 17, new List<string>{ "3", "6" }),
                new Location("3-37", 17, new List<string>{ "3", "37" }),
                new Location("4-5", 17, new List<string>{ "4", "5" }),
                new Location("4-7", 17, new List<string>{ "4", "7" }),
                new Location("5-6", 17, new List<string>{ "5", "6" }),
                new Location("5-8", 17, new List<string>{ "5", "8" }),
                new Location("6-9", 17, new List<string>{ "6", "9" }),
                new Location("7-8", 17, new List<string>{ "7", "8" }),
                new Location("7-10", 17, new List<string>{ "7", "10" }),
                new Location("8-9", 17, new List<string>{ "8", "9" }),
                new Location("8-11", 17, new List<string>{ "8", "11" }),
                new Location("9-12", 17, new List<string>{ "9", "12" }),
                new Location("10-11", 17, new List<string>{ "10", "11" }),
                new Location("10-13", 17, new List<string>{ "10", "13" }),
                new Location("11-12", 17, new List<string>{ "11", "12" }),
                new Location("11-14", 17, new List<string>{ "11", "14" }),
                new Location("12-15", 17, new List<string>{ "12", "15" }),
                new Location("13-14", 17, new List<string>{ "13", "14" }),
                new Location("13-16", 17, new List<string>{ "13", "16" }),
                new Location("14-15", 17, new List<string>{ "14", "15" }),
                new Location("14-17", 17, new List<string>{ "14", "17" }),
                new Location("15-18", 17, new List<string>{ "15", "18" }),
                new Location("16-17", 17, new List<string>{ "16", "17" }),
                new Location("16-19", 17, new List<string>{ "16", "19" }),
                new Location("17-18", 17, new List<string>{ "17", "18" }),
                new Location("17-20", 17, new List<string>{ "17", "20" }),
                new Location("18-21", 17, new List<string>{ "18", "21" }),
                new Location("19-20", 17, new List<string>{ "19", "20" }),
                new Location("19-22", 17, new List<string>{ "19", "22" }),
                new Location("20-21", 17, new List<string>{ "20", "21" }),
                new Location("20-23", 17, new List<string>{ "20", "23" }),
                new Location("21-24", 17, new List<string>{ "21", "24" }),
                new Location("22-23", 17, new List<string>{ "22", "23" }),
                new Location("22-25", 17, new List<string>{ "22", "25" }),
                new Location("23-24", 17, new List<string>{ "23", "24" }),
                new Location("23-26", 17, new List<string>{ "23", "26" }),
                new Location("24-27", 17, new List<string>{ "24", "27" }),
                new Location("25-26", 17, new List<string>{ "25", "26" }),
                new Location("25-28", 17, new List<string>{ "25", "28" }),
                new Location("26-27", 17, new List<string>{ "26", "27" }),
                new Location("26-29", 17, new List<string>{ "26", "29" }),
                new Location("27-30", 17, new List<string>{ "27", "30" }),
                new Location("28-29", 17, new List<string>{ "28", "29" }),
                new Location("28-31", 17, new List<string>{ "28", "31" }),
                new Location("29-30", 17, new List<string>{ "29", "30" }),
                new Location("29-32", 17, new List<string>{ "29", "32" }),
                new Location("30-33", 17, new List<string>{ "30", "33" }),
                new Location("31-32", 17, new List<string>{ "31", "32" }),
                new Location("31-34", 17, new List<string>{ "31", "34" }),
                new Location("32-33", 17, new List<string>{ "32", "33" }),
                new Location("32-35", 17, new List<string>{ "32", "35" }),
                new Location("33-36", 17, new List<string>{ "33", "36" }),
                new Location("34-35", 17, new List<string>{ "34", "35" }),
                new Location("35-36", 17, new List<string>{ "35", "36" }),
            };

            // Add numbers (0-37)
            for (int n = 0; n < 38; n++)
            {
                // Add current number
                this.locationList.Add(new Location(n.ToString(), 35, new List<string>{ n.ToString() }));
            }
        }
    }
}


Since the framework is game-agnostic, it processes locations as text to accommodate different game result formats in a generic fashion, therefore the List<string>.
Email/Paypal: betselectiongmail.com
-- Victor

VLS

Compiled game DLLs must be placed into \BetSoftware\Data\Games folder for them to be picked by the program.

[attachimg=1]

Game choice window features icons from valid libraries conforming to these BetSoftwareLib specifications.

[attachimg=2]
Email/Paypal: betselectiongmail.com
-- Victor