C++ for Windows Version, Listing




// ------- BBallCpW.Cpp Baseball probability program in C++

/* =========================================================== *\
**  BBallCpW.cpp                                               **
** =========================================================== **
**                                                             **
** =========================================================== **
** Copyright (c) 1994 by Harry J. Smith. All rights reserved.  **
\* =========================================================== */

char name[] = "BBallCpW - Baseball probability.";
char version[] = "C++ Windows Version 2.04, last revised: 1994-07-08, 0600 hour";
char author[]  = "Copyright \xA9 1981-1994 by author: Harry J. Smith,";
char address[] = "19628 Via Monte Dr., Saratoga CA 95070.  All rights reserved.";
char hint1[] = "Uses a bivariate binomial distribution as a model,";
char hint2[] = "and assumes each game is a 50-50 chance.";


// Computes the probability that the 1st place team will beat the 2nd place
// team for the division title, assuming each has a 50-50 chance of winning
// any given future game. Uses a bivariate binomial distribution as a model.

// Developed in Turbo Pascal 5.0, converted to
// Converted to Borland C++ 4.0 and OWL 2.0

#include <owl\applicat.h>
#include <owl\framewin.h>
#include <owl\menu.h>
#include <owl\dialog.h>
#include <owl\edit.h>
#include <owl\validate.h>
#include <owl\printer.h>
#include <classlib\date.h>
#include <mem.h>
#include <cstring.h>
#pragma hdrstop
#include "BBallCpW.rh"
#include <stdio.h>    // Definitions for stream input/output
#include <math.h>     // Definitions for the math floating point package
#include <conio.h>    // Direct MS-DOS console input/output, getch()
#include <stdlib.h>   // Definition of exit() etc.
#include <string.h>   // Definition of srtcpy() etc.

// Detect Windows NT or Win32s for 32-bit mode
#ifdef __WIN32__
  char WinMode[] = ", (32-bit mode)";
#else
  char WinMode[] = ", (16-bit mode)";
#endif

#define GL1_SIZE 4
#define GL2_SIZE 4
#define GE_SIZE 3
#define GA_SIZE 6
#define TN1_SIZE 13
#define TN2_SIZE 13
#define DATE_SIZE 13

#define P_SIZE 16
#define Q_SIZE 16
#define OOQ_SIZE 16
#define POQ_SIZE 16
#define MNT1_SIZE 16
#define MNW1_SIZE 16
#define MNT2_SIZE 16
#define MNW2_SIZE 16
#define ER_GA_SIZE 16
#define ER_GE_SIZE 16

struct TBBBuffer {
  char GL1[GL1_SIZE];
  char GL2[GL2_SIZE];
  char GE[GE_SIZE];
  char GA[GA_SIZE];
  char TN1[TN1_SIZE];
  char TN2[TN2_SIZE];
  char Date[DATE_SIZE];
};

// Global constants and variables
const char ESC = 27;

char   TN1[11]; // Team's name, 1st place team
char   TN2[11]; // Team's name, 2nd place team
int    GL1;     // Games Left to play, 1st place team
int    GL2;     // Games Left to play, 2nd place team
int    GE;      // Games to play each other
double GA;      // Games 1st place team is ahead. 0, 0.5, ...
long   GA2;     // Twice games ahead = 2 * GA, 0, 1, ...
long   MNT1;    // Magic Number to tie for 1st place team
long   MNW1;    // Magic Number to win for 1st place team
long   MNT2;    // Magic Number to tie for 2nd place team
long   MNW2;    // Magic Number to win for 2nd place team
double P;       // Probability that 1st place team beats 2nd place team
double Q;       // Probability that 2nd place team beats 1st place team
BOOL GAEr;      // True if GA value not possible
BOOL GEEr;      // True if GE value not possible
BOOL PEr;       // True if Overflow while computing P
string msg;     // Message for printer

// Procedure prototypes
void ExpandCase( void);  // Compute related data
void ComputeProb( void); // Compute probability using a bivariate binomial
                         //   distribution as a model

