Skip to content
This repository has been archived by the owner on Sep 4, 2023. It is now read-only.

Add competence profile data model #76

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -646,4 +646,8 @@ fabric.properties
### VisualStudio Patch ###
# Additional files built by Visual Studio

# End of https://www.toptal.com/developers/gitignore/api/csharp,rider,visualstudio,dotnetcore
# End of https://www.toptal.com/developers/gitignore/api/csharp,rider,visualstudio,dotnetcore

appsettings.json
appsettings.*.json
!appsettings.example.json
6 changes: 6 additions & 0 deletions Epsilon.Abstractions/Model/CompetenceProfile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Epsilon.Abstractions.Model;

public record CompetenceProfile(
HboIDomain HboIDomain,
IEnumerable<CompetenceProfileOutcome> CompetenceProfileOutcomes
);
9 changes: 9 additions & 0 deletions Epsilon.Abstractions/Model/CompetenceProfileOutcome.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Epsilon.Abstractions.Model;

public record CompetenceProfileOutcome(
string ArchitectureLayer,
string Activity,
int MasteryLevel,
int Grade,
DateTime AssessedAt
);
38 changes: 38 additions & 0 deletions Epsilon.Abstractions/Model/HboIDomain.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Epsilon.Abstractions.Model;

public record HboIDomain(
IEnumerable<ArchitectureLayer> ArchitectureLayers,
IEnumerable<Activity> Activities,
IEnumerable<MasteryLevel> MasteryLevels
)
{
public static readonly HboIDomain HboIDomain2018 = new(
new[]
{
new ArchitectureLayer("Hardware Interfacing", "#8D9292"),
new ArchitectureLayer("Infrastructure", "#6EA7D4"),
new ArchitectureLayer("Organisational Processes", "#D16557"),
new ArchitectureLayer("User Interaction", "#E29C53"),
new ArchitectureLayer("Software", "#96B9C0")
},
new[]
{
new Activity("Manage & Control"),
new Activity("Analysis"),
new Activity("Advise"),
new Activity("Design"),
new Activity("Realisation")
},
new[]
{
new MasteryLevel(1, "#00B0F0"),
new MasteryLevel(2, "#00B050"),
new MasteryLevel(3, "#FFFC00"),
new MasteryLevel(4)
}
);
}

public record ArchitectureLayer(string Value, string? Color = null);
public record Activity(string Value, string? Color = null);
public record MasteryLevel(int Value, string? Color = null);
8 changes: 8 additions & 0 deletions Epsilon.Canvas.Abstractions/Model/GraphQL/AssessmentRating.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Text.Json.Serialization;

namespace Epsilon.Canvas.Abstractions.Model.GraphQL;

public record AssessmentRating(
[property: JsonPropertyName("points")] double? Points,
[property: JsonPropertyName("outcome")] Outcome? Outcome
);
8 changes: 8 additions & 0 deletions Epsilon.Canvas.Abstractions/Model/GraphQL/Assignment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Text.Json.Serialization;

namespace Epsilon.Canvas.Abstractions.Model.GraphQL;

public record Assignment(
[property: JsonPropertyName("name")] string Name,
[property: JsonPropertyName("modules")] List<Module>? Modules
);
8 changes: 8 additions & 0 deletions Epsilon.Canvas.Abstractions/Model/GraphQL/Course.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Text.Json.Serialization;

namespace Epsilon.Canvas.Abstractions.Model.GraphQL;

public record Course(
[property: JsonPropertyName("name")] string Name,
[property: JsonPropertyName("submissionsConnection")] SubmissionsConnection? SubmissionsConnection
);
7 changes: 7 additions & 0 deletions Epsilon.Canvas.Abstractions/Model/GraphQL/Module.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using System.Text.Json.Serialization;

namespace Epsilon.Canvas.Abstractions.Model.GraphQL;

public record Module(
[property: JsonPropertyName("name")] string Name
);
8 changes: 8 additions & 0 deletions Epsilon.Canvas.Abstractions/Model/GraphQL/Node.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Text.Json.Serialization;

namespace Epsilon.Canvas.Abstractions.Model.GraphQL;

