/// <summary> /// Items that have /// </summary> /// <param name="expiredResponses"></param> /// <returns></returns> private int ProcessExpiredResponses(IEnumerable <ScorableResponse> expiredResponses) { int failures = 0; foreach (ScorableResponse scorableResponse in expiredResponses) { ScoredResponse scoredResponse = new ScoredResponse { ItemKey = scorableResponse.ItemKey, OppKey = scorableResponse.OppKey, Position = scorableResponse.Position, Score = -1, ScoreDimensions = null, ScoreMark = scorableResponse.ScoreMark, ScoreRationale = "Max Score Attempts Exceeded", ScoreStatus = "ScoringError", Sequence = scorableResponse.ResponseSequence }; try { UpdateItemScore(scoredResponse); } catch (Exception e) { failures++; } } return(failures); }
public void UpdateItemScore(ScoredResponse scoredResponse) { if (scoredResponse == null) { return; // Should probably log an error here if this were to happen. } ScorableTest scorableTest = ResponseRepository.UpdateItemScore(scoredResponse); }
private static void OutputScoredResponse(ScoredResponse response) { OutputResponse(response); Console.WriteLine("CustomerId: " + response.Score.CustomerId); Console.WriteLine("Action: " + response.Score.Action); Console.WriteLine("Source: " + response.Score.Source); Console.WriteLine("ScoreId: " + response.Score.ScoreId); Console.WriteLine("Comment: " + response.Score.Comment); }
/// <summary> /// Will attempt to update the item score for this response. If there are no more /// responses waiting for action, it will also flip the test status to 'handscored' /// and submit the file back to the source bin in xmlrepo for TIS to pick up and process. /// </summary> /// <param name="scoredResponse"></param> /// <returns></returns> public ScorableTest UpdateItemScore(ScoredResponse scoredResponse) { ReturnStatus returnStatus = null; SqlCommand cmd = CreateCommand(CommandType.StoredProcedure, "SD_UpdateItemScore"); MemoryStream ms = null; int[] itemKey = scoredResponse.GetItemKeyTokens(); try { cmd.AddUniqueIdentifier("oppkey", scoredResponse.OppKey); cmd.AddInt("itemBank", itemKey[0]); cmd.AddInt("itemKey", itemKey[1]); //cmd.AddInt("position", scoredResponse.Position); cmd.AddInt("sequence", scoredResponse.Sequence); // TODO: this will be reportingversion cmd.AddInt("score", scoredResponse.Score); cmd.AddVarChar("scorestatus", scoredResponse.ScoreStatus, 150); if (!String.IsNullOrEmpty(scoredResponse.ScoreRationale)) { cmd.AddVarCharMax("scoreRationale", scoredResponse.ScoreRationale); } //cmd.AddUniqueIdentifier("scoremark", scoredResponse.ScoreMark); if (!String.IsNullOrEmpty(scoredResponse.ScoreDimensions)) { ms = new MemoryStream(); scoredResponse.ScoreInfoAsXml().Save(ms); cmd.AddXml("scoreDimensions", new SqlXml(ms)); } ExecuteReader(cmd, delegate(IColumnReader reader) { if (reader.Read()) { returnStatus = ReturnStatus.Parse(reader); } }); } finally { if (ms != null) { ms.Dispose(); } } // if the sproc didn't return success, it means that the opp was not in a state that allows // item score updates. Either the reportingVersion didn't match or the opp was not in handscoring or appeal status // Log the score in this case so that we have a record of it. if (!returnStatus.Status.Equals("success")) { TDSLogger.Application.Info(new TraceLog(String.Format("Item Scoring: Did not accept score: {0}", scoredResponse.AsString()))); } // always returning null for ScorableTest. Will not support test scoring here. That will be the responsibility of TIS return(null); }
private void ProcessScore(HttpContext context) { Interlocked.Increment(ref RequestCount); // GET RESPONSE ItemScoreResponse itemScoreResponse; // Get XML using (XmlReader reader = XmlReader.Create(context.Request.InputStream)) { itemScoreResponse = HttpWebHelper.DeserializeXml <ItemScoreResponse>(reader); reader.Close(); } // get the context token and deserialize it string decryptedToken = GetContextToken(itemScoreResponse); ItemScoreRequestContextToken tokenData = null; // get test data try { tokenData = JsonHelper.Deserialize <ItemScoreRequestContextToken>(decryptedToken); } catch (Exception ex) { throw new ApplicationException(String.Format("Could not read contextToken: {0}, Error: {1}.", decryptedToken ?? "(null)", ex.Message)); } // create response ScoredResponse scoredResponse = new ScoredResponse() { ItemKey = tokenData.ItemKey, OppKey = tokenData.oppKey, Sequence = tokenData.reportingVersion ?? -1, Score = itemScoreResponse.Score.ScoreInfo.Points, ScoreStatus = itemScoreResponse.Score.ScoreInfo.Status.ToString(), ScoreRationale = null, ScoreDimensions = HttpWebHelper.SerializeXml(itemScoreResponse.Score.ScoreInfo) }; string hubDBIP = tokenData.TISIP; string hubDBName = tokenData.TISDbName; string clientName = tokenData.clientName; string environment = tokenData.environment; // create function for submitting scores Action submitScore = delegate { Interlocked.Increment(ref ProgressCount); try { if (String.IsNullOrEmpty(hubDBIP)) { // must be sending items for scoring in the TDSReport format where we don't send // this information in the context token. In this case, we can only support a single configured hub. // Grab the info from that hub. IAdminRepository cloudRepository = ServiceLocator.Resolve <IAdminRepository>(); List <DataStoreInfo> hubs = cloudRepository.GetMonitoredDataStores(ScoringDaemonSettings.MachineName); hubs = hubs.FindAll(h => h.ClientName == clientName).ToList <DataStoreInfo>(); if (hubs.Count == 0) { throw new ApplicationException(String.Format("No hubs are configured for client: {0} on machine: {1}", clientName, ScoringDaemonSettings.MachineName)); } if (hubs.Count > 1) { throw new ApplicationException(String.Format("TIS item scoring callback handler only supports a single hub per client for this type of request. {0} are configured for client: {1}.", hubs.Count, clientName)); } hubDBIP = ScoringDaemonSettings.HubIP(hubs[0]); hubDBName = hubs[0].DBName; clientName = hubs[0].ClientName; environment = hubs[0].Environment; } // Save score to DB IResponseRepository responseRepo = ServiceLocator.Resolve <IResponseRespositoryFactory>() .Create(ScoringDaemonSettings.HubConnectionString(hubDBIP, hubDBName), clientName, environment); if (responseRepo == null) { // this is really unusual. We got a item score response for an unknown hub. string errorMessage = String.Format( "Got a score response for a hub that we dont monitor. oppKey:{0}, itemKey: {1}, sequence:{2}, clientName: {3}, environment: {4}", scoredResponse.OppKey, scoredResponse.ItemKey, scoredResponse.Sequence, clientName, environment); throw new InvalidDataException(errorMessage); } //run resolution rule if there is one //Zach 12/11/2014 TODO: Add checks or try/catches around each part of running the rule to give more specific error messages? TISItemResolutionRule rule = TISItemResolutionRule.CreateRule(tokenData.itemType, scoredResponse.ItemKey, clientName); if (rule != null) { TDSQASystemAPI.TestResults.ItemScoreInfo resolvedScore = rule.ResolveItemScore(Serialization.DeserializeXml <TDSQASystemAPI.TestResults.ItemScoreInfo>(scoredResponse.ScoreDimensions)); scoredResponse.Score = (int)resolvedScore.Points; scoredResponse.ScoreStatus = resolvedScore.Status == TDSQASystemAPI.TestResults.ScoringStatus.Scored ? ScoringStatus.Scored.ToString() : ScoringStatus.ScoringError.ToString(); scoredResponse.ScoreDimensions = HttpWebHelper.SerializeXml(resolvedScore); } responseRepo.UpdateItemScore(scoredResponse); } catch (Exception ex) { Interlocked.Decrement(ref ProgressCount); Interlocked.Increment(ref ErrorCount); LastError = String.Format("{0} ({1})", ex.Message, DateTime.Now); // wasn't logging the exception. See TDS.Shared.Logging.TraceLog.ToString() string id = tokenData == null ? "Unknown" : tokenData.ToString(); TDSLogger.Application.Error(new ApplicationException(String.Format("Error submitting callback score for: {0}", id), ex)); //TDSLogger.Application.Error(new TraceLog("Error submitting callback score.", ex)); return; } Interlocked.Decrement(ref ProgressCount); Interlocked.Increment(ref SuccessCount); }; // check if thread pooling is enabled for callbacks if (WorkerPool != null) { // async if (!WorkerPool.Enqueue(submitScore)) { Interlocked.Increment(ref RejectCount); } } else { // sync submitScore(); } }
/// <summary> /// Submit responses that need scores to the remote item scoring engine /// </summary> /// <param name="pendingResponses"></param> /// <returns></returns> private int ProcessPendingResponses(IEnumerable <ScorableResponse> pendingResponses) { int failures = 0; if (ItemScoringConf == null) { return(pendingResponses.Count()); } foreach (ScorableResponse scorableResponse in pendingResponses) { ItemScoringRule rule = ItemScoringConf.GetItemScoringRule(scorableResponse.Format, scorableResponse.TestId); if (rule == null || (rule.Enabled && (rule.ServerUrl == null || rule.StudentAppUrl == null))) { failures++; continue; } if (!rule.Enabled || scorableResponse.Response == null) { // This item is NOT supposed to be machine scored. ScoredResponse scoredResponse = new ScoredResponse { ItemKey = scorableResponse.ItemKey, OppKey = scorableResponse.OppKey, Position = scorableResponse.Position, Score = -1, ScoreDimensions = null, ScoreMark = scorableResponse.ScoreMark, ScoreRationale = !rule.Enabled ? "Item configured not to be scored" : "Item Response is NULL", ScoreStatus = "NotScored", Sequence = scorableResponse.ResponseSequence }; try { UpdateItemScore(scoredResponse); } catch (Exception e) { failures++; } } else if (String.IsNullOrEmpty(scorableResponse.ItemFile)) // Sometimes, we get responses that have no item file specified. We cannot do anything with these. { // This item is NOT supposed to be machine scored. ScoredResponse scoredResponse = new ScoredResponse { ItemKey = scorableResponse.ItemKey, OppKey = scorableResponse.OppKey, Position = scorableResponse.Position, Score = -1, ScoreDimensions = null, ScoreMark = scorableResponse.ScoreMark, ScoreRationale = "Item file path is null", ScoreStatus = "ScoringError", Sequence = scorableResponse.ResponseSequence }; try { UpdateItemScore(scoredResponse); } catch (Exception e) { failures++; } } else { // Send this item off to scoring string itemScoringServerUrl = ScoringDaemonSettings.ItemScoringServerUrlOverride ?? rule.ServerUrl; ItemScoreRequest itemScoreRequest = ServiceLocator.Resolve <ItemScoreRequestFactory>().MakeItemScoreRequest(this, scorableResponse, rule, itemScoringServerUrl); if (itemScoreRequest == null) { failures++; continue; } ScoreRequestSender.SendRequestAsync(itemScoringServerUrl, itemScoreRequest, null); } } return(failures); }
private void ProcessScore(HttpContext context) { Interlocked.Increment(ref RequestCount); // GET RESPONSE ItemScoreResponse itemScoreResponse; // Get XML using (XmlReader reader = XmlReader.Create(context.Request.InputStream)) { itemScoreResponse = HttpWebHelper.DeserializeXml <ItemScoreResponse>(reader); reader.Close(); } // decrypt token string decryptedToken = EncryptionHelper.DecryptFromBase64(itemScoreResponse.Score.ContextToken); // get test data WebValueCollection tokenData = new WebValueCollection(); tokenData.FillFromString(decryptedToken); // parse test data and collect up the information needed to persist this score ScoredResponse scoredResponse = new ScoredResponse { OppKey = tokenData.Get <Guid>("oppKey"), ItemKey = tokenData.Get("itemKey"), Position = tokenData.Get <int>("position"), Sequence = tokenData.Get <int>("sequence"), ScoreMark = tokenData.Get <Guid>("scoremark"), Score = itemScoreResponse.Score.ScoreInfo.Points, ScoreStatus = itemScoreResponse.Score.ScoreInfo.Status.ToString(), ScoreRationale = HttpWebHelper.SerializeXml(itemScoreResponse.Score.ScoreInfo), ScoreDimensions = GetDimensionsXmlForSP(itemScoreResponse.Score.ScoreInfo) }; string hubDBIP = tokenData.Get <String>("hubDBIP"); string hubDBName = tokenData.Get <String>("hubDBName"); string clientName = tokenData.Get <String>("clientName"); string environment = tokenData.Get <String>("environment"); // create function for submitting scores Action submitScore = delegate { Interlocked.Increment(ref ProgressCount); try { // Save score to DB IResponseRepository responseRepo = ServiceLocator.Resolve <IResponseRespositoryFactory>() .Create(ScoringDaemonSettings.HubConnectionString(hubDBIP, hubDBName), clientName, environment); if (responseRepo != null) { responseRepo.UpdateItemScore(scoredResponse); } else { // this is really unusual. We got a item score response for an unknown hub. string errorMessage = String.Format( "Got a score response for a hub that we dont monitor. oppKey:{0}, itemKey: {1}, position: {2}, sequence:{3}, scoreMark: {4}, clientName: {5}, environment: {6}", scoredResponse.OppKey, scoredResponse.ItemKey, scoredResponse.Position, scoredResponse.Sequence, scoredResponse.ScoreMark, clientName, environment); throw new InvalidDataException(errorMessage); } } catch (Exception ex) { Interlocked.Decrement(ref ProgressCount); Interlocked.Increment(ref ErrorCount); LastError = String.Format("{0} ({1})", ex.Message, DateTime.Now); TDSLogger.Application.Error(new TraceLog("Item Scoring: Error submitting callback score.", ex)); return; } Interlocked.Decrement(ref ProgressCount); Interlocked.Increment(ref SuccessCount); }; // check if thread pooling is enabled for callbacks if (WorkerPool != null) { // async if (!WorkerPool.Enqueue(submitScore)) { Interlocked.Increment(ref RejectCount); } } else { // sync submitScore(); } }