// ------- Compute related data
void ExpandCase( void)
{
  long I;

  GA2 = 2 * GA + 0.5; // Round
  I = GL1 + GL2 - GA2;
  MNT1 = I / 2;             MNW1 = MNT1 + 1;
  MNT2 = GL1 + GL2 - MNT1;  MNW2 = MNT2 + 1;
  I = GL1 + GL2 + GA2;
  GAEr = (I % 2 == 1); // True if I is odd
} // --end-- ExpandCase

// ------- Compute probability using a bivariate binomial dist. as a model
void ComputeProb( void)
{
  int I, J;
  double A, B;
  double* E; // 25 Binomial coefficients, games to play each other
  double* S; // 25 Running sum of 2 * E[I]
  double* F; // 163 B. C., games not played with each other
  double* G; // 163 Sum of 2 * E[I] for 2nd place team win, E[I] for tie

  E =(double*) calloc( GE+1, sizeof(double));
  S =(double*) calloc( GE+1, sizeof(double));
  F =(double*) calloc( (size_t)max(1L, MNT1+1), sizeof(double));
  G =(double*) calloc( (size_t)max(1L, MNT1+1), sizeof(double));

  PEr = FALSE;
  A = GL1 + GL2 - GE - GE; // A = not played with each other games
  B = 1.0;
  F[0] = 1.0;
  for (I = 1; I <= MNT1; I++) { // Compute binomial coefficients
	 F[I] = F[I - 1] * A / B;
	 A = A - 1.0;
	 B = B + 1.0;
  }
  A = GE;
  B = 1.0;
  E[0] = 1.0;
  S[0] = 2.0;
  for (I = 1; I <= GE; I++) { // Compute binomial coefficients
	 E[I] = E[I - 1] * A / B;
	 A = A - 1.0;
	 B = B + 1.0;
	 S[I] = S[I - 1] + 2 * E[I];
  }
  for (I = 0; I <= MNT1; I++) { // Compute G[I]
	 J = (int)((MNT1 - I) / 2);
	 if (J <= GE) {
		G[I] = S[J];
		if ((J + J) == (MNT1 - I))  G[I] = G[I] - E[J]; // Adjust for tie
	 }
	 else
		G[I] = S[GE];
  }
  Q = 0.0;   // Compute probability that 2nd place team beats 1st place team
  for (I = 0; I <= MNT1; I++) {
	 Q = Q + F[I] * G[I];
  }
  A = GL1 + GL2 - GE + 1;
  B = pow( 2.0, A); // 2 ** Flips
  Q = Q / B;
  P = 1.0 - Q;
//catch (...) {
//  string msg;
//  string NL('\n'), DL("\n\n");
//  msg += """";
//  msg += "Overflow" + DL;
//  msg += "Input numbers are too large!";
//  MessageBox(      // Display message
//    NULL,
//    msg.c_str(),
//    "Overflow",
//    MB_OK);
//  P = Q = 0;  PEr = TRUE;
//}
} // --end-- ComputeProb

// ===========================================================
// The Printout class
// ===========================================================

class TBBPrintout: public TPrintout {
public:
  TBBPrintout(TWindow* window, const char* title);
protected:
  void PrintPage(int page, TRect& rect, unsigned flags);
private:
  TWindow* parentWindow;
};

// Constructor
TBBPrintout::TBBPrintout(
  TWindow* window, const char* title)
  : TPrintout(title)
{
  parentWindow = window;
}

// Print pages of document (only 1 page)
void
TBBPrintout::PrintPage(
  int /*page*/, TRect& rect, unsigned /*flags*/)
{
  TPrintDC& dc = *DC;
  TSize     pageSize = PageSize;
  TEXTMETRIC tm;
  int h;
  //
  // Size the fonts to whatever DC we print to
  //
  h = -MulDiv(dc.GetDeviceCaps(LOGPIXELSY), abs(-12), 72); // 12-point font
  TFont fontNormal(h, 0, 0, 0, FW_NORMAL, 0, 0, 0,
                ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
                DRAFT_QUALITY, VARIABLE_PITCH | FF_SWISS, NULL);
  TSize     extent;
  dc.SetBkMode(TRANSPARENT);
  dc.SelectObject(fontNormal);
  dc.GetTextMetrics(tm);
  dc.DrawText(msg.c_str(), -1, rect, DT_LEFT);
  parentWindow->Paint(*DC, FALSE, rect);
}

