feat: add optional student nickname for informal display
Keep legal first and last names for formal lists; show DisplayFirstName on teams, calendars, and import matching so two Josiahs can be told apart. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
using System.Text;
|
||||
using Core.Entities;
|
||||
using Core.Models;
|
||||
using Core.Parsers;
|
||||
using Tests.Builders;
|
||||
|
||||
namespace Tests.Parsers;
|
||||
|
||||
public class AssignmentRequirement_Tests
|
||||
@@ -16,4 +22,53 @@ public class AssignmentRequirement_Tests
|
||||
|
||||
Assert.Pass();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_MatchesNicknameColumnsForTwoJosiahs()
|
||||
{
|
||||
StudentBuilder.ResetIdCounter();
|
||||
var jo = StudentBuilder.Create("Josiah", "Brown").WithNickname("Jo").Build();
|
||||
var josiahB = StudentBuilder.Create("Josiah", "Green").WithNickname("Josiah B").Build();
|
||||
var coding = EventDefinitionBuilder.Individual("Coding").WithShortName("Coding").Build();
|
||||
|
||||
const string csv = """
|
||||
,Jo,josiah b
|
||||
Coding,i,x
|
||||
""";
|
||||
|
||||
var requirements = ParseCsv(csv, [coding], [jo, josiahB]);
|
||||
|
||||
Assert.That(requirements, Has.Length.EqualTo(2));
|
||||
Assert.That(requirements.Single(r => r.Student.Id == jo.Id).Requirement, Is.EqualTo(Requirement.Include));
|
||||
Assert.That(requirements.Single(r => r.Student.Id == josiahB.Id).Requirement, Is.EqualTo(Requirement.Exclude));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_SharedLegalFirstName_TakesFirstStudent()
|
||||
{
|
||||
StudentBuilder.ResetIdCounter();
|
||||
var first = StudentBuilder.Create("Josiah", "Brown").WithNickname("Jo").Build();
|
||||
var second = StudentBuilder.Create("Josiah", "Green").WithNickname("Josiah B").Build();
|
||||
var coding = EventDefinitionBuilder.Individual("Coding").WithShortName("Coding").Build();
|
||||
|
||||
const string csv = """
|
||||
,Josiah
|
||||
Coding,i
|
||||
""";
|
||||
|
||||
var requirements = ParseCsv(csv, [coding], [first, second]);
|
||||
|
||||
Assert.That(requirements, Has.Length.EqualTo(1));
|
||||
Assert.That(requirements[0].Student.Id, Is.EqualTo(first.Id));
|
||||
}
|
||||
|
||||
private static AssignmentRequirement[] ParseCsv(
|
||||
string csv,
|
||||
ICollection<EventDefinition> events,
|
||||
ICollection<Student> students)
|
||||
{
|
||||
using var reader = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(csv)));
|
||||
using var parser = new AssignmentRequirementParser(reader);
|
||||
return parser.Parse(events, students);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using Core.Parsers;
|
||||
using Tests.Builders;
|
||||
|
||||
namespace Tests.Parsers;
|
||||
|
||||
[TestFixture]
|
||||
public class FuzzyStudentMatcher_Tests
|
||||
{
|
||||
[SetUp]
|
||||
public void SetUp() => StudentBuilder.ResetIdCounter();
|
||||
|
||||
[Test]
|
||||
public void Find_MatchesNicknameAmongTwoJosiahs()
|
||||
{
|
||||
var jo = StudentBuilder.Create("Josiah", "Brown").WithNickname("Jo").Build();
|
||||
var josiahB = StudentBuilder.Create("Josiah", "Green").WithNickname("Josiah B").Build();
|
||||
|
||||
var match = FuzzyStudentMatcher.Find([jo, josiahB], "Jo");
|
||||
|
||||
Assert.That(match, Is.Not.Null);
|
||||
Assert.That(match!.Value.Student.Id, Is.EqualTo(jo.Id));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Score_LegalNameStillMatchesWhenNicknameSet()
|
||||
{
|
||||
var jo = StudentBuilder.Create("Josiah", "Brown").WithNickname("Jo").Build();
|
||||
|
||||
Assert.That(FuzzyStudentMatcher.Score(jo, "Josiah Brown"), Is.GreaterThanOrEqualTo(FuzzyStudentMatcher.MatchThreshold));
|
||||
Assert.That(FuzzyStudentMatcher.Score(jo, "Brown, Josiah"), Is.GreaterThanOrEqualTo(FuzzyStudentMatcher.MatchThreshold));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Score_NullNicknameDoesNotThrow()
|
||||
{
|
||||
var student = StudentBuilder.Create("Aria", "Cole").Build();
|
||||
|
||||
Assert.That(FuzzyStudentMatcher.Score(student, "Aria Cole"), Is.GreaterThanOrEqualTo(FuzzyStudentMatcher.MatchThreshold));
|
||||
Assert.That(FuzzyStudentMatcher.Find([student], "Nobody"), Is.Null);
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,21 @@ public class StudentEventRankingParser_Tests
|
||||
Assert.That(result.Matches[0].Ranking.Student, Is.SameAs(_aria));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_NicknamePlusLastName_MatchesStudent()
|
||||
{
|
||||
var jo = StudentBuilder.Create("Josiah", "Brown").WithNickname("Jo").Build();
|
||||
|
||||
var result = ParseCsv("""
|
||||
Student Name,1
|
||||
Jo Brown,Coding
|
||||
""", [jo], _events);
|
||||
|
||||
Assert.That(result.IsSuccess, Is.True);
|
||||
Assert.That(result.Matches, Has.Count.EqualTo(1));
|
||||
Assert.That(result.Matches[0].Ranking.Student, Is.SameAs(jo));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_ShortName_MatchesEvent()
|
||||
{
|
||||
|
||||
@@ -34,6 +34,22 @@ public class StudentNotesFieldParser_Tests
|
||||
Assert.That(result.Issues[0].RawStudentName, Is.EqualTo("Nobody Here"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_MatchesNicknamePlusLastName()
|
||||
{
|
||||
var jo = StudentBuilder.Create("Josiah", "Brown").WithNickname("Jo").Build();
|
||||
const string csv = """
|
||||
Student Name,Interview Time
|
||||
Jo Brown,3:20-3:35
|
||||
""";
|
||||
|
||||
var result = Parse(csv, [jo]);
|
||||
|
||||
Assert.That(result.IsSuccess, Is.True);
|
||||
Assert.That(result.Matches, Has.Count.EqualTo(1));
|
||||
Assert.That(result.Matches[0].Student, Is.SameAs(jo));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_SameExistingNote_HasNoChanges()
|
||||
{
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
using System.Text;
|
||||
using Core.Parsers;
|
||||
using Tests.Builders;
|
||||
|
||||
namespace Tests.Parsers;
|
||||
|
||||
public class TeamParser_Tests
|
||||
@@ -37,4 +41,26 @@ public class TeamParser_Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_MatchesNicknameAndLegalStudentColumns()
|
||||
{
|
||||
StudentBuilder.ResetIdCounter();
|
||||
var jo = StudentBuilder.Create("Josiah", "Brown").WithNickname("Jo").Build();
|
||||
var josiahB = StudentBuilder.Create("Josiah", "Green").WithNickname("Josiah B").Build();
|
||||
var coding = EventDefinitionBuilder.Team("Coding", 2, 2).Build();
|
||||
|
||||
const string csv = """
|
||||
Team Name,Event Name,Regional Time Slot,Student 1,Student 2
|
||||
A,Coding,,Jo,Josiah Green
|
||||
""";
|
||||
|
||||
using var reader = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(csv)));
|
||||
using var parser = new TeamParser(reader);
|
||||
var teams = parser.Parse([coding], [jo, josiahB]);
|
||||
|
||||
Assert.That(teams, Has.Length.EqualTo(1));
|
||||
Assert.That(teams[0].Students.Select(s => s.Id), Is.EquivalentTo(new[] { jo.Id, josiahB.Id }));
|
||||
Assert.That(teams[0].Captain!.Id, Is.EqualTo(jo.Id));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user