Ex110b - Common Ancestor Source Code

Description:
Below is the source code to generate the Common Ancestor Report for Example 110.
// Get selected tree node
  int* pSel = sNd_pT_m;
  if (!pSel){
    ASSERT(FALSE);
    return;
  }

TCHAR sMsg[kStrSz_g+1] = _T("");
TCHAR sRel[kStrSz_g+1] = _T("");
TCHAR sRelRecip[kStrSz_g+1] = _T("");

// Get current db's path, so that we can output file there
  TCHAR sDbFilePath[MAX_PATH+1] = _T("");
  DbFilePathInRegistry_get(sDbFilePath, MAX_PATH); 
  if (_tcslen(sDbFilePath)){
    _tcscat(sDbFilePath, _T("\\")); 
  }

// Get pSel's name
  TCHAR sSel[kStrSz_g+1] = _T("");
  N_Name_get(pSel, sSel, kStrSz_g);

// Determine pVb based on pSel
  int* pVb = NULL;
  int* pVbRecip = NULL;
  int* pA1[128]; int* p1 = (int*)pA1;
  int* eS = Xp_Node(pSel, p1);
  int* pQ1 = Xp_S_getV(eS, p1);
  while (int* pVbTmp=Xp_execute(pQ1)){
    // If pVb goes down a hierarchy
      if ( (pVbTmp != pName_g)
        && N_SVO_get(pVbTmp, pVbLeads_g, pDown_g) ){
        // If pSel doesn't have hier level indicating it is root of a hierarchy
          if (!N_VO_getS(pVbTmp, pSel)){
            // Get pVb's name
              *sRel = NULL;
              N_Name_get(pVbTmp, sRel, kStrSz_g);

            // Verify user's request to generate report for this relation
              _stprintf(sMsg, _T("Generate '%s' '%s' Report?"), sSel, sRel);
              int response = MessageBox(sMsg, NULL, MB_YESNOCANCEL|MB_ICONQUESTION);
              if (response == IDCANCEL){
                return;
              }
              if (response == IDYES){
                pVb = pVbTmp;

                // Get pVb's reciprocal
                  pVbRecip = N_Vb_getRecip(pVb);
                  if (!pVbRecip){
                    _stprintf(sMsg, _T("%s doesn't have reciprocal."), sRel);
                    MessageBox(sMsg, NULL, MB_OK|MB_ICONEXCLAMATION);
                    return;
                  }

                N_Name_get(pVbRecip, sRelRecip, kStrSz_g);
                break;
              }
          }
      }
  }

// Prompt user, invalid node for report
  if (!pVb){
    _stprintf(sMsg, _T("No relationship to %s specified."), sSel);
    MessageBox(sMsg, NULL, MB_OK|MB_ICONEXCLAMATION);
    return;
  }

// Get time report generation started
  DWORD timeStart = GetTickCount();

// Create file name based on pSel
  TCHAR sFileName[kStrSz_g+1] = _T("");
  _stprintf(sFileName, _T("%s_%X.txt"), sSel, N_ID(pSel));

// Create file spec
  TCHAR sFileSpec[kStrSz_g+1] = _T("");
  if (_tcslen(sDbFilePath)){
    _stprintf(sFileSpec, _T("%s\\%s"), sDbFilePath, sFileName);
  }
  else{
    _tcscpy(sFileSpec, sFileName);
  }

// Create file
  HANDLE hFile;
  hFile = CreateFile (sFileSpec,              // Open file
                      GENERIC_WRITE,          // Open for writing
                      0,                      // Do not share
                      NULL,                   // No security
                      CREATE_ALWAYS,          // Open or create
                      FILE_ATTRIBUTE_NORMAL,  // Normal file
                      NULL);                  // No template file

// Exit if file could not be opened
  if (hFile == INVALID_HANDLE_VALUE){
    ASSERT(FALSE);
    return;
  }

// Var to store one report line
  TCHAR sData[1024] = _T("");  // ???

// Write report header
  _stprintf(sData, _T("Common '%s' Report for '%s'\r\x00A"), sRel, sSel);
  WriteToFile(hFile, sData);

// Write column headers
  _stprintf(sData, _T("ThingX\tThingY\tCmnAnc\tDist\r\x00A"));
  WriteToFile(hFile, sData);

// Prepare params
  int* eS1 = Xp_Node(pSel, p1);
  int* eVb1 = Xp_Node(pVb, p1);

  int* eS3 = Xp_Node(pSel, p1);
  int* eVbR3 = Xp_Node(pVbRecip, p1);

  int* eS4 = Xp_Node(pSel, p1);
  int* eVbR4 = Xp_Node(pVbRecip, p1);