// ===========================================================
// The application's main dialog
// ===========================================================

class TBBDialog: public TDialog {
public:
  TBBDialog(TWindow* parent, TBBBuffer* BBBuffer);
  ~TBBDialog();
  TEdit* EditDate;
protected:
  void CmCheckInput();   // Respond to Check Input button
  void CmUpdateOutput(); // Respond to Update Output button
  void CmReset();        // Respond to Reset button
  void CmFilePrintSetup(); // Respond to File|Print Setup menu command
  void CmFilePrint();    // Respond to File|Print menu command
  void CmFileExit();     // Respond to File|Exit menu command
  void CmHelpTest();     // Respond to Help|Test menu command
  void CmHelpAbout();    // Respond to Help|About menu command
  void UpdateInput();    // Common code
  void UpdateOutput();   // Common code
private:
  TPrinter* printer;
  TEdit* EditGL1;
  TEdit* EditGL2;
  TEdit* EditGE;
  TEdit* EditGA;
  TEdit* EditTN1;
  TEdit* EditTN2;
//TEdit* EditDate;
  TStatic* StaticP;
  TStatic* StaticQ;
  TStatic* Static1oQ;
  TStatic* StaticPoQ;
  TStatic* StaticMNT1;
  TStatic* StaticMNW1;
  TStatic* StaticMNT2;
  TStatic* StaticMNW2;
  TStatic* ErrorGE;
  TStatic* ErrorGA;
DECLARE_RESPONSE_TABLE(TBBDialog);
};

DEFINE_RESPONSE_TABLE1(TBBDialog, TDialog)
  EV_COMMAND(CM_CHECK_INPUT, CmCheckInput),
  EV_COMMAND(CM_UPDATE_OUTPUT, CmUpdateOutput),
  EV_COMMAND(CM_RESET, CmReset),
  EV_COMMAND(CM_FILE_PRINTSETUP, CmFilePrintSetup),
  EV_COMMAND(CM_FILE_PRINT, CmFilePrint),
  EV_COMMAND(CM_FILE_EXIT, CmFileExit),
  EV_COMMAND(CM_HELP_TEST, CmHelpTest),
  EV_COMMAND(CM_HELP_ABOUT, CmHelpAbout),
END_RESPONSE_TABLE;

// Constructor
TBBDialog::TBBDialog(
  TWindow* parent, TBBBuffer* BBBuffer)
  : TDialog(parent, DIALOG_1)
{
  EditGL1 = new TEdit(this, ED_GL1, GL1_SIZE);
  EditGL1->SetValidator(new TRangeValidator(0, 162));
  EditGL2 = new TEdit(this, ED_GL2, GL2_SIZE);
  EditGL2->SetValidator(new TRangeValidator(0, 162));
  EditGE = new TEdit(this, ED_GE, GE_SIZE);
  EditGE->SetValidator(new TRangeValidator(0, 24));
  EditGA = new TEdit(this, ED_GA, GA_SIZE);
  EditGA->SetValidator(new TFilterValidator("0-9."));
  EditTN1 = new TEdit(this, ED_TN1, TN1_SIZE);
  EditTN2 = new TEdit(this, ED_TN2, TN2_SIZE);
  EditDate = new TEdit(this, ED_DATE, DATE_SIZE);
  SetTransferBuffer(BBBuffer);

  StaticP = new TStatic(this, O_P, P_SIZE);
  StaticQ = new TStatic(this, O_Q, Q_SIZE);
  Static1oQ = new TStatic(this, O_1OQ, OOQ_SIZE);
  StaticPoQ = new TStatic(this, O_POQ, POQ_SIZE);
  StaticMNT1 = new TStatic(this, O_MNT1, MNT1_SIZE);
  StaticMNW1 = new TStatic(this, O_MNW1, MNW1_SIZE);
  StaticMNT2 = new TStatic(this, O_MNT2, MNT2_SIZE);
  StaticMNW2 = new TStatic(this, O_MNW2, MNW2_SIZE);
  ErrorGE = new TStatic(this, ER_GE, ER_GE_SIZE);
  ErrorGA = new TStatic(this, ER_GA, ER_GA_SIZE);
  printer = new TPrinter;
}

