First published development version.
Please provide feedback on core functionality.
Download: [attachmini=1]
[attachimg=2] (http://betselection.cc/development/(dev)-lastxsplits/?action=dlattach;attach=529)
Coded in Cross-platform C#
Works on windows (with .NET), Linux/Mac via Mono (http://www.mono-project.com/).
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace LastXSplits_0_1
{
public partial class Form1 : Form
{
/// <summary>
/// Constructor
/// </summary>
public Form1()
{
// Initialization
InitializeComponent();
}
// History implemented as stack (LIFO)
Stack<int> history = new Stack<int>();
// Splits as List of Split class
List<Split> Splits = new List<Split>() { new Split(1, 0), new Split(2, 0), new Split(3, 0), new Split(1, 2), new Split(1, 4), new Split(2, 3), new Split(2, 5), new Split(3, 6), new Split(4, 5), new Split(4, 7), new Split(5, 6), new Split(5,, new Split(6, 9), new Split(7,, new Split(7, 10), new Split(8, 9), new Split(8, 11), new Split(9, 12), new Split(10, 11), new Split(10, 13), new Split(11, 12), new Split(11, 14), new Split(12, 15), new Split(13, 14), new Split(13, 16), new Split(14, 15), new Split(14, 17), new Split(15, 18), new Split(16, 17), new Split(16, 19), new Split(17, 18), new Split(17, 20), new Split(18, 21), new Split(19, 20), new Split(19, 22), new Split(20, 21), new Split(20, 23), new Split(21, 24), new Split(22, 23), new Split(22, 25), new Split(23, 24), new Split(23, 26), new Split(24, 27), new Split(25, 26), new Split(25, 28), new Split(26, 27), new Split(26, 29), new Split(27, 30), new Split(28, 29), new Split(28, 31), new Split(29, 30), new Split(29, 32), new Split(30, 33), new Split(31, 32), new Split(31, 34), new Split(32, 33), new Split(32, 35), new Split(33, 36), new Split(34, 35), new Split(35, 36) };
// Counter as BindingList of SplitCount (bound to DataGridView in FormCount)
BindingList<SplitCount> Counter = new BindingList<SplitCount>();
// Instantiate history form
Form fHistory = new FormHistory();
// Instantiate counter form
Form fCount = new FormCount();
// Reference to DataGridView
DataGridView dgvCount;
// Reference to History ListBox
ListBox lbHistory;
/// <summary>
/// Program's entrypoint
/// </summary>
private void Form1_Load(object sender, EventArgs e)
{
// Declare control array
PictureBox[] pbCtrl = { pb0, pb1, pb2, pb3, pb4, pb5, pb6, pb7, pb8, pb9, pb10, pb11, pb12, pb13, pb14, pb15, pb16, pb17, pb18, pb19, pb20, pb21, pb22, pb23, pb24, pb25, pb26, pb27, pb28, pb29, pb30, pb31, pb32, pb33, pb34, pb35, pb36 };
// Attach events to each control
foreach (PictureBox ctrl in pbCtrl)
{
// MouseLeave
ctrl.MouseLeave += new EventHandler(PictureBox_MouseLeave);
// MouseEnter
ctrl.MouseEnter += new EventHandler(PictureBox_MouseEnter);
// MouseDown
ctrl.MouseDown += new MouseEventHandler(PictureBox_MouseDown);
// MouseUp
ctrl.MouseUp += new MouseEventHandler(PictureBox_MouseUp);
// MouseClick
ctrl.MouseClick += new MouseEventHandler(PictureBox_MouseClick);
}
// Set dgvCount
dgvCount = (DataGridView)fCount.Controls["dgvCount"];
// Prevent automatic generation of columns
dgvCount.AutoGenerateColumns = false;
// Add shows column
DataGridViewTextBoxColumn showsColumn = new DataGridViewTextBoxColumn();
showsColumn.DataPropertyName = "Shows";
showsColumn.HeaderText = "Shows";
showsColumn.Width = 50;
showsColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
showsColumn.DefaultCellStyle.Font = new Font(fileToolStripMenuItem.Font, fileToolStripMenuItem.Font.Style ^ FontStyle.Italic);
dgvCount.Columns.Add(showsColumn);
// Add splits column
DataGridViewTextBoxColumn splitsColumn = new DataGridViewTextBoxColumn();
splitsColumn.DataPropertyName = "Splits";
splitsColumn.HeaderText = "Splits";
showsColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
splitsColumn.DefaultCellStyle.Font = new Font(fileToolStripMenuItem.Font, fileToolStripMenuItem.Font.Style ^ FontStyle.Italic);
splitsColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dgvCount.Columns.Add(splitsColumn);
// Set dgvCount DataSource
dgvCount.DataSource = Counter;
// Set lbHistory
lbHistory = (ListBox)fHistory.Controls["lbHistory"];
// Show history form
fHistory.Show();
// Show counters form
fCount.Show();
}
/// <summary>
/// MouseEnter handler
/// </summary>
private void PictureBox_MouseEnter(object sender, System.EventArgs e)
{
// Show alpha-blended image
((PictureBox)sender).BackgroundImage = Properties.Resources.yellow_highlight_alpha_38x47;
}
/// <summary>
/// MouseLeave handler
/// </summary>
private void PictureBox_MouseLeave(object sender, System.EventArgs e)
{
// Remove image
((PictureBox)sender).BackgroundImage = null;
}
/// <summary>
/// MouseDown Handler
/// </summary>
private void PictureBox_MouseDown(object sender, MouseEventArgs e)
{
// Check for left button
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
// Change cursor to hand
((PictureBox)sender).Cursor = Cursors.Hand;
// Show blue alpha-blended image
((PictureBox)sender).BackgroundImage = Properties.Resources.blue_highlight_alpha_38x47;
}
}
/// <summary>
/// MouseUp Handler
/// </summary>
private void PictureBox_MouseUp(object sender, MouseEventArgs e)
{
// Show yellow alpha-blended image
((PictureBox)sender).BackgroundImage = Properties.Resources.yellow_highlight_alpha_38x47;
// Change cursor back
((PictureBox)sender).Cursor = Cursors.Default;
}
/// <summary>
/// MouseClick handler
/// </summary>
private void PictureBox_MouseClick(object sender, MouseEventArgs e)
{
/* Right click = UNDO */
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
// Check there's something
if (history.Count > 0)
{
// Pop last one
history.Pop();
// Remove from history ListBox
lbHistory.Items.RemoveAt(0);
}
// Update
update();
// Halt flow
return;
}
// Check sender
if (!(sender is PictureBox))
{
// Halt flow too
return;
}
/* Left click = add to history */
// Snip number
int number = Convert.ToInt32(((PictureBox)sender).Name.ToString().Substring(2));
// Push onto history stack
history.Push(number);
// Add to history ListBox
lbHistory.Items.Insert(0, number);
// Update
update();
}
/// <summary>
/// Update procedure
/// </summary>
private void update()
{
// Set dictionary of int, List<Split>
Dictionary<int, List<Split>> SpD = new Dictionary<int, List<Split>>();
// Reset every split counter
foreach (Split sp in Splits)
{
// Zero it
sp.count = 0;
}
// Set a count for iterations
int iteration = 0;
// Update X times
foreach (int currentNumber in history)
{
// Rise iteration count
++iteration;
// Update Splits list count
foreach (Split sp in Splits)
{
// If number in split matches input one
if (sp.n1 == currentNumber || sp.n2 == currentNumber)
{
// Rise one in .count
sp.count += 1;
}
}
// Check if must halt
if (iteration == nudX.Value)
{
// Time to break
break;
}
}
// Set dictionary values
foreach (Split sp in Splits)
{
// Account (or not) for unhit splits
if (sp.count == 0 && !showUnhitSplitsToolStripMenuItem.Checked)
{
// Unchecked, skip iteration
continue;
}
// Create dictionary entry if not present
if (!SpD.ContainsKey(sp.count))
{
// Add new list
SpD.Add(sp.count, new List<Split>() { sp });
}
else
{
// Add split to index
SpD[sp.count].Add(sp);
}
}
// Clear counter
Counter.Clear();
// Declare new int list
List<int> intList = new List<int>();
// Populate with dictionary keys
foreach (KeyValuePair<int, List<Split>> kvp in SpD)
{
// Add key to list
intList.Add(kvp.Key);
}
// Sort list
intList.Sort();
// Sync counter with dictionary using list
for (int i = 0; i < intList.Count; ++i)
{
// Add to Counter
Counter.Add(new SplitCount(intList[i], SpD[intList[i]]));
}
// Update status strip count
tsslHistory.Text = history.Count.ToString();
}
/// <summary>
/// Launch website in default browser
/// </summary>
private void websiteToolStripMenuItem_Click(object sender, EventArgs e)
{
// Open web
LaunchSite();
}
/// <summary>
/// Open website in default browser
/// </summary>
private void LaunchSite()
{
// Launch BetSelection.cc
System.Diagnostics.Process.Start("http://betselection.cc");
}
/// <summary>
/// Show about box
/// </summary>
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
// Message
MessageBox.Show("Created for the BetSelection.cc community by: Victor/VLS" + Environment.NewLine + Environment.NewLine + "Point your browser to [url=http://www.BetSelection.cc]www.BetSelection.cc[/url] for more releases!" + Environment.NewLine + Environment.NewLine + "(Nov. 2012)", "About Last X Splits", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
}
/// <summary>
/// Account for unhit splits
/// </summary>
private void showUnhitSplitsToolStripMenuItem_Click(object sender, EventArgs e)
{
// Reverse checked status
showUnhitSplitsToolStripMenuItem.Checked = !showUnhitSplitsToolStripMenuItem.Checked;
}
/// <summary>
/// Act upon change of X
/// </summary>
private void nudX_ValueChanged(object sender, EventArgs e)
{
// Trigger update
update();
}
/// <summary>
/// Launch website when form is closed
/// </summary>
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
// Open web
LaunchSite();
}
}
/// <summary>
/// Split class
/// </summary>
public class Split
{
// Count, First and second splits
public int count, n1, n2;
// Overloaded constructor
public Split(int first, int second)
{
// Set first number
n1 = first;
// Set second number
n2 = second;
}
}
/// <summary>
/// SplitCount Class
/// </summary>
public class SplitCount
{
// Shows
public int _shows;
// Splits
public List<Split> _splits;
/// <summary>
/// Overloaded constructor
/// </summary>
/// <param name="shows">int for shows</param>
/// <param name="splits">List of Split</param>
public SplitCount(int shows, List<Split> splits)
{
_shows = shows;
_splits = splits;
}
/// <summary>
/// Shows property
/// </summary>
public int Shows
{
get { return _shows; }
set { _shows = value; }
}
/// <summary>
/// Splits property
/// </summary>
public string Splits
{
get
{
// Splits string
string splits = "";
// Populate splits string
foreach (Split sp in _splits)
{
// First number + second number + comma and space (added after every split for speed)
splits += sp.n1 + "-" + sp.n2 + ", ";
}
// Strip last comma and space
splits = splits.Substring(0, splits.Length - 2);
// Return processed string
return splits;
}
}
}
}
I'll try. It looks good.
Thank you very much for finally publishing it.
I can give my suggestions if you could explain clearly what the core functionality means.
Greetings.
Having perused the code I stand in TOTAL AWE of your programming skills, Victor.
Non-programmers simply have no idea of the skill, knowledge, understanding, time and sheer persistence that has gone into this program.
And not only that -- you have mastered several very high-level programming languages!! [It's hard enough getting to grips with just one.]
I sincerely hope this forum helps to make a reality all your hopes and dreams, both for feeding your family and for feeding this community with superb software.
You deserve it.
We are SO, SO lucky...
Thanks for your warm and kind words dear Max,
I'm very pleased to know you do appreciate it.
Actually my triumph is the triumph of a whole community. I'm going to act as a "glue" or as an interface in translating simpler instructions into their more expanded versions.
In order to achieve the goals intended with HobbyCode/BetCode, I have to be proficient in several languages / technologies.
PHP - Server/CGI
HTML5+Javascript/AJAX - WebGUI
C++ - WIN32/GTK/QT
C# - .NET/Mono
Java - JavaVM/Android
ObjectiveC - Mac/iOS
I'm glad lending my programming skills to a beginner language will be the base of one of those "silent revolutions"; I know chances are it'll never be taught at MIT, but it will make many non-programmers (beginners) and hobbyists very happy. That's what matters.
Targeting a wide array of platforms with a single, easy-to-learn and use codebase sure gets to paint many smiling faces.
Cheers.
Vic
Quote from: wannawin on November 25, 2012, 11:14:18 PM
I can give my suggestions if you could explain clearly what the core functionality means.
By core functionality I want to convey aspects
related to the tracked criterion itself.
I'm aware menus and other secondary functionality need to be implemented, yet the
main body of it is what I need you and the fellows to approve.
Expect upcoming builds with improvements.
Regards.
Nice work Vic :thumbsup:
Being only fairly technically minded compared against Victor, but I can see decent work there....intelligent and thoughtful programming
Many of the menus do not work. The counting functionality seems correct until now.
Will there be an opportunity to make this a clicker for Dublinbet and playtech?
Thank you.
Thank you dear friends for your kind and encouraging words. I'm humbled by them :rose: :nod:
@wannawin
ClickMate is the public clicker I'm going to support, this one is a tracker only.
I'm going to release the full project with resources on 0.1 version (non-dev), so you could hire a fellow coder to extend it (or hire me!) to make it a full clicker.
What I can do for you is to give it the ability to copy splits to clipboard in ClickMate format, so you can have both programs open and get the functionality you want: tracker + clicker. At no cost.
Is there any update?
Release = "This month" :)
Superceeded by: [DEV] LastXSplits 2012-12-23 (http://betselection.cc/development/(dev)-lastxsplits-2012-12-23/)