// Walk thru sel's unique descendants
  #define kInx 4
  #define maxTreeDepth 64
  int* pDescX_a[maxTreeDepth];
  pDescX_a[0] = eS1; Xp_Inps_reset(eS1, FALSE);    // eSub
  pDescX_a[1] = eVb1;  Xp_Inps_reset(eVb1, FALSE); // eVb
  pDescX_a[2] = (int*)TRUE;      // distinct
  pDescX_a[3] = (int*)(maxTreeDepth - 4);  // aSz
  pDescX_a[4] = 0;              // inx
  while (int* pDescXR=F_getHier((int*)pDescX_a)){
    // Get DescX's name
      TCHAR sX[kStrSz_g+1] = _T("");
      N_Name_getEx(N_getElem(pDescXR), sX, kStrSz_g, trNdTxt_expr_bm);

    // Walk thru sel's remaining unique descendants
      int* pDescY_a[maxTreeDepth] = {NULL};
      // Copy pDescX_a to pDescY_a
        int** p11 = pDescX_a;
        int** p22 = pDescY_a;
        int** pEnd = pDescX_a + maxTreeDepth;
        do{
          *p22 = *p11;
          ++p22;
        }while(++p11 < pEnd);

      while (int* pDescYR=F_getHier((int*)pDescY_a)){
        // Get DescY's name
          TCHAR sY[kStrSz_g+1] = _T("");
          N_Name_getEx(N_getElem(pDescYR), sY, kStrSz_g, trNdTxt_expr_bm);

        // Walk DescX's and its ancestors
          int distXtoYMin = INT_MAX;
          int* pXYmin = NULL;
          int* pXR = pDescXR;
          int distX = 0;
          int* pAncXR_a[maxTreeDepth] = {pDescXR, NULL};
          pAncXR_a[0] = Xp_Node(N_getElem(pDescXR), p1);  // eSub
          pAncXR_a[1] = eVbR3; Xp_Inps_reset(eVbR3, FALSE);  // eVb
          pAncXR_a[2] = (int*)FALSE;                    // distinct
          pAncXR_a[3] = (int*)(maxTreeDepth - kInx);  // aSz
          pAncXR_a[4] = 0;                          // inx
          pAncXR_a[5] = pDescXR;
          do{
            int* pAncX = N_getElem(pXR);
            
            // Walk DescY's and its ancestors
              int* pYR = pDescYR;
              int distY = 0;
              int* pAncYR_a[maxTreeDepth] = {pDescYR, NULL};
              pAncYR_a[0] = Xp_Node(N_getElem(pDescYR), p1);  // eSub
              pAncYR_a[1] = eVbR4; Xp_Inps_reset(eVbR4, FALSE);  // eVb
              pAncYR_a[2] = (int*)FALSE;                    // distinct
              pAncYR_a[3] = (int*)(maxTreeDepth - kInx);  // aSz
              pAncYR_a[4] = 0;                          // inx
              pAncYR_a[5] = pDescYR;
              do{
                // Find common ancestor and store if closest
                // If pAncX/ancestors matches pAncY/ancestors
                  if (pAncX == N_getElem(pYR)){
                    // Store dist if less then current
                      int dist = distX + distY;
                      if (dist < distXtoYMin){
                         distXtoYMin = dist;
                        pXYmin = pAncX;

                        // Exit for loops if one of nearest found
                          if (dist == 1){
                            goto PROCESS_ONE_OF_NEAREST;
                          }
                      }
                  }

                // Walk pCrY's ancestors
                  pYR = F_getHier((int*)pAncYR_a);
                  distY = (int)pAncYR_a[kInx];
              }while (pYR);

            // Walk pCrX's ancestors
              pXR = F_getHier((int*)pAncXR_a);
              distX = (int)pAncXR_a[kInx];
          }while (pXR);

        // Write smallest pXYmin dist
          PROCESS_ONE_OF_NEAREST:
          if (pXYmin){
            TCHAR sCmnAnc[kStrSz_g+1] = _T("");
            N_Name_getEx(pXYmin, sCmnAnc, kStrSz_g, trNdTxt_expr_bm);
            _stprintf(sData, _T("%s\t%s\t%s\t%d\r\x00A"), sX, sY, sCmnAnc, distXtoYMin);
            WriteToFile(hFile, sData);
          }
          else{
            // Common ancestor not applicable
              ASSERT(FALSE);
              _stprintf(sData, _T("%s\t%s\tna\t0\r\x00A"), sX, sY);
              WriteToFile(hFile, sData);
          }

      } // Walk thru DescY
  } // Walk thru DescX

// Get time report generation ended
  DWORD timeEnd = GetTickCount();

// Calc time elapsed
  DWORD timeElapsed = timeEnd - timeStart;

// Write time elapsed
  _stprintf(sData, _T("Time Elapsed: %d msec\r\x00A"), timeElapsed);
  WriteToFile(hFile, sData);

// Close file
  CloseHandle (hFile);

// Report completed msg
  _stprintf(sMsg, _T("Report completed."));
  MessageBox(sMsg, NULL, MB_OK);
Notes:
The creation of rolex replica the watch is inspired by the retro and elegant money of rolex replica watches the brand's round watch. The chronograph is omega replica simple and stylish, with the line features of rolex replica uk the watch series.

CM ©2000-2007