// Destructor
TBBDialog::~TBBDialog() {
  delete printer;
}

// Respond to Check Input button
void
TBBDialog::CmCheckInput() {
  UpdateInput();
}

// Respond to Update Output button
void
TBBDialog::CmUpdateOutput() {
  UpdateOutput();
}

// Respond to Reset button
void
TBBDialog::CmReset() {
  EditGL1->SetText("");
  EditGL2->SetText("");
  EditGE->SetText("");
  EditGA->SetText("");
  EditTN1->SetText("");
  EditTN2->SetText("");
  TDate Date;
  string msg = Date.AsString();
  EditDate->SetText(msg.c_str());
  StaticP->SetText("");
  StaticQ->SetText("");
  Static1oQ->SetText("");
  StaticPoQ->SetText("");
  StaticMNT1->SetText("");
  StaticMNW1->SetText("");
  StaticMNT2->SetText("");
  StaticMNW2->SetText("");
  ErrorGE->SetText("");
  ErrorGA->SetText("");
}

// Respond to File|Print Setup menu command
void
TBBDialog::CmFilePrintSetup()
{
  printer->Setup(this);
}

// Respond to File|Print menu command
void
TBBDialog::CmFilePrint()
{
  string NL("\n                "), DL = ("\n") + NL;
  msg  = "\n\n" + DL;
  msg += name + NL;
  msg += version;
  msg += WinMode + NL;
  msg += author + NL;
  msg += address + DL;
  msg += hint1 + NL;
  msg += hint2 + DL;

  char st[16];
  EditDate->GetText(st, DATE_SIZE);
  msg += st;
  msg += " = Date of morning after last game" + NL;

  EditGL1->GetText(st, GL1_SIZE);
  msg += st;
  msg += " = Games Left to play, 1st place team (";
  msg += TN1;
  msg += ")" + NL;

  EditGL2->GetText(st, GL2_SIZE);
  msg += st;
  msg += " = Games Left to play, 2nd place team (";
  msg += TN2;
  msg += ")" + NL;

  EditGE->GetText(st, GE_SIZE);
  msg += st;
  msg += " = Games to play each other" + NL;

  EditGA->GetText(st, GA_SIZE);
  msg += st;
  msg += " = Games 1st place team is ahead.  0, 0.5, ..." + DL;

  StaticMNT1->GetText(st, MNT1_SIZE);
  msg += st;
  msg += " = Magic Number to tie for 1st place team" + NL;

  StaticMNW1->GetText(st, MNW1_SIZE);
  msg += st;
  msg += " = Magic Number to win for 1st place team" + NL;

  StaticMNT2->GetText(st, MNT2_SIZE);
  msg += st;
  msg += " = Magic Number to tie for 2nd place team" + NL;

  StaticMNW2->GetText(st, MNW2_SIZE);
  msg += st;
  msg += " = Magic Number to win for 2nd place team" + DL;

  StaticP->GetText(st, P_SIZE);
  msg += st;
  msg += " = Probability that 1st place team beats 2nd place team" + NL;

  StaticQ->GetText(st, Q_SIZE);
  msg += st;
  msg += " = Probability that 2nd place team beats 2nd place team" + NL;

  StaticQ->GetText(st, Q_SIZE);
  msg += st;
  msg += " = Probability that 2nd place team beats 2nd place team" + NL;

  Static1oQ->GetText(st, OOQ_SIZE);
  msg += st;
  msg += " = 1 / Q, (Odds = ";
  StaticPoQ->GetText(st, POQ_SIZE);
  msg += st;
  msg += " : 1)";

  if (printer) {
    TBBPrintout printout(this, "BB Printout");
    printer->Print(this, printout, TRUE);
  }
}

// Respond to File|Exit menu command
void
TBBDialog::CmFileExit()
{
  // MainWindow->CmFileExit();
  CmExit();
  CloseWindow();
}

// Respond to Help|Test menu command
void
TBBDialog::CmHelpTest() {
  EditGL1->SetText("6");
  EditGL2->SetText("7");
  EditGE->SetText("0");
  EditGA->SetText("1.5");
  EditTN1->SetText("Braves");
  EditTN2->SetText("Giants");
  EditDate->SetText("1993-09-27");
  UpdateOutput();
}

