Exemplo n.º 1
0
        private static HttpResponseMessage RandomizeASubject(string token, string uri, int id)
        {
            List <Dictionary <string, string> > newList = new List <Dictionary <string, string> >();
            Dictionary <string, string>         form1   = new Dictionary <string, string>();
            Dictionary <string, string>         form2   = new Dictionary <string, string>();

            // These next set of variables will change per project
            const string form1Name             = "Baseline";
            const string form2Name             = "Other";
            const string eventName             = "event1_arm_1";
            const string randomizationFormName = "randomization";
            const string randomizationTimeName = "pc_rnd_date";
            const string recordIdName          = "subject_id";
            const string projectId             = "206";

            string recordId = id.ToString();

            RedcapAccess rc  = new RedcapAccess(uri);
            Random       rnd = new Random(id + DateTime.Now.Millisecond);

            // Prepare random pre-randomization data to be sent to REDCap
            form1.Add(recordIdName, recordId);
            form1.Add("redcap_event_name", eventName);
            form1.Add(form1Name + "_complete", "2");
            form2.Add(recordIdName, recordId);
            form2.Add("redcap_event_name", eventName);
            form2.Add(form2Name + "_complete", "2");
            form2.Add(randomizationTimeName, DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"));
            form2.Add(randomizationFormName + "_complete", "2");
            newList.Add(form1);
            newList.Add(form2);

            // Create new record with pre-randomization data
            var insertResponse = rc.PostRedcapData(token, JsonConvert.SerializeObject(newList), false, "MDY");

            // Now call the controller method
            // Arrange
            var controller = new AdaptiveController(token, uri);

            controller.Request = new HttpRequestMessage {
                Method = HttpMethod.Post
            };
            controller.Configuration = new HttpConfiguration();

            // Act
            RedcapDET det = new RedcapDET();

            det.redcap_data_access_group = "";
            det.redcap_event_name        = eventName;
            det.instrument    = randomizationFormName;
            det.project_id    = projectId;
            det.complete_flag = "1";
            det.record        = recordId;

            var response = controller.Post(det);

            return(response);
        }
Exemplo n.º 2
0
        // POST https://your-domain/api/DETExampleProject
        public void Post([ModelBinder(typeof(RedcapDETModelBinderProvider))] RedcapDET redcapDet)
        {
            RedcapAccess rc = new RedcapAccess();

            Log.InfoFormat("DotNetDETs triggered for project {0}, instrument {1}", redcapDet.project_id, redcapDet.instrument);

            switch (redcapDet.instrument)
            {
            case "form-name":
                List <Dictionary <string, string> > recordList = new List <Dictionary <string, string> >();

                string errorMessage = string.Empty;
                string recordId     = redcapDet.record;

                Log.InfoFormat("Using GetRedcapData to retrieve record {0}", recordId);
                try
                {
                    recordList = rc.GetRedcapData(token, recordId, "", "", "", false, false, false, false, true, "", "");
                }
                catch (Exception ex)
                {
                    Log.ErrorFormat("GetRedcapData Exception: {0}", ex.Message);
                }

                // Some logic to evaluate. Made up for example.
                if (recordList[0]["field1"].ToString() == "1")
                {
                    // Set some field values. This is all made up for the sake of the example.
                    recordList[0]["field2"]             = "foo";
                    recordList[0]["field3"]             = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss");
                    recordList[0]["form-name_complete"] = "2";

                    Log.InfoFormat("Attempting PostRedcapData");
                    try
                    {
                        rc.PostRedcapData(token, JsonConvert.SerializeObject(recordList), true, "MDY");
                    }
                    catch (Exception ex)
                    {
                        Log.ErrorFormat("PostRedcapData Exception: {0}", ex.Message);
                    }
                }
                break;

            default:
                break;
            }

            return;
        }
        // POST https://your-domain/api/AdaptiveProject
        public HttpResponseMessage Post([ModelBinder(typeof(RedcapDETModelBinderProvider))] RedcapDET redcapDet)
        {
            RedcapAccess rc;

            // This handles calling of RedcapAccess from a unit test where
            // the URI needs to be passed to the contructor.
            // Perhaps there is a more elegant way to do this but...
            if (string.IsNullOrEmpty(this.uri))
            {
                rc = new RedcapAccess();
            }
            else
            {
                rc = new RedcapAccess(uri);
            }

            HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);

            Log.InfoFormat("DotNetDETs triggered for project {0}, instrument {1}", redcapDet.project_id, redcapDet.instrument);

            switch (redcapDet.instrument)
            {
            case "randomization":

                // Assumes two covariates
                List <Dictionary <string, string> > triggerList  = new List <Dictionary <string, string> >();
                List <Dictionary <string, string> > cov1List     = new List <Dictionary <string, string> >();
                List <Dictionary <string, string> > cov2List     = new List <Dictionary <string, string> >();
                List <Dictionary <string, string> > returnList   = new List <Dictionary <string, string> >();
                Dictionary <string, string>         returnRecord = new Dictionary <string, string>();

                // These next set of variables will change per project
                const string cov1FieldName           = "pc_rnd_bmi_cat";
                const string cov2FieldName           = "pc_rnd_age_cat";
                const string assignmentFieldName     = "pc_rnd_assignment";
                const string assignmentDateFieldName = "pc_rnd_assignment_date";
                const string eventName         = "clinic_visit_1_arm_1";
                const string formName          = "randomization";
                const string recordIdFieldName = "subject_id";
                const string eligibleFieldName = "pc_rnd_eligible";

                // Array of weights; size of array must correspond to number of arms.
                // Here we have two arms with equal weights of 1 each.
                double[] weights = new double[] { 1, 1 };

                string errorMessage  = string.Empty;
                string triggerRecord = redcapDet.record;
                string cov1Cat       = string.Empty;
                string cov2Cat       = string.Empty;
                string cov1CatFilter = string.Empty;
                string cov2CatFilter = string.Empty;

                // New randomization assignment
                // Assumption: first arm = 0, second arm = 1, nth arm = n-1, etc.
                int newAssignment;

                Log.InfoFormat("Record {0}", triggerRecord);
                Log.DebugFormat("Using GetRedcapData to retrieve record {0}", triggerRecord);
                try
                {
                    triggerList = rc.GetRedcapData(token, triggerRecord, "", eventName, formName, false, false, false, false, true, "", "");
                }
                catch (Exception ex)
                {
                    Log.ErrorFormat("GetRedcapData Exception: {0}", ex.Message);
                }

                List <List <Dictionary <string, string> > > covLists = new List <List <Dictionary <string, string> > >();

                // *** This next section of code will repeat for each covariate ****

                // Create filter string and grab existing randomized records for cov1 group
                // *** You will need to adjust if more than 2 arms and/or arm values are other than 0 and 1. ***
                cov1Cat       = triggerList[0][cov1FieldName].ToString();
                cov1CatFilter = string.Format("[{0}]='{1}' and ([{2}]='{3}' or [{2}]='{4}')", cov1FieldName, cov1Cat, assignmentFieldName, 0, 1);

                Log.DebugFormat("Using GetRedcapData to retrieve record(s) using filter '{0}'", cov1CatFilter);
                try
                {
                    cov1List = rc.GetRedcapData(token, "", assignmentFieldName, eventName, formName, false, false, false, false, true, cov1CatFilter, "");
                    covLists.Add(cov1List);
                }
                catch (Exception ex)
                {
                    Log.ErrorFormat(string.Format("GetRedcapData Exception: {0}", ex.Message));
                }

                // Prevent randomizing an ineligble subject
                if (string.IsNullOrEmpty(triggerList[0][eligibleFieldName].ToString()) ||
                    !(triggerList[0][eligibleFieldName].ToString() == "1"))
                {
                    Log.InfoFormat("Exiting because pt {0} not eligible to be randomized.", triggerRecord);
                    return(response);
                }

                // Prevent re-randomizing a subject
                if (!string.IsNullOrEmpty(triggerList[0][assignmentFieldName].ToString()))
                {
                    Log.InfoFormat("Exiting because pt {0} already randomized.", triggerRecord);
                    return(response);
                }

                Log.InfoFormat("{1} existing rows with '{0}.'", cov1CatFilter, cov1List.Count);

                // Create filter string and grab existing randomized records for cov2 group
                // *** You will need to adjust if more than 2 arms and/or arm values are other than 0 and 1. ***
                cov2Cat       = triggerList[0][cov2FieldName].ToString();
                cov2CatFilter = string.Format("[{0}]='{1}' and ([{2}]='{3}' or [{2}]='{4}')", cov2FieldName, cov2Cat, assignmentFieldName, 0, 1);

                Log.DebugFormat("Using GetRedcapData to retrieve record(s) using filter '{0}'", cov2CatFilter);
                try
                {
                    cov2List = rc.GetRedcapData(token, "", assignmentFieldName, eventName, formName, false, false, false, false, true, cov2CatFilter, "");
                    covLists.Add(cov2List);
                }
                catch (Exception ex)
                {
                    Log.ErrorFormat("GetRedcapData Exception: {0}", ex.Message);
                }

                Log.InfoFormat("{1} existing rows with '{0}'", cov2CatFilter, cov2List.Count);

                // Use Adaptive randomization when at least one other subject with
                // this combination of covariates.
                // *** If more than 2 covariates, this condition will need to be changed. ***
                if (cov1List.Count > 0 && cov2List.Count > 0)
                {
                    // Get adaptive randomization assignment
                    Log.InfoFormat("Need to use adaptive randomization for subject {0}.", triggerRecord);
                    newAssignment = GetAdaptiveAssignment(covLists, assignmentFieldName, weights);
                    Log.InfoFormat("Adaptively assigned participant {0} to arm {1}.", triggerRecord, newAssignment);
                }
                else
                {
                    // Special case of no previous records for this combination of covariates
                    Random rnd = new Random(int.Parse(triggerRecord) + DateTime.Now.Millisecond);
                    Log.Info("Zero prior subjects with this set of covariates.");
                    // This will generate a random integer number greater than or equal to 0 and
                    // strictly less than weights.GetLength(0).
                    // If there are only two treatment arms, it will select a random integer between 0 and 1.
                    newAssignment = rnd.Next(0, weights.GetLength(0));
                    Log.InfoFormat("Randomly assigned participant {0} to arm {1}.", triggerRecord, newAssignment);
                }

                // Prepare randomization record to be sent to REDCap
                returnRecord.Add(recordIdFieldName, triggerRecord);
                returnRecord.Add("redcap_event_name", eventName);
                returnRecord.Add(assignmentFieldName, newAssignment.ToString());
                returnRecord.Add(assignmentDateFieldName, DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"));
                returnList.Add(returnRecord);

                Log.DebugFormat("Attempting PostRedcapData");
                try
                {
                    rc.PostRedcapData(token, JsonConvert.SerializeObject(returnList), false, "MDY");
                }
                catch (Exception ex)
                {
                    Log.ErrorFormat("PostRedcapData Exception: {0}", ex.Message);
                }

                break;

            default:
                break;
            }

            return(response);
        }
Exemplo n.º 4
0
        // POST https://your-domain/api/DatabasedNotify
        public void Post([ModelBinder(typeof(RedcapDETModelBinderProvider))] RedcapDET redcapDet)
        {
            RedcapAccess rc = new RedcapAccess();

            Log.InfoFormat("DotNetDETs triggered for project {0}, instrument {1}", redcapDet.project_id, redcapDet.instrument);

            switch (redcapDet.instrument)
            {
            case redcapSurvey:
                List <Dictionary <string, string> > recordList = new List <Dictionary <string, string> >();

                string errorMessage = string.Empty;
                string recordId     = redcapDet.record;
                // This is the field for this example that we are using to determine
                // which DAG to put the survey in AND which site coordinator to send an email notification.
                string cityField = "cityfield";

                if (redcapDet.complete_flag == "2")
                {
                    Log.InfoFormat("Using GetRedcapData to retrieve record {0}", recordId);
                    try
                    {
                        recordList = rc.GetRedcapData(token, recordId, $"subject_id,{cityField}", "", "", false, false, false, false, true, "", "");
                    }
                    catch (Exception ex)
                    {
                        Log.ErrorFormat("GetRedcapData Exception: {0}", ex.Message);
                    }

                    CityInfo ci = GetContactForCity(recordList[0][cityField], recordId);

                    if (ci.Dag != string.Empty)
                    {
                        // Remove cityField so as not to resave the value
                        // Set data access group
                        recordList[0]["redcap_data_access_group"] = ci.Dag;
                        recordList[0][cityField] = string.Empty;     // to prevent overwriting with same value
                        Log.InfoFormat("Attempting PostRedcapData");
                        try
                        {
                            rc.PostRedcapData(token, JsonConvert.SerializeObject(recordList), false, "MDY");
                        }
                        catch (Exception ex)
                        {
                            Log.ErrorFormat("PostRedcapData Exception: {0}", ex.Message);
                        }
                    }

                    // Now email the contact
                    try
                    {
                        Messaging messaging = new Messaging();

                        StringBuilder sbMsg = new StringBuilder();
                        sbMsg.Append($"<div style='font-family: Sans-Serif;'>");
                        sbMsg.Append($"Dear {ci.ContactName},");
                        sbMsg.Append(Environment.NewLine + Environment.NewLine + "<br /><br />");
                        sbMsg.Append($"A new {projectName} response for the {ci.City} site has been received. ");
                        sbMsg.Append(Environment.NewLine + "<br />");
                        sbMsg.Append("Click on the following link to view the record (you may be required to log into REDCap first):");
                        sbMsg.Append(Environment.NewLine + Environment.NewLine + "<br /><br />");
                        sbMsg.Append($"<a href='https://redcap-address-goes-here/DataEntry/index.php?pid={redcapPid}&id={recordId}&page={redcapSurvey}'>New {ci.City} survey response</a>");
                        sbMsg.Append(Environment.NewLine + Environment.NewLine + "<br /><br />");
                        sbMsg.Append($"Alternately, login to the {projectName} project and view the response for subject with identification number of {recordId}.");
                        sbMsg.Append(Environment.NewLine + Environment.NewLine + "<br /><br />");
                        sbMsg.Append("Regards,");
                        sbMsg.Append(Environment.NewLine + "<br />");
                        sbMsg.Append("name of sender");
                        sbMsg.Append(Environment.NewLine + "<br />");
                        sbMsg.Append("organization");
                        sbMsg.Append(Environment.NewLine + "<br />");
                        sbMsg.Append("title");
                        sbMsg.Append("</div>");

                        string mailBody = sbMsg.ToString();
                        Log.DebugFormat("Body of email: {0}", mailBody);

                        messaging.SendEmail("Name<*****@*****.**>", ci.ContactEmail, projectName, mailBody, "Name<*****@*****.**>", null, recordId);
                    }
                    catch (Exception ex)
                    {
                        Log.ErrorFormat("PostRedcapData Exception: {0}", ex.Message);
                    }
                }
                break;

            default:
                break;
            }
            return;
        }