public ItemScoringConfig GetItemScoringConfigs() { SqlCommand cmd = CreateCommand(CommandType.StoredProcedure, "SD_GetItemScoringConfigs"); AddClientParameter(cmd); ItemScoringConfig config = new ItemScoringConfig { LoadTime = DateTime.Now, ItemScoringRules = new List <ItemScoringRule>(), Satellites = new List <ScoreHostInfo>() }; ExecuteReader(cmd, delegate(IColumnReader reader) { while (reader.Read()) { ItemScoringRule rule = new ItemScoringRule { Context = reader.GetString("Context"), ItemType = reader.GetString("ItemType"), Enabled = reader.GetBoolean("Item_in") }; if (reader.GetFieldType("Priority") == typeof(Boolean)) { rule.Priority = reader.GetBoolean("Priority") ? 1 : 0; } else { rule.Priority = reader.GetInt32("Priority"); } if (!reader.IsDBNull("ServerUrl")) { rule.ServerUrl = reader.GetString("ServerUrl"); } config.ItemScoringRules.Add(rule); } if (reader.NextResult()) { while (reader.Read()) { ScoreHostInfo satellite = new ScoreHostInfo { ScoreHost = reader.GetString("scoreHost"), StudentApp = reader.GetString("studentApp") }; config.Satellites.Add(satellite); } } }); if (config.ItemScoringRules.Count == 0) { return(null); } return(config); }
/// <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); }
public virtual ItemScoreRequest MakeItemScoreRequest(ReponseRepoMonitor repoMon, ScorableResponse scorableResponse, ItemScoringRule scoringRule, string itemScoringServerUrl) { // Check if we have a call back url. Without that, ISE can't send us back a score if (ScoringDaemonSettings.ItemScoringCallBackHostUrl == null) { return(null); } //The actual rubric is retrieved from the satellites student app. We send the item file path and let the student app give us the rubric string itemFile = EncryptionHelper.EncodeToBase64(scorableResponse.ItemFile); string studentAppUrl = ScoringDaemonSettings.StudentAppUrlOverride ?? scoringRule.StudentAppUrl; Uri rubricUri; if (!Uri.TryCreate(studentAppUrl + "ItemScoringRubric.axd?item=" + itemFile, UriKind.Absolute, out rubricUri)) { return(null); } // If the item scoring server and the student app are colocated, check if we can use localhost to talk between the 2 instead of thier public URLs if (ScoringDaemonSettings.EnableLocalHostUsageForColocatedApps) { Uri itemScoringServerUri; if (Uri.TryCreate(itemScoringServerUrl, UriKind.Absolute, out itemScoringServerUri) && itemScoringServerUri.Host == rubricUri.Host) { rubricUri = (new UriBuilder(rubricUri) { Host = "localhost" }).Uri; } } // If the item format is one that is scored using our Java ISE, we need to send the item bank and key in the rubric URI as opposed to the itemFile // Rewrite the rubricUri accordingly if (ScoringDaemonSettings.ItemFormatsRequiringItemKeysForRubric.Contains(scorableResponse.Format)) { string[] tokens = scorableResponse.ItemKey.Split('-'); // Item key is something like 195-3456 if (tokens.Length != 2) { return(null); // the item key is not parseable } if (!Uri.TryCreate(studentAppUrl + String.Format("ItemScoringRubric.axd?itembank={0}&itemid={1}", tokens[0], tokens[1]), UriKind.Absolute, out rubricUri)) { return(null); } } // Create a context token with enough info in it for the item scoring callback handler to persist the score // when it receives it string contextToken = GetContextToken(repoMon, scorableResponse); ResponseInfo responseInfo = new ResponseInfo(scorableResponse.Format, scorableResponse.ItemKey, scorableResponse.Response, rubricUri, RubricContentType.Uri, contextToken, true); return(new ItemScoreRequest { ResponseInfo = responseInfo, CallbackUrl = ScoringDaemonSettings.ItemScoringCallBackHostUrl + "ItemScoringCallback.axd" }); }