public record Node(
[property: JsonPropertyName("assignment")] Assignment? Assignment,
[property: JsonPropertyName("rubricAssessmentsConnection")] RubricAssessmentsConnection? RubricAssessmentsConnection
);
7 changes: 7 additions & 0 deletions Epsilon.Canvas.Abstractions/Model/GraphQL/Outcome.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using System.Text.Json.Serialization;

namespace Epsilon.Canvas.Abstractions.Model.GraphQL;

public record Outcome(
[property: JsonPropertyName("title")] string? Title
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Text.Json.Serialization;

namespace Epsilon.Canvas.Abstractions.Model.GraphQL;

public record RubricAssessmentNode(
[property: JsonPropertyName("assessmentRatings")] List<AssessmentRating>? AssessmentRatings,
[property: JsonPropertyName("user")] User? User
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using System.Text.Json.Serialization;

namespace Epsilon.Canvas.Abstractions.Model.GraphQL;

public record RubricAssessmentsConnection(
[property: JsonPropertyName("nodes")] List<RubricAssessmentNode>? Nodes
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using System.Text.Json.Serialization;

namespace Epsilon.Canvas.Abstractions.Model.GraphQL;

public record SubmissionsConnection(
[property: JsonPropertyName("nodes")] List<Node>? Nodes
);
7 changes: 7 additions & 0 deletions Epsilon.Canvas.Abstractions/Model/GraphQL/User.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using System.Text.Json.Serialization;

namespace Epsilon.Canvas.Abstractions.Model.GraphQL;

public record User(
[property: JsonPropertyName("name")] string Name
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Text.Json.Serialization;
using Epsilon.Canvas.Abstractions.Model.GraphQL;

namespace Epsilon.Canvas.Abstractions.QueryResponse;

public record GetUserSubmissionOutcomes(
HansenSven marked this conversation as resolved.
Show resolved Hide resolved
[property: JsonPropertyName("data")] GetUserSubmissionOutcomes.CourseData? Data
)
{
public record CourseData(
[property: JsonPropertyName("course")] Course? Course
);
};
6 changes: 6 additions & 0 deletions Epsilon.Canvas.Abstractions/Service/IGraphQlHttpService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Epsilon.Canvas.Abstractions.Service;

public interface IGraphQlHttpService
{
public Task<T?> Query<T>(string query);
}
2 changes: 1 addition & 1 deletion Epsilon.Canvas/CanvasModuleCollectionFetcher.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Diagnostics;
using Epsilon.Canvas.Abstractions;
using Epsilon.Canvas.Abstractions.Model;
using Epsilon.Canvas.Abstractions.QueryResponse;
using Epsilon.Canvas.Abstractions.Service;
using Microsoft.Extensions.Logging;

Expand All @@ -12,7 +13,6 @@ public class CanvasModuleCollectionFetcher : ICanvasModuleCollectionFetcher
private readonly IOutcomeHttpService _outcomeService;

public CanvasModuleCollectionFetcher(
ILogger<CanvasModuleCollectionFetcher> logger,
IModuleHttpService moduleService,
IOutcomeHttpService outcomeService
)
Expand Down
1 change: 1 addition & 0 deletions Epsilon.Canvas/CanvasServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static IServiceCollection AddCanvas(this IServiceCollection services, ICo
services.AddHttpClient<IAssignmentHttpService, AssignmentHttpService>(CanvasHttpClient);
services.AddHttpClient<IOutcomeHttpService, OutcomeHttpService>(CanvasHttpClient);
services.AddHttpClient<ISubmissionHttpService, SubmissionHttpService>(CanvasHttpClient);
services.AddHttpClient<IGraphQlHttpService, GraphQlHttpService>(CanvasHttpClient);

services.AddScoped<ILinkHeaderConverter, LinkHeaderConverter>();

Expand Down
35 changes: 35 additions & 0 deletions Epsilon.Canvas/QueryConstants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace Epsilon.Canvas;

public static class QueryConstants
{
public const string GetUserSubmissionOutcomes = @"
query GetUserSubmissionOutcomes {
course(id: $courseId) {
name
submissionsConnection {
nodes {
assignment {
name
modules {
name
}
}
rubricAssessmentsConnection {
nodes {
assessmentRatings {
points
outcome {
title
}
}
user {
name
}
}
}
}
}
}
}
";
}
22 changes: 22 additions & 0 deletions Epsilon.Canvas/Service/GraphQlHttpService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Net.Http.Json;
using Epsilon.Abstractions.Http;
using Epsilon.Canvas.Abstractions.Service;

namespace Epsilon.Canvas.Service;

public class GraphQlHttpService : HttpService, IGraphQlHttpService
{
public GraphQlHttpService(HttpClient client) : base(client)
{ }

public async Task<T?> Query<T>(string query)
{
var request = new HttpRequestMessage(HttpMethod.Post, "/api/graphql") {
Content = new FormUrlEncodedContent(new Dictionary<string, string>() {{"query", query}})
};

var response = await Client.SendAsync(request);

return await response.Content.ReadFromJsonAsync<T>();
}
}
65 changes: 65 additions & 0 deletions Epsilon.Host.WebApi/Controllers/ComponentController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using Epsilon.Abstractions.Model;
using Epsilon.Canvas;
using Epsilon.Canvas.Abstractions;
using Epsilon.Canvas.Abstractions.QueryResponse;
using Epsilon.Canvas.Abstractions.Service;
using Microsoft.AspNetCore.Mvc;

namespace Epsilon.Host.WebApi.Controllers;

[ApiController]
[Route("component")]
public class ComponentController : ControllerBase
{
private readonly IGraphQlHttpService _graphQlService;
private readonly IConfiguration _configuration;

public ComponentController(IGraphQlHttpService graphQlService, IConfiguration configuration)
{
_graphQlService = graphQlService;
_configuration = configuration;
}

[HttpGet("competence_profile")]
public ActionResult<GetUserSubmissionOutcomes> GetCompetenceProfile([FromQuery] DateTime startDate, [FromQuery] DateTime endDate)
{
var courseId = _configuration["Canvas:CourseId"];
var query = QueryConstants.GetUserSubmissionOutcomes.Replace("$courseId", courseId);

return _graphQlService.Query<GetUserSubmissionOutcomes>(query).Result!;
}

[HttpGet("competence_profile_mock")]
public ActionResult<CompetenceProfile> GetMockCompetenceProfile([FromQuery] DateTime startDate, [FromQuery] DateTime endDate)
{
var competenceProfileOutcomes = new List<CompetenceProfileOutcome>();
for (var i = 0; i < 5; i++)
{
competenceProfileOutcomes.Add(GetRandomCompetenceProfileOutcome());
}

return new CompetenceProfile(
HboIDomain.HboIDomain2018,
competenceProfileOutcomes
);
}

private static CompetenceProfileOutcome GetRandomCompetenceProfileOutcome()
{
return new CompetenceProfileOutcome(
GetRandom(HboIDomain.HboIDomain2018.ArchitectureLayers).Value,
GetRandom(HboIDomain.HboIDomain2018.Activities).Value,
GetRandom(HboIDomain.HboIDomain2018.MasteryLevels).Value,
GetRandom(new[] { 0, 3, 4, 5 }),
DateTime.Now
);
}

private static T GetRandom<T>(IEnumerable<T> items)
{
var random = new Random();
var itemsArray = items.ToArray();
var index = random.Next(0, itemsArray.Length);
return itemsArray.ElementAt(index);
}
HansenSven marked this conversation as resolved.
Show resolved Hide resolved
}
2 changes: 1 addition & 1 deletion Epsilon.Host.WebApi/Epsilon.Host.WebApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</ItemGroup>

<ItemGroup>
<Folder Include="Controllers" />
<ProjectReference Include="..\Epsilon\Epsilon.csproj" />
</ItemGroup>

</Project>
6 changes: 6 additions & 0 deletions Epsilon.Host.WebApi/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
using Epsilon.Canvas;
using Epsilon.Canvas.Abstractions.Service;
using Epsilon.Canvas.Service;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var canvasConfiguration = builder.Configuration.GetSection("Canvas");

builder.Services.AddCanvas(canvasConfiguration);
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
Expand Down
8 changes: 0 additions & 8 deletions Epsilon.Host.WebApi/appsettings.Development.json

This file was deleted.