// Respond to Help|About menu command
void
TBBDialog::CmHelpAbout() {
  string msg;
  string NL('\n'), DL("\n\n");
  msg += name + DL;
  msg += version;
  msg += WinMode + DL;
  msg += author + DL;
  msg += address + DL + DL;
  msg += hint1 + NL;
  msg += hint2;
  MessageBox(
    msg.c_str(),
    "About BBallCpW",
    MB_OK);
}

// Respond to Update Input common code
void
TBBDialog::UpdateInput() {
  char st[16];
  EditGL1->GetText(st, GL1_SIZE);  GL1 = atoi(st);
  EditGL2->GetText(st, GL2_SIZE);  GL2 = atoi(st);
  EditGE->GetText(st, GE_SIZE);    GE = atoi(st);
  EditGA->GetText(st, GA_SIZE);    GA = atof(st);

  sprintf( st, "%1d", GL1);  EditGL1->SetText(st);
  sprintf( st, "%1d", GL2);  EditGL2->SetText(st);
  sprintf( st, "%1d", GE);  EditGE->SetText(st);

  GA2 = floor(2 * GA + 0.5); // Round
  GA = GA2 / 2.0;
  if (GA2 % 2 == 1)
    sprintf( st, "%.1f", GA);
  else
    sprintf( st, "%.0f", GA);
  EditGA->SetText(st);
  EditTN1->GetText(TN1, TN1_SIZE);
  EditTN2->GetText(TN2, TN2_SIZE);
  if (GE > GL1 || GE > GL2) {
    GEEr = TRUE;
    ErrorGE->SetText("ERROR -->");
    //ErrorGE->SetTextColor(4); // Red
    //EditGE->SetTextColor(4);
  } else {
    GEEr = FALSE;
    ErrorGE->SetText("");
    //ErrorGE->SetTextColor(0); // Black
    //EditGE->SetTextColor(0);
  }
  ExpandCase();
  if (GAEr) {
    ErrorGA->SetText("ERROR -->");
    //ErrorGA->SetTextColor(4); // Red
    //EditGA->SetTextColor(4);
  } else {
    ErrorGA->SetText("");
    //ErrorGA->SetTextColor(0); // Black
    //EditGA->SetTextColor(0);
  }
}

// Respond to Update Output common code
void
TBBDialog::UpdateOutput() {
  UpdateInput();
  char st[16];
  if (GEEr) {
    PEr = TRUE;
    Q = 0;
  } else {
    ComputeProb();
  }
  if (PEr) {
    StaticP->SetText("");
    StaticQ->SetText("");
    Q = 0;
  } else {
    sprintf( st, "%#6.4f", P);    StaticP->SetText(st);
    sprintf( st, "%#6.4f", Q);    StaticQ->SetText(st);
    if (!Q) {                      // If Q is zero
      StaticP->SetText("One");
      StaticQ->SetText("Zero");
    } else {
      if (!strcmp(st, "0.0000")) { // If Q looks like zero
        StaticQ->SetText("Very Small");
        StaticP->SetText("Almost 1.0000");
      }
    }
  }
  if (Q) {
    if (1/Q < 9999999999.9999) {
      sprintf( st, "%#6.4f", 1/Q);  Static1oQ->SetText(st);
      sprintf( st, "%#6.4f", P/Q);  StaticPoQ->SetText(st);
    } else {
      Static1oQ->SetText("> 10^10");
      StaticPoQ->SetText("> 10^10");
    }
    sprintf( st, "%13ld", MNT1);   StaticMNT1->SetText(st);
    sprintf( st, "%13ld", MNW1);   StaticMNW1->SetText(st);
    sprintf( st, "%13ld", MNT2);   StaticMNT2->SetText(st);
    sprintf( st, "%13ld", MNW2);   StaticMNW2->SetText(st);
  } else {
    Static1oQ->SetText("");
    StaticPoQ->SetText("");
    StaticMNT1->SetText("");
    StaticMNW1->SetText("");
    StaticMNT2->SetText("");
    StaticMNW2->SetText("");
  }
}

