Esempio n. 1
0
        private string dojTransform(Stop stop)
        {
            ExtractJNode eJson, deJson;

            string jsonStop = stop.JsonStop;

            try
            {
                JObject o = JObject.Parse(jsonStop);
                eJson = new ExtractJNode("ori", o);
                string ori = eJson.traverseNode();
                eJson = new ExtractJNode("date", o);
                string date = eJson.traverseNode();

                //date = DateTime.Parse(date).ToString("MM/dd/yyyy", CultureInfo.InvariantCulture);

                DateTime dateValue;
                if (DateTime.TryParseExact(date, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateValue))
                {
                    date = dateValue.ToString("MM/dd/yyyy", CultureInfo.InvariantCulture);
                }
                else if (DateTime.TryParseExact(date, "yy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateValue))
                {
                    date = dateValue.ToString("MM/dd/yyyy", CultureInfo.InvariantCulture);
                }
                else
                {
                    //throw Exception;
                }

                eJson = new ExtractJNode("time", o);
                string time = eJson.traverseNode();
                eJson = new ExtractJNode("stopDuration", o);
                string stopDuration = eJson.traverseNode();
                eJson = new ExtractJNode("officerID", o);
                string officerID = eJson.traverseNode();
                eJson = new ExtractJNode("ExpYears", o);
                string ExpYears = eJson.traverseNode();
                eJson = new ExtractJNode("officerAssignment.key", o);
                string OFKey = eJson.traverseNode();
                eJson = new ExtractJNode("officerAssignment.otherType", o);
                string OFOtherType = eJson.traverseNode();

                eJson = new ExtractJNode("location.intersection", o);
                string intersection = eJson.traverseNode();
                eJson = new ExtractJNode("location.blockNumber", o);
                string blockNumber = eJson.traverseNode();
                eJson = new ExtractJNode("location.landMark", o);
                string landMark = eJson.traverseNode();
                eJson = new ExtractJNode("location.streetName", o);
                string streetName = eJson.traverseNode();
                eJson = new ExtractJNode("location.highwayExit", o);
                string highwayExit = eJson.traverseNode();

                // Generate Location
                string location = intersection;
                if (blockNumber != "")
                {
                    location += " " + blockNumber;
                }
                if (landMark != "")
                {
                    location += " " + landMark;
                }
                if (streetName != "")
                {
                    location += " " + streetName;
                }
                if (highwayExit != "")
                {
                    location += " " + highwayExit;
                }
                eJson = new ExtractJNode("location.city.codes.code", o);
                string city = eJson.traverseNode();

                eJson = new ExtractJNode("location.school", o);
                string isSchool = "";

                if (eJson.traverseNode() == "True")
                {
                    isSchool = "Y";
                }
                eJson = new ExtractJNode("location.schoolName.codes.code", o);
                string schoolNameCode = eJson.traverseNode();

                eJson = new ExtractJNode("stopInResponseToCFS", o);
                string stopInResponseToCFS = "N";

                if (eJson.traverseNode() == "True")
                {
                    stopInResponseToCFS = "Y";
                }

                JObject jsonObject = JObject.FromObject(new
                {
                    //stopdatarecord = new
                    //{
                    LEARecordID = stop.ID.ToString(),
                    BatchID     = "",
                    ORI         = ori,
                    TX_Type     = "I",
                    Is_NFIA     = "",
                    SDate       = date,
                    STime       = time,
                    SDur        = stopDuration,
                    Officer     = new
                    {
                        UID   = officerID,
                        Proxy = "",
                        ExpYears,
                        AT    = OFKey,
                        ATOth = OFOtherType,
                    },
                    Location = new
                    {
                        Loc      = location,
                        City     = city,
                        K12_Flag = isSchool,
                        K12Code  = schoolNameCode,
                    },
                    Is_ServCall        = stopInResponseToCFS,
                    ListPerson_Stopped = new
                    {
                        Person_Stopped = new JArray(),
                    }
                });
                string jString = JsonConvert.SerializeObject(jsonObject);

                JArray personList = (JArray)o["ListPerson_Stopped"];

                JObject stopdatarecord = (JObject)jsonObject["ListPerson_Stopped"];

                int pid = 0;
                int i   = 0;
                foreach (JObject item in personList)
                {
                    //eJson = new ExtractJNode("PID", item);
                    //string PID = eJson.traverseNode();

                    //PID value should not exceed 99
                    if (pid < 100)
                    {
                        pid++;

                        eJson = new ExtractJNode("perceivedRace.key", item);
                        string   pRace    = eJson.traverseNode();
                        string[] ethnList = pRace.Split(',');

                        eJson = new ExtractJNode("perceivedAge", item);
                        string perceivedAge = eJson.traverseNode();

                        eJson = new ExtractJNode("perceivedLimitedEnglish", item);
                        string perceivedLimitedEnglish = "N";
                        if (eJson.traverseNode() == "True")
                        {
                            perceivedLimitedEnglish = "Y";
                        }

                        eJson = new ExtractJNode("perceivedOrKnownDisability.key", item);
                        string   prcvDisability   = eJson.traverseNode();
                        string[] prcvDisabltyList = prcvDisability.Split(',');

                        eJson = new ExtractJNode("Gend", item);
                        string Gend = eJson.traverseNode();

                        eJson = new ExtractJNode("gendNC", item);
                        string GendNC = eJson.traverseNode();

                        eJson = new ExtractJNode("perceivedLgbt", item);
                        string perceivedLgbt = "N";
                        if (eJson.traverseNode() == "Yes")
                        {
                            perceivedLgbt = "Y";
                        }

                        eJson = new ExtractJNode("Is_Stud", item);
                        string Is_Stud = "";
                        if (isSchool == "Y")
                        {
                            if (eJson.traverseNode() == "True")
                            {
                                Is_Stud = "Y";
                            }
                            else
                            {
                                Is_Stud = "N";
                            }
                        }

                        eJson = new ExtractJNode("reasonForStop.key", item);
                        string StReas = eJson.traverseNode();

                        eJson = new ExtractJNode("reasonForStopExplanation", item);
                        string StReas_N = eJson.traverseNode();


                        eJson = new ExtractJNode("basisForSearch.key", item);
                        string   BasSearch     = eJson.traverseNode();
                        string[] BasSearchList = BasSearch.Split(',');

                        eJson = new ExtractJNode("basisForSearchBrief", item);
                        string BasSearch_N = eJson.traverseNode();

                        eJson = new ExtractJNode("basisForPropertySeizure.key", item);
                        string   BasSeiz     = eJson.traverseNode();
                        string[] BasSeizList = BasSeiz.Split(',');

                        eJson = new ExtractJNode("typeOfPropertySeized.key", item);
                        string   PropType     = eJson.traverseNode();
                        string[] PropTypeList = PropType.Split(',');

                        eJson = new ExtractJNode("contrabandOrEvidenceDiscovered.key", item);
                        string   Cb     = eJson.traverseNode();
                        string[] CbList = Cb.Split(',');
                        string   pidStr = pid.ToString();


                        JArray listP = (JArray)stopdatarecord["Person_Stopped"];
                        listP.Add(new JObject(new JProperty("PID", pidStr),
                                              new JProperty("Perc",
                                                            new JObject(new JProperty("ListEthn",
                                                                                      new JObject(new JProperty("Ethn", new JArray(ethnList)))),
                                                                        new JProperty("Age", perceivedAge),
                                                                        new JProperty("Is_LimEng", perceivedLimitedEnglish),
                                                                        new JProperty("ListDisb",
                                                                                      new JObject(new JProperty("Disb", new JArray(prcvDisabltyList)))),
                                                                        new JProperty("Gend", Gend),
                                                                        new JProperty("GendNC", GendNC),
                                                                        new JProperty("LGBT", perceivedLgbt))),
                                              new JProperty("Is_Stud", Is_Stud),
                                              new JProperty("PrimaryReason",
                                                            new JObject(new JProperty("StReas", StReas),
                                                                        new JProperty("StReas_N", StReas_N))),
                                              new JProperty("ListActTak",
                                                            new JObject(new JProperty("ActTak", new JArray()))),
                                              new JProperty("ListBasSearch",
                                                            new JObject(new JProperty("BasSearch", BasSearchList))),
                                              new JProperty("BasSearch_N", BasSearch_N),
                                              new JProperty("ListBasSeiz",
                                                            new JObject(new JProperty("BasSeiz", BasSeizList))),
                                              new JProperty("ListPropType",
                                                            new JObject(new JProperty("PropType", PropTypeList))),
                                              new JProperty("ListCB",
                                                            new JObject(new JProperty("Cb", CbList))),
                                              new JProperty("ListResult",
                                                            new JObject(new JProperty("Result", new JArray())))));



                        i = pid - 1;

                        //Action Taken
                        eJson = new ExtractJNode("actionsTakenDuringStop.key", item);
                        string   ActTak     = eJson.traverseNode();
                        string[] ActTakList = ActTak.Split(';');

                        JObject ListActTakO = (JObject)listP[i]["ListActTak"];
                        JArray  listAct     = (JArray)ListActTakO["ActTak"];
                        for (int j = 0; j < ActTakList.Length; j++)
                        {
                            string[] CD_Con = ActTakList[j].Split(',');
                            if (CD_Con.Length == 2)
                            {
                                listAct.Add(new JObject(new JProperty("Act_CD", CD_Con[0]),
                                                        new JProperty("Is_Con", CD_Con[1])));
                            }
                            else
                            {
                                listAct.Add(new JObject(new JProperty("Act_CD", CD_Con[0]),
                                                        new JProperty("Is_Con", "na")));
                            }
                        }

                        deJson = new ExtractJNode("reasonForStop.details.key", item);
                        JObject PrimaryReason = (JObject)listP[i]["PrimaryReason"];
                        string  key           = "";
                        string  reasonCode    = "";

                        // Traffic Violation
                        if (StReas == "1")
                        {
                            key = deJson.traverseNode();
                            PrimaryReason.Add(new JProperty("Tr_ID", key));
                        }

                        eJson = new ExtractJNode("reasonForStop.codes.code", item);
                        if (StReas == "1")
                        {
                            reasonCode = eJson.traverseNode();
                            PrimaryReason.Add(new JProperty("Tr_O_CD", reasonCode));
                        }

                        // Reasonable Suspicion
                        if (StReas == "2")
                        {
                            key = deJson.traverseNode();
                            string[] keys = key.Split(',');
                            PrimaryReason.Add(new JProperty("ListSusp_T",
                                                            new JObject(new JProperty("Susp_T", keys))));
                        }

                        eJson = new ExtractJNode("reasonForStop.codes.code", item);
                        if (StReas == "2")
                        {
                            reasonCode = eJson.traverseNode();
                            string[] codes = reasonCode.Split(',');
                            PrimaryReason.Add(new JProperty("Susp_O_CD", codes));
                        }

                        // Education Code
                        if (StReas == "7")
                        {
                            key = deJson.traverseNode();
                            PrimaryReason.Add(new JProperty("EDU_sec_CD", key));
                        }

                        eJson = new ExtractJNode("reasonForStop.codes.code", item);
                        if (StReas == "7")
                        {
                            reasonCode = eJson.traverseNode();
                            PrimaryReason.Add(new JProperty("EDU_subDiv_CD", reasonCode));
                        }
                        JArray resultOfStopList = (JArray)item["resultOfStop"];

                        foreach (JObject resultItem in resultOfStopList)
                        {
                            JObject resultRecord = (JObject)listP[i]["ListResult"];
                            JArray  listR        = (JArray)resultRecord["Result"];

                            eJson = new ExtractJNode("key", resultItem);
                            string   Result     = eJson.traverseNode();
                            string[] ResultList = Result.Split(',');
                            foreach (string unit in ResultList)
                            {
                                eJson = new ExtractJNode("codes.code", resultItem);
                                string   Res_O_CD     = eJson.traverseNode();
                                string[] Res_O_CDList = Res_O_CD.Split(',');
                                listR.Add(new JObject(new JProperty("ResCD", unit),
                                                      new JProperty("Res_O_CD", Res_O_CDList)));
                            }
                        }



                        jString = JsonConvert.SerializeObject(jsonObject);
                    }
                }


                string sJSON = JsonConvert.SerializeObject(jsonObject);
                return(sJSON);
            }
            catch (Exception error)
            {
                string err = error.Message;
                throw error;
            }
        }
Esempio n. 2
0
        //public connectionStatus HTTP_Connection()
        //{
        //    connectionStatus connectStat = new connectionStatus();
        //    connectStat.error = String.Empty;
        //    System.Net.WebRequest req = System.Net.WebRequest.Create(TestDOJUrl);
        //    try
        //    {
        //        connectStat.connected = false;

        //        var response = (HttpWebResponse)req.GetResponse();
        //        if (response.StatusCode == HttpStatusCode.OK)
        //        {
        //            //  it is responsive
        //            connectStat.error = string.Format("{0} Available", TestDOJUrl);
        //            connectStat.connected = true;
        //        }
        //        else
        //        {
        //            connectStat.error = string.Format("{0} Returned, but with status: {1}",
        //                TestDOJUrl, response.StatusDescription);
        //        }
        //        return connectStat;
        //    }
        //    catch (Exception ex)
        //    {
        //        //  not available at all, for some reason
        //        connectStat.error = string.Format("{0} unavailable: {1}", TestDOJUrl, ex.Message);
        //        connectStat.connected = false;
        //        return connectStat;
        //    }
        //}

        public connectionStatus HTTP_Connection()
        {
            try
            {
                string       Out   = String.Empty;
                string       Error = String.Empty;
                string       Log   = String.Empty;
                ExtractJNode eJson;

                connectionStatus connectStat = new connectionStatus();
                connectStat.error     = String.Empty;
                connectStat.connected = true;
                DOJWebApiUrl          = ConfigurationManager.AppSettings["DOJWebApiUrl"];

                System.Net.WebRequest req = System.Net.WebRequest.Create(DOJWebApiUrl);

                req.Method      = "PUT";
                req.Timeout     = 100000;
                req.ContentType = "application/json";

                byte[] sentData = Encoding.UTF8.GetBytes(connectionTestData);
                req.ContentLength = sentData.Length;

                using (Stream sendStream = req.GetRequestStream())
                {
                    sendStream.Write(sentData, 0, sentData.Length);
                    sendStream.Close();
                }

                System.Net.WebResponse res = req.GetResponse();
                Stream ReceiveStream       = res.GetResponseStream();
                using (StreamReader sr = new
                                         StreamReader(ReceiveStream, Encoding.UTF8))
                {
                    Char[] read  = new Char[256];
                    int    count = sr.Read(read, 0, 256);

                    while (count > 0)
                    {
                        String str = new String(read, 0, count);
                        Out  += str;
                        count = sr.Read(read, 0, 256);
                    }
                }
                JObject o = JObject.Parse(Out);
                eJson = new ExtractJNode("Messages.Code", o);
                string code = eJson.traverseNode();
                if (code == "SYSERR")
                {
                    eJson = new ExtractJNode("Messages.Message", o);
                    string message = eJson.traverseNode();
                    connectStat.error     = code + " : " + message;
                    connectStat.connected = false;
                }
                return(connectStat);
            }
            catch (Exception error)
            {
                string err = error.Message;
                throw error;
            }
        }
Esempio n. 3
0
        // GET: api/DOJSubmit
        public async Task <EntityState> GetStops(Submissions submission)
        {
            JsonResultModel jsonResult = new JsonResultModel();

            DojResultModel dojRes = new DojResultModel();
            ExtractJNode   eJson;
            string         logFilename;


            try
            {
                entitiesdb.Submissions.Add(submission);
                entitiesdb.SaveChanges();
                int submissionID = submission.ID;
                logFilename        = submissionID + "-" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".txt";
                submission.LogFile = logFilename;

                // Writing logs on both servers
                LogFilePath1 = ConfigurationManager.AppSettings["LogFilePath1"];
                LogFilePath2 = ConfigurationManager.AppSettings["LogFilePath2"];
                if (LogFilePath2 == "")
                {
                    logFile1 = LogFilePath1 + logFilename;
                }
                else
                {
                    logFile1 = LogFilePath1 + logFilename;
                    logFile2 = LogFilePath2 + logFilename;
                }

                if (!Directory.Exists(LogFilePath1))
                {
                    Directory.CreateDirectory(LogFilePath1);
                }
                if (LogFilePath2 != "")
                {
                    if (!Directory.Exists(LogFilePath2))
                    {
                        Directory.CreateDirectory(LogFilePath2);
                    }
                }

                var stopsIDs = entitiesdb.StopOfficerIDDateTime_JSON_vw.ToList()
                               .Where(x => submission.StartDate <= Convert.ToDateTime(x.stopDate) && Convert.ToDateTime(x.stopDate) <= submission.EndDate)
                               //.Where(x => submission.StartDate <= Convert.ToDateTime(x.stopDate) && Convert.ToDateTime(x.stopDate) <= submission.EndDate && x.ID >= 15187  )
                               .Select(x => x.ID);

                string DOJjson = "";
                foreach (int stopId in stopsIDs)
                {
                    Stop st = db.Stop
                              .Where(x => x.ID == stopId && x.Status.Trim() != "success" && x.Status.Trim() != "postSubRedact")
                              .Select(x => x).FirstOrDefault();

                    if (st != null)
                    {
                        jsonResult.processedCount++;
                        submission.TotalProcessed = jsonResult.processedCount;
                        DOJjson = st.JsonDojStop;
                        HTTP_PUT(Url: DOJWebApiUrl, Data: DOJjson, model: jsonResult);
                        // the next lines are for testing
                        //jsonResult.Results = "{    \"MandatoryValidationFlag\": false,    \"Status\": \"failed\",    \"BatchID\": \"\",    \"LEARecordID\": \"63\",    \"ORI\": \"CA0370000\",    \"OfficerUID\": \"11\",    \"Proxy\": \"\",    \"StopDate\": \"06 / 05 / 2018\",    \"StopTime\": \"14:25:51\",    \"Messages\": [      {        \"Code\": \"DV007\",        \"Field\": \"UID\",        \"Message\": \"Officer Unique ID is invalid or missing, it must be 9 alphanumerical characters.\",        \"PersonNumber\": null      }    ]}";
                        //jsonResult.Results = "{\"MandatoryValidationFlag\":false,\"Status\":\"failed\",\"BatchID\":\"\",\"LEARecordID\":\"14140\",\"ORI\":\"CA0370000\",\"OfficerUID\":\"111106405\",\"Proxy\":\"\",\"StopDate\":\"06 / 05 / 2018\",\"StopTime\":\"23:58:56\",\"Messages\":[{\"Code\":\"DV236\",\"Field\":\"Tx_type\",\"Message\":\"Duplicate record exists with the same ORI,  LEA record ID combination.\",\"PersonNumber\":null},{\"Code\":\"DV004\",\"Field\":\"sTime\",\"Message\":\"Duplicate record; a stop exists for this ORI, Officer UID, Date & Time.\",\"PersonNumber\":null}]}";
                        //jsonResult.IsSuccess = true;
                        if (jsonResult.IsSuccess)
                        {
                            dojRes.ReturnPayload = jsonResult.Results;

                            st.SubmissionsID = submissionID;
                            JObject submissionO;
                            JArray  subInfoArry;
                            if (st.JsonSubmissions == null)
                            {
                                submissionO = JObject.FromObject(new { SubmissionInfo = new JArray() });
                            }
                            else
                            {
                                submissionO = JObject.Parse(st.JsonSubmissions);
                            }
                            subInfoArry = (JArray)submissionO["SubmissionInfo"];
                            subInfoArry.Add(new JObject(new JProperty("submissionID", submissionID), new JProperty("edited", false)));
                            st.JsonSubmissions = JsonConvert.SerializeObject(submissionO);

                            JObject o = JObject.Parse(dojRes.ReturnPayload);
                            o.Add("CustomProperty_DOJReceiptTime", DateTime.Now.ToString());
                            eJson        = new ExtractJNode("MandatoryValidationFlag", o);
                            dojRes.VFlag = eJson.traverseNode();

                            eJson         = new ExtractJNode("Status", o);
                            dojRes.Status = eJson.traverseNode();

                            if (dojRes.VFlag == "True")
                            {
                                if (dojRes.Status == "failed")
                                {
                                    st.Status = "fail";
                                    jsonResult.failedCount++;
                                    submission.TotalWithErrors = jsonResult.failedCount;
                                }
                                else
                                {
                                    st.Status = "success";
                                    jsonResult.succeededCount++;
                                    submission.TotalSuccess = jsonResult.succeededCount;
                                }
                            }
                            else
                            {
                                if (dojRes.Status == "failed")
                                {
                                    st.Status = "fatal";
                                    jsonResult.fatalCount++;
                                    submission.TotalRejected = jsonResult.fatalCount;
                                }
                            }

                            st.StatusMessage = o.ToString();

                            // The following section of code, saving messages in dojRes is not used at this point
                            if (st.Status != "success")
                            {
                                eJson = new ExtractJNode("Messages.Message", o);
                                string messages = eJson.traverseNode();
                                messages = messages.Replace(".,", "~");
                                dojRes.SetMessages(messages.Split('~'));
                            }
                        }
                        else
                        {
                            submission.TotalHTTPErrors = jsonResult.httpErrCount;
                        }
                        await db.SaveChangesAsync();

                        entitiesdb.Entry(submission).State = EntityState.Modified;
                        await entitiesdb.SaveChangesAsync();
                    }
                }
                jsonResult.Log += "Records processed = " + jsonResult.processedCount + "\r\n" +
                                  "Records successfully submitted = " + jsonResult.succeededCount + "\r\n" +
                                  "Records with errors = " + jsonResult.failedCount + "\r\n" +
                                  "Rejected records = " + jsonResult.fatalCount + "\r\n" +
                                  "HTTP error count = " + jsonResult.httpErrCount + "\r\n";

                File.WriteAllText(logFile1, jsonResult.Log);
                if (LogFilePath2 != "")
                {
                    File.WriteAllText(logFile2, jsonResult.Log);
                }
                submission.LogFile = logFilename;
                var state = entitiesdb.Entry(submission).State;
                return(state);
            }
            catch (Exception error)
            {
                string err = error.Message;
                throw error;
            }

            //return Ok(db.Stop.Where(x => startDate <= x.Time && x.Time <= endDate && (x.Status == "fail" || x.Status == "fatal")).ToList());
        }
Esempio n. 4
0
        //[ValidateAntiForgeryToken]
        public IHttpActionResult PutStop(JObject jsonStop, int stopId, string changeAuditReason, int submissionEdit)
        {
            HomeController.UserAuth user = new HomeController.UserAuth();
            if (ConfigurationManager.AppSettings["requireGroupMembership"] == "true")
            {
                user = HomeController.AuthorizeUser(User.Identity.Name.ToString());

                if (!user.authorizedAdmin)
                {
                    throw new HttpResponseException(HttpStatusCode.Forbidden);
                }
            }

            ExtractJNode eJson;

            eJson = new ExtractJNode("JsonStop", jsonStop);
            string jsonStopStr  = eJson.traverseNode();
            Stop   stop         = db.Stop.Find(stopId);
            string originalJson = stop.JsonStop;

            stop.JsonStop = Regex.Replace(jsonStopStr, @"\p{Cs}", ""); // remove emojis

            CommonRoutines cr = new CommonRoutines();

            try
            {
                StopChangeAudits newAuditRec = new StopChangeAudits();
                newAuditRec.StopID       = stopId;
                newAuditRec.OrigJsonStop = originalJson;
                newAuditRec.Time         = DateTime.Now;
                newAuditRec.NTUserName   = User.Identity.Name.ToString();
                newAuditRec.ModJsonStop  = jsonStopStr;
                newAuditRec.Reason       = changeAuditReason;
                if (ModelState.IsValid)
                {
                    dbe.StopChangeAudits.Add(newAuditRec);
                    dbe.SaveChanges();
                }

                if (stop.SubmissionsID != null)
                {
                    JObject submissionO    = JObject.Parse(stop.JsonSubmissions);
                    JObject lastSubmission = (JObject)submissionO["SubmissionInfo"].Last();
                    lastSubmission["edited"] = true;
                    stop.JsonSubmissions     = JsonConvert.SerializeObject(submissionO);
                }
                string dojJson = "";

                if (stop.Status == "fail")
                {
                    dojJson = cr.dojTransform(stop, "U");
                }

                if (stop.Status == "fatal" || stop.Status == null)
                {
                    dojJson = cr.dojTransform(stop, "I");
                }

                stop.JsonDojStop     = dojJson;
                db.Entry(stop).State = EntityState.Modified;
                db.SaveChanges();
                return(Ok());
            }
            catch (Exception ex)
            {
                throw new HttpResponseException(HttpStatusCode.InternalServerError);
            }
        }