using System;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
namespace Analizator9000
{
///
/// Structure holding single deal analysis result.
///
public struct BCalcResult
{
///
/// Trump denomination (N/S/H/D/C).
///
public char trumpSuit;
///
/// Declaring player (N/E/S/W).
///
public char declarer;
///
/// Number of tricks taken by the declaring side.
///
public int tricks;
///
/// Deal number, parsed out from input string.
///
public long dealNo;
///
/// Constructor for result structure.
///
/// Trump denomination (N/S/H/D/C).
/// Declaring player (N/E/S/W).
/// Number of tricks taken by the declaring side.
/// Deal number, parsed out from input string.
public BCalcResult(char a, char b, int c, long d)
{
trumpSuit = a;
declarer = b;
tricks = c;
dealNo = d;
}
};
///
/// Wrapper class for libbcalcDDS.ddl.
///
class BCalcWrapper
{
///
/// Allocates new instance of BCalc solver.
///
/// Deal format string. See the original documentation for details.
/// Card distribution.
/// Trump denomination, in numeric format. See the original documentation for details.
/// Player on lead, in numeric format. See the original documentation for details.
/// Pointer to solver instance.
/// Original documentation: http://bcalc.w8.pl/API_C/bcalcdds_8h.html#ab636045f65412652246b769e8e95ed6f
[DllImport(@"bin\libbcalcdds.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr bcalcDDS_new(IntPtr format, IntPtr hands, Int32 trump, Int32 leader);
///
/// Conducts DD analysis.
///
/// Pointer to solver instance.
/// Number of tricks to take by leading side.
/// Original documentation: http://bcalc.w8.pl/API_C/bcalcdds_8h.html#a369ce661d027bef3f717967e42bf8b33
[DllImport(@"bin\libbcalcdds.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 bcalcDDS_getTricksToTake(IntPtr solver);
///
/// Checks for solver errors.
///
/// Pointer to solver instance.
/// Error string or NULL if no error accured.
/// Original documentation: http://bcalc.w8.pl/API_C/bcalcdds_8h.html#a89cdec200cde91331d40f0900dc0fb46
[DllImport(@"bin\libbcalcdds.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr bcalcDDS_getLastError(IntPtr solver);
///
/// Frees allocated solver instance and cleans up after it.
///
/// Pointer to solver instance.
/// Original documentation: http://bcalc.w8.pl/API_C/bcalcdds_8h.html#a4a68da83bc7da4663e2257429539912d
[DllImport(@"bin\libbcalcdds.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void bcalcDDS_delete(IntPtr solver);
///
/// Sets trump denomination and resets the analysis.
///
/// Pointer to solver instance.
/// Trump denomination, in numeric format. See the original documentation for details.
/// Original documentation: http://bcalc.w8.pl/API_C/bcalcdds_8h.html#a88fba3432e66efa5979bbc9e1f044164
[DllImport(@"bin\libbcalcdds.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void bcalcDDS_setTrumpAndReset(IntPtr solver, Int32 trump);
///
/// Sets leading player and resets the analysis.
///
/// Pointer to solver instance.
/// Player on lead, in numeric format. See the original documentation for details.
/// Original documentation: http://bcalc.w8.pl/API_C/bcalcdds_8h.html#a616031c1e1d856c4aac14390693adb4c
[DllImport(@"bin\libbcalcdds.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void bcalcDDS_setPlayerOnLeadAndReset(IntPtr solver, Int32 player);
///
/// Translation table between player characters and numeric values.
///
public static String table = "NESW";
///
/// Translation table between denomination characters and numeric values.
///
public static String denominations = "CDHSN";
///
/// Pointer to solver instance.
///
private IntPtr solver;
///
/// Deal distribution.
///
private String deal;
///
/// Internal number of deal being analyzed.
///
private long dealNo;
///
/// Trump suit, in numeric format.
///
private int trumps;
///
/// Constructor of class instance for single deal analysis.
///
/// Deal distribution prefixed with deal number.
public BCalcWrapper(String deal)
{
try
{
Match dealMatch = Regex.Match(deal, @"^(\d+): (.*)$");
if (!dealMatch.Success) {
throw new Exception();
}
this.deal = dealMatch.Groups[2].Value;
this.dealNo = Convert.ToInt64(dealMatch.Groups[1].Value);
}
catch (Exception)
{
throw new Exception(Form1.GetResourceManager().GetString("BCalcWrapper_dealLoadError", Form1.GetCulture()) + ": " + deal);
}
this.solver = BCalcWrapper.bcalcDDS_new(Marshal.StringToHGlobalAnsi(BCalcWrapper.table), Marshal.StringToHGlobalAnsi(this.deal), 0, 0);
this.errorCheck();
}
///
/// Sets the trump denomination.
///
/// Trump denomination, in numeric format.
public void setTrump(int trumpSuit)
{
if (trumpSuit < 0)
{
throw new Exception(Form1.GetResourceManager().GetString("BCalcWrapper_trumpError", Form1.GetCulture()) + ": " + trumpSuit);
}
BCalcWrapper.bcalcDDS_setTrumpAndReset(solver, trumpSuit);
this.errorCheck();
this.trumps = trumpSuit;
}
///
/// Runs the single contract analysis.
///
/// Declaring player, in numeric format.
/// Result structur for the contract.
//TODO substitute from actual number of tricks to analyze, rather than 13, maybe.
public BCalcResult run(int declarer)
{
if (declarer < 0)
{
throw new Exception(Form1.GetResourceManager().GetString("BCalcWrapper_declarerError", Form1.GetCulture()) + ": " + declarer);
}
int l = (declarer + 1) % 4;
BCalcWrapper.bcalcDDS_setPlayerOnLeadAndReset(solver, l);
this.errorCheck();
int result = BCalcWrapper.bcalcDDS_getTricksToTake(this.solver);
this.errorCheck();
return new BCalcResult(BCalcWrapper.denominations[this.trumps], BCalcWrapper.table[declarer], 13 - result, this.dealNo);
}
///
/// Releases the solver instaces.
///
public void destroy() {
BCalcWrapper.bcalcDDS_delete(this.solver);
}
///
/// Checks for errors, throws exception if any occured.
///
private void errorCheck()
{
IntPtr error = BCalcWrapper.bcalcDDS_getLastError(this.solver);
String eStr = Marshal.PtrToStringAnsi(error);
if (eStr != null)
{
throw new Exception(eStr);
}
}
}
}