using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Unity.Multiplayer.Center.Analytics;
using Unity.Multiplayer.Center.Common;
using Unity.Multiplayer.Center.Recommendations;
namespace Unity.MultiplayerCenterTests
{
[TestFixture]
internal class AnalyticsUtilsTests
{
[Test]
public void AnalyticsUtils_GetQuestionDisplayNames_RightCount()
{
var questionnaire = UtilsForRecommendationTests.GetProjectQuestionnaire();
var questionDisplayNames = AnalyticsUtils.GetQuestionDisplayNames(questionnaire);
Assert.AreEqual(questionDisplayNames.Count, questionnaire.Questions.Length);
}
///
/// Note: this test checks exact values and has to be adapted in case those display names change.
/// Why do that? To force the developers to think about the impact on the analytics!
/// Contact the engine-data team and product.
///
[Test]
public void AnalyticsUtils_GetQuestionDisplayNames_RightValuesForSelectedQuestions()
{
var questionnaire = UtilsForRecommendationTests.GetProjectQuestionnaire();
var questionDisplayNames = AnalyticsUtils.GetQuestionDisplayNames(questionnaire);
Assert.AreEqual("Number of Players per Session", questionDisplayNames["PlayerCount"]);
Assert.AreEqual("Gameplay Pace", questionDisplayNames["Pace"]);
Assert.AreEqual("Cheating / Modding Prevention", questionDisplayNames["Cheating"]);
Assert.AreEqual("Cost Sensitivity", questionDisplayNames["CostSensitivity"]);
Assert.AreEqual("Netcode Architecture", questionDisplayNames["NetcodeArchitecture"]);
}
[Test]
public void AnalyticsUtils_GetAnswerDisplayNames_RightCount()
{
var questionnaire = UtilsForRecommendationTests.GetProjectQuestionnaire();
var answerDisplayNames = AnalyticsUtils.GetAnswerDisplayNames(questionnaire);
// Note: 2 birds one stone: this test also nicely checks if we have duplicates with question ids
var expectedCount = questionnaire.Questions.Sum(question => question.Choices.Length);
Assert.AreEqual(answerDisplayNames.Count, expectedCount);
}
[Test]
public void AnalyticsUtils_GetPresetFullNames_RightCountAndIntValuesDidNotChange()
{
var presetFullNames = AnalyticsUtils.GetPresetFullNames();
Assert.AreEqual(12, presetFullNames.Length);
}
///
/// Note: this test checks exact values and has to be adapted in case those display names change.
/// Why do that? To force the developers to think about the impact on the analytics!
/// Contact the engine-data team and product.
///
[Test]
public void AnalyticsUtils_GetPresetFullNames_RightValues()
{
var presetFullNames = AnalyticsUtils.GetPresetFullNames();
Assert.AreEqual("-", presetFullNames[0]);
Assert.AreEqual("Adventure", presetFullNames[1]);
Assert.AreEqual("Shooter, Battle Royale, Battle Arena", presetFullNames[2]);
Assert.AreEqual("Racing", presetFullNames[3]);
Assert.AreEqual("Card Battle, Turn-based, Tabletop", presetFullNames[4]);
Assert.AreEqual("Simulation", presetFullNames[5]);
Assert.AreEqual("Strategy", presetFullNames[6]);
Assert.AreEqual("Sports", presetFullNames[7]);
Assert.AreEqual("Role-Playing, MMO", presetFullNames[8]);
Assert.AreEqual("Async, Idle, Hyper Casual, Puzzle", presetFullNames[9]);
Assert.AreEqual("Fighting", presetFullNames[10]);
Assert.AreEqual("Arcade, Platformer, Sandbox", presetFullNames[11]);
}
[Test]
public void AnalyticsUtils_ToGameSpecs_AllIdsAreInTheGameSpecs()
{
var questionnaire = UtilsForRecommendationTests.GetProjectQuestionnaire();
var answerDisplayNames = AnalyticsUtils.GetAnswerDisplayNames(questionnaire);
var answerData = UtilsForRecommendationTests.BuildAnswerMatching(questionnaire);
var questionIdToQuestionName = AnalyticsUtils.GetQuestionDisplayNames(questionnaire);
var gameSpecs = AnalyticsUtils.ToGameSpecs(answerData, answerDisplayNames, questionIdToQuestionName);
Assert.AreEqual(answerData.Answers.Count, gameSpecs.Length);
var questionIdsFromAnswerData = answerData.Answers.Select(answer => answer.QuestionId).ToArray();
var questionIdsFromGameSpecs = gameSpecs.Select(spec => spec.QuestionId).ToArray();
CollectionAssert.AreEquivalent(questionIdsFromAnswerData, questionIdsFromGameSpecs);
}
[Test]
public void AnalyticsUtils_ToGameSpecs_ValueCheck()
{
var answerDisplayNames = new Dictionary(){
{"A1", "Display Name A1"},
{"A2", "Display Name A2"},
{"A3", "Display Name A3"},
{"A4", "Display Name A4"}
};
var questionIdToQuestionName = new Dictionary()
{
{"Q1", "Display Name Q1"},
{"Q2", "Display Name Q2"}
};
var answerData = new AnswerData()
{
Answers = new List()
{
new() {QuestionId = "Q2", Answers = new List() {"A3"}},
new() {QuestionId = "Q1", Answers = new List() {"A1"}}
}
};
var gameSpecs = AnalyticsUtils.ToGameSpecs(answerData, answerDisplayNames, questionIdToQuestionName);
var expectedGameSpecs = new GameSpec[]
{
new (){ QuestionId = "Q2", QuestionText = "Display Name Q2", AcceptsMultipleAnswers = false, AnswerId = "A3", AnswerText = "Display Name A3"},
new (){ QuestionId = "Q1", QuestionText = "Display Name Q1", AcceptsMultipleAnswers = false, AnswerId = "A1", AnswerText = "Display Name A1"},
};
CollectionAssert.AreEquivalent(expectedGameSpecs, gameSpecs);
}
[Test]
public void AnalyticsUtils_ToGameSpecs_NoEmptyString()
{
GetAnswersWithMatchingAnalyticsData(out var _, out var gameSpecs);
foreach (var spec in gameSpecs)
{
Assert.False(string.IsNullOrEmpty(spec.QuestionId), spec.QuestionId);
Assert.False(string.IsNullOrEmpty(spec.QuestionText), spec.QuestionText);
Assert.False(string.IsNullOrEmpty(spec.AnswerId), spec.AnswerId);
Assert.False(string.IsNullOrEmpty(spec.AnswerText), spec.AnswerText);
}
}
[Test]
public void AnalyticsUtils_AssumptionTest_HardCodedNumNetcodePackageMatchesRecommendations()
{
// note that the amount of possible netcode does not change with the answer data.
var someRecommendation = UtilsForRecommendationTests.GetSomeRecommendation();
var netcodePackageCount = someRecommendation.NetcodeOptions.Count(e
=> !string.IsNullOrEmpty(e.MainPackage?.PackageId));
Assert.AreEqual(netcodePackageCount, AnalyticsUtils.NumNetcodePackage);
}
[Test]
public void AnalyticsUtils_AssumptionTest_HardCodedNumHostingPackageMatchesRecommendations()
{
// note that the amount of possible netcode does not change with the answer data.
var someRecommendation = UtilsForRecommendationTests.GetSomeRecommendation();
var hostingPackageCount = someRecommendation.ServerArchitectureOptions.Count(e
=> !string.IsNullOrEmpty(e.MainPackage?.PackageId));
Assert.AreEqual(hostingPackageCount, AnalyticsUtils.NumHostingPackages);
}
[Test]
public void AnalyticsUtils_GetPackagesWithAnalyticsFormat_NetcodeValuesMakeSense()
{
const string ngo = "com.unity.netcode.gameobjects";
const string n4e = "com.unity.netcode";
const string tp = "com.unity.transport";
var someRecommendation = UtilsForRecommendationTests.GetSomeRecommendation();
var packageViews = RecommenderSystem.GetSolutionsToRecommendedPackageViewData();
var packagesAnalyticsFormat = AnalyticsUtils.GetPackagesWithAnalyticsFormat(someRecommendation, packageViews);
// all netcode packages are in the array
Assert.AreEqual(1,packagesAnalyticsFormat.Count(e => e.PackageId == ngo) );
Assert.AreEqual(1, packagesAnalyticsFormat.Count(e => e.PackageId == n4e));
Assert.AreEqual(1, packagesAnalyticsFormat.Count(e => e.PackageId == tp));
var netcodePackages = packagesAnalyticsFormat.Where(e => e.PackageId is ngo or n4e or tp).ToArray();
Assert.AreEqual(3, netcodePackages.Count()); // exactly 3 matches
Assert.AreEqual(1, netcodePackages.Count(e => e.SelectedForInstall)); // 1 selected
Assert.AreEqual(1, netcodePackages.Count(e => e.IsRecommended)); // 1 recommended
// Since we only look at the project direct dependencies, 1 netcode max can be installed in a normal setup
// edge case would be: some installed ngo/n4e and manually added Transport to the manifest
Assert.True(netcodePackages.Count(e => e.IsAlreadyInstalled) <= 1);
}
[Test]
public void AnalyticsUtils_GetPackagesWithAnalyticsFormat_AllPackagesAreIn()
{
var someRecommendation = UtilsForRecommendationTests.GetSomeRecommendation();
var packageViews = RecommenderSystem.GetSolutionsToRecommendedPackageViewData();
var packagesAnalyticsFormat = AnalyticsUtils.GetPackagesWithAnalyticsFormat(someRecommendation, packageViews);
var allPackages = RecommenderSystemDataObject.instance.RecommenderSystemData.PackageDetailsById.Keys;
foreach (var id in allPackages)
{
Assert.AreEqual(1, packagesAnalyticsFormat.Count(e => e.PackageId == id), id);
}
}
static void GetAnswersWithMatchingAnalyticsData(out AnswerData answerData, out GameSpec[] gameSpecs)
{
var questionnaire = UtilsForRecommendationTests.GetProjectQuestionnaire();
var answerDisplayNames = AnalyticsUtils.GetAnswerDisplayNames(questionnaire);
answerData = UtilsForRecommendationTests.BuildAnswerMatching(questionnaire);
var questionIdToQuestionName = AnalyticsUtils.GetQuestionDisplayNames(questionnaire);
gameSpecs = AnalyticsUtils.ToGameSpecs(answerData, answerDisplayNames, questionIdToQuestionName);
}
}
}