Find Last A08/Visit not discharged A03

Question: How do I find the last A08/Visit not discharged.

This code searches through a message set, pulling the last A08 per visit/encounter. If the visit gets an A03 discharge message, then the visit is excluded from the final data set.

The final data set loads in a new tab and has only the last A08 for non-discharged encounters. If you want to include the A04s, see below for lines to comment out.

Note: that some of the A08 messages could still be for discharged patients. The PV1-45 discharge date/time may contain a value, but the original message set not have contained a corresponding A03.

Thank you to Scott Hall for contributing this code.

string _fileName = @"c:\_test.txt";
Dictionary<string,Encounter> _data = new Dictionary<string,Encounter>(10000);
Dictionary<string,Encounter> _discharged = new Dictionary<string,Encounter>(10000);

public class Encounter
{
   public Encounter(string encounterId)
   {
    EncounterId = encounterId;
   }

   public IMessageData Message;
   public string EncounterId;
}

public override void Run()
{
  // Get an HL7 Message in parsed format
  HL7Message message = GetParsedMessage();
  MSH msh = message.Segments.First<MSH>();
  if(msh==null || (msh.MessageType_09.TriggerEvent_02.Value!="A08" && msh.MessageType_09.TriggerEvent_02.Value!="A03"))
    return; // not an ADT^A08 message
  PID pid = message.Segments.First<PID>();
  if(pid==null)
    return; // no pid segment

  PV1 pv1 = message.Segments.First<PV1>();
  if(pv1==null)
    return; // no PV1 segment for encounter number
  string encounterId = pv1.VisitNumber_19.ToString(); //pid.PatientIdentifierList_03.First.ToString();
  Encounter CSN;

  // handle A03 Discharges
  if(msh.MessageType_09.TriggerEvent_02.Value=="A03")
  {
    if(!_discharged.TryGetValue(encounterId,out CSN)) // is patient already in the discharged dictionary?
    {
      _discharged.Add(encounterId,CSN);
    }

    // If you want A04 messages included for discharged patients, then comment out these two lines.
    // Otherwise, your dataset will be A08 messages for patients w/o an A04.
    // If you comment these lines, you might also want to change the tab name in the SaveMessage at the end.

    _data.Remove(encounterId);
    return;
  }

  // For A08 patient updates, check if the patient is already discharged.
  if(msh.MessageType_09.TriggerEvent_02.Value=="A08")
  {
    if(_discharged.TryGetValue(encounterId,out CSN)) // is patient in the discharged dictionary?
    {
      return;
    }
  }

  if(!_data.TryGetValue(encounterId,out CSN)) //CSN not found in dictionary?
  {
     CSN = new Encounter(encounterId);
     _data.Add(encounterId,CSN);
  } 

  CSN.Message = Message;
}

// Called once after the last message has been processed.
// It is a good place to perform cleanup and to report information.
// Always called from the UI thread.
public override void OnFinish()
{
   SaveMessage(_data.Values.Select(p=>p.Message),"Last A08/Visit not discharged A03");
}