// ===========================================================
// The application's main window
// ===========================================================

class TBBallCpWWin: public TFrameWindow {
public:
  TBBallCpWWin(TWindow* parent, const char far* title);
  ~TBBallCpWWin();
protected:
  void SetupWindow();
  void CmFilePrintSetup();
  void CmFileExit();
  void CmRunGo();
  void CmHelpAbout();
private:
  TMenu* windowMenu; // Pointer to window's menu
  TBBBuffer BBBuffer; // Dialog transfer buffers
  TPrinter* printer;
DECLARE_RESPONSE_TABLE(TBBallCpWWin);
};

DEFINE_RESPONSE_TABLE1(TBBallCpWWin, TFrameWindow)
  EV_COMMAND(CM_FILE_PRINTSETUP, CmFilePrintSetup),
  EV_COMMAND(CM_FILE_EXIT, CmFileExit),
  EV_COMMAND(CM_RUN_GO, CmRunGo),
  EV_COMMAND(CM_HELP_ABOUT, CmHelpAbout),
END_RESPONSE_TABLE;

// Constructor
TBBallCpWWin::TBBallCpWWin(TWindow* parent, const char far* title)
  : TFrameWindow(parent, title),
    TWindow(parent, title)
{
  AssignMenu(ID_MENU);
  printer = new TPrinter;
  memset(&BBBuffer, 0, sizeof(BBBuffer));
  strcpy(BBBuffer.GL1, "");
  strcpy(BBBuffer.GL2, "");
  strcpy(BBBuffer.GE, "");
  strcpy(BBBuffer.GA, "");
  strcpy(BBBuffer.TN1, "");
  strcpy(BBBuffer.TN2, "");
  TDate Date;
  string msg = Date.AsString();
  strcpy(BBBuffer.Date, msg.c_str());
}

// Destructor
TBBallCpWWin::~TBBallCpWWin()
{
  delete windowMenu;
  delete printer;
}

// Initialize window object
void
TBBallCpWWin::SetupWindow()
{
  TFrameWindow::SetupWindow();

// Create menu object interface for this window's menu
  windowMenu = new TMenu(HWindow);
}

// Respond to File|Print Setup menu command
void
TBBallCpWWin::CmFilePrintSetup()
{
  printer->Setup(this);
}

// Respond to File|Exit menu command
void
TBBallCpWWin::CmFileExit()
{
  CmExit();
}

// Respond to Run|Go menu command
void
TBBallCpWWin::CmRunGo()
{
// Input GL1 from the operator
  TBBDialog* BBDialog = new TBBDialog(this, &BBBuffer);
  // BBDialog->SetIcon(this, ID_ICON);
  if (BBDialog->Execute() == IDOK) {}
}

// Respond to Help|About information menu command
void
TBBallCpWWin::CmHelpAbout()
{
  string msg;
  string NL('\n'), DL("\n\n");
  msg += name + DL;
  msg += version;
  msg += WinMode + DL;
  msg += author + DL;
  msg += address + DL + DL;
  msg += hint1 + NL;
  msg += hint2;
  MessageBox(
    msg.c_str(),
    "About BBallCpW",
    MB_OK);
}

// ===========================================================
// The application class
// ===========================================================

class TBBallCpWApp: public TApplication {
public:
  TBBallCpWApp(const char far* name)
    : TApplication(name) {};
  void InitMainWindow();
};

// Initialize the program's main window
void
TBBallCpWApp::InitMainWindow()
{
//EnableCtl3d(); // Did not work in Windows NT
  EnableBWCC();
  MainWindow = new TBBallCpWWin(0, "Baseball Probability");
  MainWindow->SetIcon(this, ID_ICON);
}

#pragma argsused

// Main program
int
OwlMain(int argc, char* argv[])
{
  TBBallCpWApp app("BBallCpW");
  return app.Run();
}
// --end-- file BBallCpW.Cpp

Return to Baseball Pennant Race Odds
Return to Harry's Home Page


This page accessed times since October 20, 2004.
Page created by: hjsmithh@sbcglobal.net
Changes last made on Saturday, 14-May-05 12:42:44 PDT

1