School Commit Init
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.9.34622.214
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lab1", "Lab1\Lab1.csproj", "{5DDE8D84-CE84-4F12-A8DD-38B99E1BBAAF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{5DDE8D84-CE84-4F12-A8DD-38B99E1BBAAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5DDE8D84-CE84-4F12-A8DD-38B99E1BBAAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5DDE8D84-CE84-4F12-A8DD-38B99E1BBAAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5DDE8D84-CE84-4F12-A8DD-38B99E1BBAAF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5D743BF4-E6DC-4DFA-B47E-523157CEBD69}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
namespace Lab1
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
private static System.Timers.Timer? aTimer;
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
aTimer = new System.Timers.Timer
|
||||
{
|
||||
Interval = 1000
|
||||
};
|
||||
aTimer.Elapsed += OnTimedEvent;
|
||||
aTimer.Start();
|
||||
Console.Read();
|
||||
return;
|
||||
}
|
||||
|
||||
public static void OnTimedEvent(object? source, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
Console.Clear();
|
||||
Console.WriteLine("Date:");
|
||||
Console.WriteLine($"Decimal: {now.Day:D2}/{now.Month:D2}/{now.Year:D4}");
|
||||
Console.WriteLine($"Hexa: {now.Day:X2}/{now.Month:X2}/{now.Year:X4}");
|
||||
Console.WriteLine($"Binary: {now.Day:b5}/{now.Month:b4}/{now.Year:b16}");
|
||||
Console.WriteLine("Time:");
|
||||
Console.WriteLine($"Decimal: {now.Hour:D2}:{now.Minute:D2}:{now.Second:D2}");
|
||||
Console.WriteLine($"Hexa: {now.Hour:X2}:{now.Minute:X2}:{now.Second:X2}");
|
||||
Console.WriteLine($"Binary: {now.Hour:b6}:{now.Minute:b6}:{now.Second:b6}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,122 @@
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
namespace CacheModule{
|
||||
|
||||
public class CacheService
|
||||
{
|
||||
private readonly Dictionary<string, Dictionary<string, CachedObject>> _cache = new Dictionary<string, Dictionary<string, CachedObject>>();
|
||||
|
||||
private static object _lock = new object();
|
||||
|
||||
private readonly Timer _timer = new Timer();
|
||||
|
||||
private static CacheService? _instance;
|
||||
|
||||
private CacheService(){
|
||||
_timer.Interval = 3600 * 1000;
|
||||
_timer.Elapsed += (sender, e) => ClearExpired();
|
||||
_timer.Start();
|
||||
}
|
||||
public static CacheService Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new CacheService();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(string functionName, string functionParams, object value, Duration duration)
|
||||
{
|
||||
Add(functionName, functionParams, value, (int)duration);
|
||||
}
|
||||
|
||||
public void Add(string functionName, string functionParams, object value, int duration)
|
||||
{
|
||||
if (!_cache.ContainsKey(functionName))
|
||||
{
|
||||
_cache[functionName] = new Dictionary<string, CachedObject>();
|
||||
}
|
||||
|
||||
_cache[functionName][functionParams] = new CachedObject(){
|
||||
Value = value,
|
||||
Timestamp = DateTime.Now,
|
||||
Duration = duration
|
||||
};
|
||||
}
|
||||
|
||||
public object? Get(string functionName, string functionParams)
|
||||
{
|
||||
if (!_cache.ContainsKey(functionName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!_cache[functionName].ContainsKey(functionParams))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var cachedObject = _cache[functionName][functionParams];
|
||||
if (cachedObject.IsExpired())
|
||||
{
|
||||
_cache[functionName].Remove(functionParams);
|
||||
return null;
|
||||
}
|
||||
return cachedObject.Value;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_cache.Clear();
|
||||
}
|
||||
|
||||
public void Clear(string functionName)
|
||||
{
|
||||
if (_cache.ContainsKey(functionName))
|
||||
{
|
||||
_cache.Remove(functionName);
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear(string functionName, string functionParams)
|
||||
{
|
||||
if (_cache.ContainsKey(functionName))
|
||||
{
|
||||
if (_cache[functionName].ContainsKey(functionParams))
|
||||
{
|
||||
_cache[functionName].Remove(functionParams);
|
||||
if (_cache[functionName].Count == 0)
|
||||
{
|
||||
_cache.Remove(functionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearExpired()
|
||||
{
|
||||
foreach (var functionName in _cache.Keys)
|
||||
{
|
||||
foreach (var functionParams in _cache[functionName].Keys)
|
||||
{
|
||||
if (_cache[functionName][functionParams].IsExpired())
|
||||
{
|
||||
_cache[functionName].Remove(functionParams);
|
||||
if (_cache[functionName].Count == 0)
|
||||
{
|
||||
_cache.Remove(functionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace CacheModule{
|
||||
|
||||
public class CachedObject
|
||||
{
|
||||
public object? Value { get; set; }
|
||||
public DateTime Timestamp {get; set; }
|
||||
public int Duration { get; set; }
|
||||
|
||||
public bool IsExpired()
|
||||
{
|
||||
return DateTime.Now > Timestamp.AddSeconds(Duration);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace CacheModule{
|
||||
public enum Duration
|
||||
{
|
||||
OneSecond = 1,
|
||||
OneMinute = 60,
|
||||
OneHour = 3600,
|
||||
OneDay = 86400,
|
||||
OneWeek = 604800,
|
||||
OneMonth = 2592000,
|
||||
OneYear = 31536000,
|
||||
FiveSeconds = 5,
|
||||
ThirtySeconds = 30,
|
||||
ThirtyMinutes = 1800,
|
||||
SixHours = 21600,
|
||||
TwelveHours = 43200,
|
||||
TwoDays = 172800,
|
||||
ThreeDays = 259200,
|
||||
TwoWeeks = 1209600,
|
||||
ThreeMonths = 7776000,
|
||||
SixMonths = 15552000
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CacheModule\CacheModule.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,134 @@
|
||||
using Xunit;
|
||||
using CacheModule;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CacheModuleTest{
|
||||
public class CacheServiceIntegratedTest
|
||||
{
|
||||
private class MockIntegration{
|
||||
private CacheService _cacheService;
|
||||
public Dictionary<string, List<int>> keyValuePairs = new Dictionary<string, List<int>>(){
|
||||
{"first", new List<int>(){1,2,3}},
|
||||
{"second", new List<int>(){4,5,6}},
|
||||
{"third", new List<int>(){7,8,9}}
|
||||
};
|
||||
public MockIntegration(){
|
||||
_cacheService = CacheService.Instance;
|
||||
}
|
||||
|
||||
public int Get(string key, int index){
|
||||
return keyValuePairs[key][index];
|
||||
}
|
||||
public int GetSum(string key){
|
||||
return keyValuePairs[key].Sum();
|
||||
}
|
||||
|
||||
public int CachedGet(string key, int index){
|
||||
var json = JsonConvert.SerializeObject(new List<object>(){key, index}) ?? string.Empty;
|
||||
var cachedObject = _cacheService.Get(nameof(Get), json);
|
||||
if(cachedObject != null){
|
||||
return (int)cachedObject;
|
||||
}
|
||||
var result = Get(key, index);
|
||||
_cacheService.Add(nameof(Get), json, result, Duration.OneMinute);
|
||||
return result;
|
||||
}
|
||||
|
||||
public int CachedGetSum(string key){
|
||||
var json = JsonConvert.SerializeObject(new List<object>(){key}) ?? string.Empty;
|
||||
var cachedObject = _cacheService.Get(nameof(GetSum), json);
|
||||
if(cachedObject != null){
|
||||
return (int)cachedObject;
|
||||
}
|
||||
var result = GetSum(key);
|
||||
_cacheService.Add(nameof(GetSum), json, result, Duration.OneMinute);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Clear(){
|
||||
_cacheService.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CachedGet_WhenCalledWithinDuration_ReturnsCachedValue()
|
||||
{
|
||||
// Arrange
|
||||
var mockIntegration = new MockIntegration();
|
||||
mockIntegration.Clear();
|
||||
var key = "first";
|
||||
var index = 1;
|
||||
var expected = mockIntegration.Get(key, index);
|
||||
var cachedExpected = mockIntegration.CachedGet(key, index);
|
||||
mockIntegration.keyValuePairs[key][index] = 100;
|
||||
|
||||
// Act
|
||||
var cachedResult = mockIntegration.CachedGet(key, index);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, cachedResult);
|
||||
Assert.Equal(cachedExpected, cachedResult);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CachedGet_WhenCalledAfterDuration_ReturnsNewValue()
|
||||
{
|
||||
// Arrange
|
||||
var mockIntegration = new MockIntegration();
|
||||
mockIntegration.Clear();
|
||||
var key = "first";
|
||||
var index = 1;
|
||||
var expected = mockIntegration.Get(key, index);
|
||||
var cachedExpected = mockIntegration.CachedGet(key, index);
|
||||
mockIntegration.keyValuePairs[key][index] = 100;
|
||||
|
||||
// Act
|
||||
System.Threading.Thread.Sleep(61000);
|
||||
var cachedResult = mockIntegration.CachedGet(key, index);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(100, cachedResult);
|
||||
Assert.NotEqual(cachedExpected, cachedResult);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CachedGetSum_WhenCalledWithinDuration_ReturnsCachedValue()
|
||||
{
|
||||
// Arrange
|
||||
var mockIntegration = new MockIntegration();
|
||||
mockIntegration.Clear();
|
||||
var key = "first";
|
||||
var expected = mockIntegration.GetSum(key);
|
||||
var cachedExpected = mockIntegration.CachedGetSum(key);
|
||||
mockIntegration.keyValuePairs[key] = new List<int>(){100, 100, 100};
|
||||
|
||||
// Act
|
||||
var cachedResult = mockIntegration.CachedGetSum(key);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, cachedResult);
|
||||
Assert.Equal(cachedExpected, cachedResult);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CachedGetSum_WhenCalledAfterDuration_ReturnsNewValue()
|
||||
{
|
||||
// Arrange
|
||||
var mockIntegration = new MockIntegration();
|
||||
mockIntegration.Clear();
|
||||
var key = "first";
|
||||
var expected = mockIntegration.GetSum(key);
|
||||
var cachedExpected = mockIntegration.CachedGetSum(key);
|
||||
mockIntegration.keyValuePairs[key] = new List<int>(){100, 100, 100};
|
||||
|
||||
// Act
|
||||
System.Threading.Thread.Sleep(61000);
|
||||
var cachedResult = mockIntegration.CachedGetSum(key);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(300, cachedResult);
|
||||
Assert.NotEqual(cachedExpected, cachedResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
using Xunit;
|
||||
using CacheModule;
|
||||
|
||||
namespace CacheModuleTest{
|
||||
public class CacheServiceUnitTest
|
||||
{
|
||||
[Fact]
|
||||
public void Instance_WhenCalled_ReturnsSameInstance()
|
||||
{
|
||||
// Arrange
|
||||
var cacheService1 = CacheService.Instance;
|
||||
var cacheService2 = CacheService.Instance;
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
Assert.Same(cacheService1, cacheService2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Add_WhenCalledWithinDuration_AddsToCache()
|
||||
{
|
||||
// Arrange
|
||||
var cacheService = CacheService.Instance;
|
||||
cacheService.Clear();
|
||||
var functionName = "functionName";
|
||||
var functionParams = "functionParams";
|
||||
var value = new object();
|
||||
|
||||
// Act
|
||||
cacheService.Add(functionName, functionParams, value, Duration.OneMinute);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(value, cacheService.Get(functionName, functionParams));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Add_WhenCalledAfterDuration_RemovesFromCache()
|
||||
{
|
||||
// Arrange
|
||||
var cacheService = CacheService.Instance;
|
||||
cacheService.Clear();
|
||||
var functionName = "functionName";
|
||||
var functionParams = "functionParams";
|
||||
var value = new object();
|
||||
|
||||
// Act
|
||||
cacheService.Add(functionName, functionParams, value, Duration.OneSecond);
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Assert
|
||||
Assert.Null(cacheService.Get(functionName, functionParams));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Add_WhenCalledWithSameFunctionNameAndFunctionParams_OverwritesCache()
|
||||
{
|
||||
// Arrange
|
||||
var cacheService = CacheService.Instance;
|
||||
cacheService.Clear();
|
||||
var functionName = "functionName";
|
||||
var functionParams = "functionParams";
|
||||
var value1 = new object();
|
||||
var value2 = new object();
|
||||
|
||||
// Act
|
||||
cacheService.Add(functionName, functionParams, value1, Duration.OneMinute);
|
||||
cacheService.Add(functionName, functionParams, value2, Duration.OneMinute);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(value2, cacheService.Get(functionName, functionParams));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Get_WhenCalledWithNonExistingFunctionName_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var cacheService = CacheService.Instance;
|
||||
cacheService.Clear();
|
||||
var functionName = "functionName";
|
||||
var functionParams = "functionParams";
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
Assert.Null(cacheService.Get(functionName, functionParams));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Get_WhenCalledWithNonExistingFunctionParams_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var cacheService = CacheService.Instance;
|
||||
cacheService.Clear();
|
||||
var functionName = "functionName";
|
||||
var functionParams = "functionParams";
|
||||
var value = new object();
|
||||
|
||||
// Act
|
||||
cacheService.Add(functionName, functionParams, value, Duration.OneMinute);
|
||||
|
||||
// Assert
|
||||
Assert.Null(cacheService.Get(functionName, "nonExistingFunctionParams"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Clear_WhenCalledWithParams_ClearsCache()
|
||||
{
|
||||
// Arrange
|
||||
var cacheService = CacheService.Instance;
|
||||
var functionName = "functionName";
|
||||
var functionParams = "functionParams";
|
||||
var value = new object();
|
||||
cacheService.Add(functionName, functionParams, value, Duration.OneMinute);
|
||||
|
||||
// Act
|
||||
cacheService.Clear();
|
||||
|
||||
// Assert
|
||||
Assert.Null(cacheService.Get(functionName, functionParams));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Clear_WhenCalledWithFunctionName_ClearsCache()
|
||||
{
|
||||
// Arrange
|
||||
var cacheService = CacheService.Instance;
|
||||
var functionName = "functionName";
|
||||
var functionParams = "functionParams";
|
||||
var functionName2 = "functionName2";
|
||||
var functionParams2 = "functionParams2";
|
||||
var value = new object();
|
||||
var value2 = new object();
|
||||
cacheService.Add(functionName, functionParams, value, Duration.OneMinute);
|
||||
cacheService.Add(functionName2, functionParams2, value2, Duration.OneMinute);
|
||||
|
||||
// Act
|
||||
cacheService.Clear(functionName);
|
||||
|
||||
// Assert
|
||||
Assert.Null(cacheService.Get(functionName, functionParams));
|
||||
Assert.Equal(value2, cacheService.Get(functionName2, functionParams2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Clear_WhenCalledWithFunctionNameAndFunctionParams_ClearsCache()
|
||||
{
|
||||
// Arrange
|
||||
var cacheService = CacheService.Instance;
|
||||
var functionName = "functionName";
|
||||
var functionParams = "functionParams";
|
||||
var functionParams2 = "functionParams2";
|
||||
var value = new object();
|
||||
var value2 = new object();
|
||||
cacheService.Add(functionName, functionParams, value, Duration.OneMinute);
|
||||
cacheService.Add(functionName, functionParams2, value2, Duration.OneMinute);
|
||||
|
||||
// Act
|
||||
cacheService.Clear(functionName, functionParams);
|
||||
|
||||
// Assert
|
||||
Assert.Null(cacheService.Get(functionName, functionParams));
|
||||
Assert.Equal(value2, cacheService.Get(functionName, functionParams2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClearExpired_WhenCalled_ClearsExpiredCache()
|
||||
{
|
||||
// Arrange
|
||||
var cacheService = CacheService.Instance;
|
||||
var functionName = "functionName";
|
||||
var functionParams = "functionParams";
|
||||
var functionName2 = "functionName2";
|
||||
var functionParams2 = "functionParams2";
|
||||
var value = new object();
|
||||
cacheService.Add(functionName, functionParams, value, Duration.OneSecond);
|
||||
cacheService.Add(functionName2, functionParams2, value, Duration.OneMinute);
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Act
|
||||
cacheService.ClearExpired();
|
||||
|
||||
// Assert
|
||||
Assert.Null(cacheService.Get(functionName, functionParams));
|
||||
Assert.Equal(value, cacheService.Get(functionName2, functionParams2));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CacheModule", "CacheModule\CacheModule.csproj", "{523A7A27-26EE-4F61-B316-8116D19CBC7E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CacheModuleTest", "CacheModuleTest\CacheModuleTest.csproj", "{B2120B94-F9E9-437C-A4D2-EC1643434A21}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{523A7A27-26EE-4F61-B316-8116D19CBC7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{523A7A27-26EE-4F61-B316-8116D19CBC7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{523A7A27-26EE-4F61-B316-8116D19CBC7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{523A7A27-26EE-4F61-B316-8116D19CBC7E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B2120B94-F9E9-437C-A4D2-EC1643434A21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B2120B94-F9E9-437C-A4D2-EC1643434A21}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B2120B94-F9E9-437C-A4D2-EC1643434A21}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B2120B94-F9E9-437C-A4D2-EC1643434A21}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
After Width: | Height: | Size: 710 KiB |
|
After Width: | Height: | Size: 160 KiB |
@@ -0,0 +1,377 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
.nuspec/
|
||||
.buildtasks/
|
||||
templatesTest/
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
tools/**
|
||||
!tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
.DS_Store
|
||||
|
||||
# Android Studio
|
||||
.gradle/
|
||||
.idea/
|
||||
local.properties
|
||||
|
||||
# Directory Build overrides for local setups
|
||||
Directory.Build.Override.props
|
||||
|
||||
# Only the "snapshots" directory should be added to Git, not the "snapshots-diff" directory
|
||||
snapshots-diff/
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.9.34723.18
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TechTitans", "TechTitans\TechTitans.csproj", "{29F15AA2-793A-43C6-B33B-D32F76EE30DC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Android Emulator|Any CPU = Android Emulator|Any CPU
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{29F15AA2-793A-43C6-B33B-D32F76EE30DC}.Android Emulator|Any CPU.ActiveCfg = Android Emulator|Any CPU
|
||||
{29F15AA2-793A-43C6-B33B-D32F76EE30DC}.Android Emulator|Any CPU.Build.0 = Android Emulator|Any CPU
|
||||
{29F15AA2-793A-43C6-B33B-D32F76EE30DC}.Android Emulator|Any CPU.Deploy.0 = Android Emulator|Any CPU
|
||||
{29F15AA2-793A-43C6-B33B-D32F76EE30DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{29F15AA2-793A-43C6-B33B-D32F76EE30DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{29F15AA2-793A-43C6-B33B-D32F76EE30DC}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{29F15AA2-793A-43C6-B33B-D32F76EE30DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{29F15AA2-793A-43C6-B33B-D32F76EE30DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{29F15AA2-793A-43C6-B33B-D32F76EE30DC}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C9BAC62F-2D93-42E0-9570-F6FC08EBCAB7}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version = "1.0" encoding = "UTF-8" ?>
|
||||
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:local="clr-namespace:TechTitans"
|
||||
x:Class="TechTitans.App">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
|
||||
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace TechTitans
|
||||
{
|
||||
public partial class App : Application
|
||||
{
|
||||
public App()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
MainPage = new AppShell();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<Shell
|
||||
x:Class="TechTitans.AppShell"
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:local="clr-namespace:TechTitans"
|
||||
Shell.FlyoutBehavior="Disabled"
|
||||
Title="TechTitans">
|
||||
|
||||
<ShellContent
|
||||
Title="Home"
|
||||
ContentTemplate="{DataTemplate local:Views.MainPage}"
|
||||
Route="MainPage" />
|
||||
|
||||
</Shell>
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace TechTitans
|
||||
{
|
||||
public partial class AppShell : Shell
|
||||
{
|
||||
public AppShell()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace TechTitans.Enums
|
||||
{
|
||||
/// <summary>
|
||||
/// 1. Has listened to a lot of songs
|
||||
/// 2. Has listened to a lot of new genres
|
||||
/// 3. Has not listened to very few songs
|
||||
/// 4. None of the above
|
||||
/// </summary>
|
||||
public enum ListenerPersonality
|
||||
{
|
||||
Melophile,
|
||||
Explorer,
|
||||
Casual,
|
||||
Vanilla,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace TechTitans.Enums
|
||||
{
|
||||
public enum PlaybackEventType
|
||||
{
|
||||
like = 1,
|
||||
start_play = 2,
|
||||
end_play = 3,
|
||||
dislike = 4,
|
||||
skip = 5
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using TechTitans.Repositories;
|
||||
using System.Reflection;
|
||||
using CommunityToolkit.Maui;
|
||||
|
||||
namespace TechTitans
|
||||
{
|
||||
public static class MauiProgram
|
||||
{
|
||||
public static IConfiguration Configuration { get; private set; }
|
||||
public static MauiApp CreateMauiApp()
|
||||
{
|
||||
var builder = MauiApp.CreateBuilder();
|
||||
builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
|
||||
builder
|
||||
.UseMauiApp<App>()
|
||||
.UseMauiCommunityToolkit()
|
||||
.ConfigureFonts(fonts =>
|
||||
{
|
||||
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
|
||||
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
|
||||
});
|
||||
|
||||
#if DEBUG
|
||||
builder.Logging.AddDebug();
|
||||
#endif
|
||||
using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("TechTitans.appsettings.json");
|
||||
builder.Configuration.AddJsonStream(stream).Build();
|
||||
var app = builder.Build();
|
||||
Configuration = app.Services.GetService<IConfiguration>();
|
||||
return app;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TechTitans.Models
|
||||
{
|
||||
[Table("AdDistributionData")]
|
||||
public class AdDistributionData
|
||||
{
|
||||
[Key]
|
||||
[Column("song_id")]
|
||||
public int Song_Id { get; set; }
|
||||
|
||||
[Key]
|
||||
[Column("ad_campaign")]
|
||||
public int Ad_Campaign { get; set; }
|
||||
|
||||
[Column("genre")]
|
||||
public string Genre { get; set; }
|
||||
|
||||
[Column("language")]
|
||||
public string Language { get; set; }
|
||||
|
||||
[Column("month")]
|
||||
public int Month { get; set; }
|
||||
|
||||
[Column("year")]
|
||||
public int Year { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TechTitans.Models
|
||||
{
|
||||
[Table("AuthorDetails")]
|
||||
public class AuthorDetails
|
||||
{
|
||||
[Key]
|
||||
[Column("artist_id")]
|
||||
public int Artist_Id { get; set; } = 0;
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; set; } = "DefaultName";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace TechTitans.Models
|
||||
{
|
||||
public class FullDetailsOnSong {
|
||||
public int TotalMinutesListened { get; set; }
|
||||
public int TotalPlays { get; set; }
|
||||
public int TotalLikes { get; set; }
|
||||
public int TotalDislikes { get; set; }
|
||||
public int TotalSkips { get; set; }
|
||||
public FullDetailsOnSong() {
|
||||
TotalMinutesListened = 0;
|
||||
TotalPlays = 0;
|
||||
TotalLikes = 0;
|
||||
TotalDislikes = 0;
|
||||
TotalSkips = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TechTitans.Models
|
||||
{
|
||||
internal class MostPlayedArtistInfo
|
||||
{
|
||||
[Column("artist_id")]
|
||||
public int Artist_Id { get; set; }
|
||||
|
||||
[Column("start_listen_events")]
|
||||
public int Start_Listen_Events { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TechTitans.Models
|
||||
{
|
||||
[Table ("SongBasicDetails")]
|
||||
public class SongBasicDetails
|
||||
{
|
||||
[Key]
|
||||
[Column("song_id")]
|
||||
public int Song_Id { get; set; } = 0;
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; set; } = "DefaultName";
|
||||
|
||||
[Column("genre")]
|
||||
public string Genre { get; set; } = "DefaultGenre";
|
||||
|
||||
[Column("subgenre")]
|
||||
public string Subgenre { get; set; } = "DefaultSubgenre";
|
||||
|
||||
[Column("artist_id")]
|
||||
public int Artist_Id { get; set; } = 0;
|
||||
|
||||
[Column("language")]
|
||||
public string Language { get; set; } = "DefaultLanguage";
|
||||
|
||||
[Column("country")]
|
||||
public string Country { get; set; } = "DefaultCountry";
|
||||
|
||||
[Column("album")]
|
||||
public string Album { get; set; } = "DefaultAlbum";
|
||||
|
||||
[Column("image")]
|
||||
public string Image { get; set; } = "song_img_default.png";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
namespace TechTitans.Models
|
||||
{
|
||||
public class SongBasicInfo
|
||||
{
|
||||
public int SongId { get; set; } = 0;
|
||||
public string Name { get; set; } = "DefaultName";
|
||||
public string Genre { get; set; } = "DefaultGenre";
|
||||
public string Subgenre { get; set; } = "DefaultSubgenre";
|
||||
public string Artist { get; set; } = "DefaultArtist";
|
||||
public IList<string> Features { get; set; } = new List<string>();
|
||||
public string Language { get; set; } = "DefaultLanguage";
|
||||
public string Country { get; set; } = "DefaultCountry";
|
||||
public string Album { get; set; } = "DefaultAlbum";
|
||||
public string Image { get; set; } = "song_img_default.png";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TechTitans.Models
|
||||
{
|
||||
[Table("SongFeatures")]
|
||||
public class SongFeatures
|
||||
{
|
||||
[Key]
|
||||
[Column("song_id")]
|
||||
public int Song_Id { get; set; }
|
||||
[Key]
|
||||
[Column("artist_id")]
|
||||
public int Artist_Id { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TechTitans.Models
|
||||
{
|
||||
[Table("SongRecommendationDetails")]
|
||||
public class SongRecommendationDetails
|
||||
{
|
||||
[Key]
|
||||
[Column("song_id")]
|
||||
public int Song_Id { get; set; } = 0;
|
||||
|
||||
[Column("likes")]
|
||||
public int Likes { get; set; } = 0;
|
||||
|
||||
[Column("dislikes")]
|
||||
public int Dislikes { get; set; } = 0;
|
||||
|
||||
[Column("minutes_listened")]
|
||||
public int Minutes_Listened { get; set; } = 0;
|
||||
|
||||
[Column("number_of_plays")]
|
||||
public int Number_Of_Plays { get; set; } = 0;
|
||||
|
||||
[Key]
|
||||
[Column("month")]
|
||||
public int Month { get; set; } = 0;
|
||||
|
||||
[Key]
|
||||
[Column("year")]
|
||||
public int Year { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TechTitans.Models
|
||||
{
|
||||
[Table("Test")]
|
||||
public class Test
|
||||
{
|
||||
[Key]
|
||||
[Column("Id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("Name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TechTitans.Models
|
||||
{
|
||||
[Table("Trends")]
|
||||
public class Trends
|
||||
{
|
||||
[Key]
|
||||
[Column("genre")]
|
||||
public string Genre { get; set; }
|
||||
|
||||
[Key]
|
||||
[Column("language")]
|
||||
public string Language { get; set; }
|
||||
|
||||
[Key]
|
||||
[Column("country")]
|
||||
public string Country { get; set; }
|
||||
|
||||
[Key]
|
||||
[Column("song_id")]
|
||||
public int Song_Id { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TechTitans.Models
|
||||
{
|
||||
[Table("UserDemographicsDetails")]
|
||||
public class UserDemographicsDetails
|
||||
{
|
||||
[Key]
|
||||
[Column("user_id")]
|
||||
public int User_Id { get; set; }
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Column("gender")]
|
||||
public int Gender { get; set; }
|
||||
|
||||
[Column("date_of_birth")]
|
||||
public DateTime Date_Of_fBirth { get; set; }
|
||||
|
||||
[Column("country")]
|
||||
public string Country { get; set; }
|
||||
|
||||
[Column("language")]
|
||||
public string Language { get; set; }
|
||||
|
||||
[Column("race")]
|
||||
public string Race { get; set; }
|
||||
|
||||
[Column("premium_user")]
|
||||
public bool Premium_User { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TechTitans.Enums;
|
||||
|
||||
namespace TechTitans.Models
|
||||
{
|
||||
[Table("UserPlaybackBehaviour")]
|
||||
public class UserPlaybackBehaviour
|
||||
{
|
||||
[Key]
|
||||
[Column("user_id")]
|
||||
public int User_Id { get; set; }
|
||||
|
||||
[Key]
|
||||
[Column("song_id")]
|
||||
public int Song_Id { get; set; }
|
||||
|
||||
[Column("event_type")]
|
||||
public PlaybackEventType Event_Type { get; set; }
|
||||
|
||||
[Key]
|
||||
[Column("timestamp")]
|
||||
public DateTime Timestamp { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
||||
@@ -0,0 +1,11 @@
|
||||
using Android.App;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
|
||||
namespace TechTitans
|
||||
{
|
||||
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
|
||||
public class MainActivity : MauiAppCompatActivity
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Android.App;
|
||||
using Android.Runtime;
|
||||
|
||||
namespace TechTitans
|
||||
{
|
||||
[Application]
|
||||
public class MainApplication : MauiApplication
|
||||
{
|
||||
public MainApplication(IntPtr handle, JniHandleOwnership ownership)
|
||||
: base(handle, ownership)
|
||||
{
|
||||
}
|
||||
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#512BD4</color>
|
||||
<color name="colorPrimaryDark">#2B0B98</color>
|
||||
<color name="colorAccent">#2B0B98</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,10 @@
|
||||
using Foundation;
|
||||
|
||||
namespace TechTitans
|
||||
{
|
||||
[Register("AppDelegate")]
|
||||
public class AppDelegate : MauiUIApplicationDelegate
|
||||
{
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<!-- See https://aka.ms/maui-publish-app-store#add-entitlements for more information about adding entitlements.-->
|
||||
<dict>
|
||||
<!-- App Sandbox must be enabled to distribute a MacCatalyst app through the Mac App Store. -->
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<!-- When App Sandbox is enabled, this value is required to open outgoing network connections. -->
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!-- The Mac App Store requires you specify if the app uses encryption. -->
|
||||
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/itsappusesnonexemptencryption -->
|
||||
<!-- <key>ITSAppUsesNonExemptEncryption</key> -->
|
||||
<!-- Please indicate <true/> or <false/> here. -->
|
||||
|
||||
<!-- Specify the category for your app here. -->
|
||||
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype -->
|
||||
<!-- <key>LSApplicationCategoryType</key> -->
|
||||
<!-- <string>public.app-category.YOUR-CATEGORY-HERE</string> -->
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/appicon.appiconset</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,16 @@
|
||||
using ObjCRuntime;
|
||||
using UIKit;
|
||||
|
||||
namespace TechTitans
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
// This is the main entry point of the application.
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||
// you can specify it here.
|
||||
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Microsoft.Maui;
|
||||
using Microsoft.Maui.Hosting;
|
||||
using System;
|
||||
|
||||
namespace TechTitans
|
||||
{
|
||||
internal class Program : MauiApplication
|
||||
{
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var app = new Program();
|
||||
app.Run(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="maui-application-id-placeholder" version="0.0.0" api-version="8" xmlns="http://tizen.org/ns/packages">
|
||||
<profile name="common" />
|
||||
<ui-application appid="maui-application-id-placeholder" exec="TechTitans.dll" multiple="false" nodisplay="false" taskmanage="true" type="dotnet" launch_mode="single">
|
||||
<label>maui-application-title-placeholder</label>
|
||||
<icon>maui-appicon-placeholder</icon>
|
||||
<metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
|
||||
</ui-application>
|
||||
<shortcut-list />
|
||||
<privileges>
|
||||
<privilege>http://tizen.org/privilege/internet</privilege>
|
||||
</privileges>
|
||||
<dependencies />
|
||||
<provides-appdefined-privileges />
|
||||
</manifest>
|
||||
@@ -0,0 +1,8 @@
|
||||
<maui:MauiWinUIApplication
|
||||
x:Class="TechTitans.WinUI.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:maui="using:Microsoft.Maui"
|
||||
xmlns:local="using:TechTitans.WinUI">
|
||||
|
||||
</maui:MauiWinUIApplication>
|
||||
@@ -0,0 +1,25 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace TechTitans.WinUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides application-specific behavior to supplement the default Application class.
|
||||
/// </summary>
|
||||
public partial class App : MauiWinUIApplication
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the singleton application object. This is the first line of authored code
|
||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||
/// </summary>
|
||||
public App()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
IgnorableNamespaces="uap rescap">
|
||||
|
||||
<Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="FAC290BF-77C6-481F-91A5-8737B04E06C7" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
<Properties>
|
||||
<DisplayName>$placeholder$</DisplayName>
|
||||
<PublisherDisplayName>User Name</PublisherDisplayName>
|
||||
<Logo>$placeholder$.png</Logo>
|
||||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
|
||||
<uap:VisualElements
|
||||
DisplayName="$placeholder$"
|
||||
Description="$placeholder$"
|
||||
Square150x150Logo="$placeholder$.png"
|
||||
Square44x44Logo="$placeholder$.png"
|
||||
BackgroundColor="transparent">
|
||||
<uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" />
|
||||
<uap:SplashScreen Image="$placeholder$.png" />
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
<Capabilities>
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
</Capabilities>
|
||||
|
||||
</Package>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="TechTitans.WinUI.app"/>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<!-- The combination of below two tags have the following effect:
|
||||
1) Per-Monitor for >= Windows 10 Anniversary Update
|
||||
2) System < Windows 10 Anniversary Update
|
||||
-->
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
@@ -0,0 +1,10 @@
|
||||
using Foundation;
|
||||
|
||||
namespace TechTitans
|
||||
{
|
||||
[Register("AppDelegate")]
|
||||
public class AppDelegate : MauiUIApplicationDelegate
|
||||
{
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/appicon.appiconset</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,16 @@
|
||||
using ObjCRuntime;
|
||||
using UIKit;
|
||||
|
||||
namespace TechTitans
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
// This is the main entry point of the application.
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||
// you can specify it here.
|
||||
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Windows Machine": {
|
||||
"commandName": "MsixPackage",
|
||||
"nativeDebugging": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TechTitans.Repositories
|
||||
{
|
||||
public interface IRepository<T>
|
||||
{
|
||||
T GetById(int id);
|
||||
IEnumerable<T> GetAll();
|
||||
bool Add(T entity);
|
||||
bool Update(T entity);
|
||||
bool Delete(T entity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Dapper;
|
||||
using static Dapper.SqlMapper;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace TechTitans.Repositories
|
||||
{
|
||||
public class Repository<T> : IRepository<T> where T : class
|
||||
{
|
||||
public IDbConnection _connection;
|
||||
private readonly IConfiguration _configuration = MauiProgram.Configuration;
|
||||
|
||||
public Repository()
|
||||
{
|
||||
|
||||
_connection = new Microsoft.Data.SqlClient.SqlConnection(_configuration.GetConnectionString("TechTitansDev"));
|
||||
}
|
||||
|
||||
public bool Add(T entity)
|
||||
{
|
||||
int rowsEffected = 0;
|
||||
try
|
||||
{
|
||||
string tableName = GetTableName();
|
||||
string columns = GetColumns(excludeKey: true);
|
||||
string properties = GetPropertyNames(excludeKey: true);
|
||||
string query = $"INSERT INTO {tableName} ({columns}) VALUES ({properties})";
|
||||
|
||||
rowsEffected = _connection.Execute(query, entity);
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
|
||||
return rowsEffected > 0 ? true : false;
|
||||
}
|
||||
|
||||
public bool Delete(T entity)
|
||||
{
|
||||
int rowsEffected = 0;
|
||||
try
|
||||
{
|
||||
string tableName = GetTableName();
|
||||
string keyColumn = GetKeyColumnName();
|
||||
string keyProperty = GetKeyPropertyName();
|
||||
string query = $"DELETE FROM {tableName} WHERE {keyColumn} = @{keyProperty}";
|
||||
|
||||
rowsEffected = _connection.Execute(query, entity);
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
|
||||
return rowsEffected > 0 ? true : false;
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetAll()
|
||||
{
|
||||
IEnumerable<T> result = null;
|
||||
try
|
||||
{
|
||||
string tableName = GetTableName();
|
||||
string query = $"SELECT * FROM {tableName}";
|
||||
|
||||
result = _connection.Query<T>(query);
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public T GetById(int Id)
|
||||
{
|
||||
IEnumerable<T> result = null;
|
||||
try
|
||||
{
|
||||
string tableName = GetTableName();
|
||||
string keyColumn = GetKeyColumnName();
|
||||
string query = $"SELECT * FROM {tableName} WHERE {keyColumn} = '{Id}'";
|
||||
|
||||
result = _connection.Query<T>(query);
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
|
||||
return result.FirstOrDefault();
|
||||
}
|
||||
|
||||
public bool Update(T entity)
|
||||
{
|
||||
int rowsEffected = 0;
|
||||
try
|
||||
{
|
||||
string tableName = GetTableName();
|
||||
string keyColumn = GetKeyColumnName();
|
||||
string keyProperty = GetKeyPropertyName();
|
||||
|
||||
StringBuilder query = new StringBuilder();
|
||||
query.Append($"UPDATE {tableName} SET ");
|
||||
|
||||
foreach (var property in GetProperties(true))
|
||||
{
|
||||
var columnAttr = property.GetCustomAttribute<ColumnAttribute>();
|
||||
|
||||
string propertyName = property.Name;
|
||||
string columnName = columnAttr.Name;
|
||||
|
||||
query.Append($"{columnName} = @{propertyName},");
|
||||
}
|
||||
|
||||
query.Remove(query.Length - 1, 1);
|
||||
|
||||
query.Append($" WHERE {keyColumn} = @{keyProperty}");
|
||||
|
||||
rowsEffected = _connection.Execute(query.ToString(), entity);
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
|
||||
return rowsEffected > 0 ? true : false;
|
||||
}
|
||||
|
||||
private string GetTableName()
|
||||
{
|
||||
string tableName = "";
|
||||
var type = typeof(T);
|
||||
var tableAttr = type.GetCustomAttribute<TableAttribute>();
|
||||
if (tableAttr != null)
|
||||
{
|
||||
tableName = tableAttr.Name;
|
||||
return tableName;
|
||||
}
|
||||
|
||||
return type.Name + "s";
|
||||
}
|
||||
|
||||
public static string GetKeyColumnName()
|
||||
{
|
||||
PropertyInfo[] properties = typeof(T).GetProperties();
|
||||
|
||||
foreach (PropertyInfo property in properties)
|
||||
{
|
||||
object[] keyAttributes = property.GetCustomAttributes(typeof(KeyAttribute), true);
|
||||
|
||||
if (keyAttributes != null && keyAttributes.Length > 0)
|
||||
{
|
||||
object[] columnAttributes = property.GetCustomAttributes(typeof(ColumnAttribute), true);
|
||||
|
||||
if (columnAttributes != null && columnAttributes.Length > 0)
|
||||
{
|
||||
ColumnAttribute columnAttribute = (ColumnAttribute)columnAttributes[0];
|
||||
return columnAttribute.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return property.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private string GetColumns(bool excludeKey = false)
|
||||
{
|
||||
var type = typeof(T);
|
||||
var columns = string.Join(", ", type.GetProperties()
|
||||
.Where(p => !excludeKey || !p.IsDefined(typeof(KeyAttribute)))
|
||||
.Select(p =>
|
||||
{
|
||||
var columnAttr = p.GetCustomAttribute<ColumnAttribute>();
|
||||
return columnAttr != null ? columnAttr.Name : p.Name;
|
||||
}));
|
||||
|
||||
return columns;
|
||||
}
|
||||
|
||||
protected string GetPropertyNames(bool excludeKey = false)
|
||||
{
|
||||
var properties = typeof(T).GetProperties()
|
||||
.Where(p => !excludeKey || p.GetCustomAttribute<KeyAttribute>() == null);
|
||||
|
||||
var values = string.Join(", ", properties.Select(p =>
|
||||
{
|
||||
return $"@{p.Name}";
|
||||
}));
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
protected IEnumerable<PropertyInfo> GetProperties(bool excludeKey = false)
|
||||
{
|
||||
var properties = typeof(T).GetProperties()
|
||||
.Where(p => !excludeKey || p.GetCustomAttribute<KeyAttribute>() == null);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
protected string GetKeyPropertyName()
|
||||
{
|
||||
var properties = typeof(T).GetProperties()
|
||||
.Where(p => p.GetCustomAttribute<KeyAttribute>() != null);
|
||||
|
||||
if (properties.Any())
|
||||
{
|
||||
return properties.FirstOrDefault().Name;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using Dapper;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TechTitans.Models;
|
||||
|
||||
namespace TechTitans.Repositories
|
||||
{
|
||||
internal class SongBasicDetailsRepository : Repository<SongBasicDetails>
|
||||
{
|
||||
public SongBasicInfo SongBasicDetailsToSongBasicInfo(SongBasicDetails songBasicDetails)
|
||||
{
|
||||
var artistId = songBasicDetails.Artist_Id;
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT name FROM AuthorDetails WHERE artist_id = @artistId");
|
||||
var artistName = _connection.Query<string>(cmd.ToString(), new { artistId }).FirstOrDefault();
|
||||
return new SongBasicInfo
|
||||
{
|
||||
SongId = songBasicDetails.Song_Id,
|
||||
Name = songBasicDetails.Name,
|
||||
Genre = songBasicDetails.Genre,
|
||||
Subgenre = songBasicDetails.Subgenre,
|
||||
Artist = artistName,
|
||||
Language = songBasicDetails.Language,
|
||||
Country = songBasicDetails.Country,
|
||||
Album = songBasicDetails.Album,
|
||||
Image = songBasicDetails.Image
|
||||
};
|
||||
}
|
||||
|
||||
public SongBasicDetails GetSongBasicDetails(int songId)
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM SongBasicDetails WHERE song_id = @songId");
|
||||
return _connection.Query<SongBasicDetails>(cmd.ToString(), new { songId }).FirstOrDefault();
|
||||
}
|
||||
|
||||
public List<SongBasicDetails> GetTop5MostListenedSongs(int userId)
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM SongBasicDetails WHERE song_id IN (SELECT TOP 5 song_id FROM UserPlaybackBehaviour WHERE user_id = @userId AND event_type = 2 GROUP BY song_id ORDER BY COUNT(song_id) DESC);");
|
||||
return _connection.Query<SongBasicDetails>(cmd.ToString(), new { userId }).ToList();
|
||||
}
|
||||
|
||||
public Tuple<SongBasicDetails, decimal> GetMostPlayedSongPercentile(int userId)
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM SongBasicDetails WHERE song_id IN (SELECT TOP 1 song_id FROM UserPlaybackBehaviour WHERE user_id = @userId AND event_type = 2 AND YEAR(timestamp) = YEAR(GETDATE()) GROUP BY song_id ORDER BY COUNT(song_id) DESC);");
|
||||
var mostPlayedSong = _connection.Query<SongBasicDetails>(cmd.ToString(), new { userId }).FirstOrDefault();
|
||||
cmd.Clear();
|
||||
cmd.Append("SELECT COUNT(*) FROM UserPlaybackBehaviour WHERE user_id = @userId AND event_type = 2 AND YEAR(timestamp) = YEAR(GETDATE());");
|
||||
var totalSongs = _connection.Query<int>(cmd.ToString(), new { userId }).FirstOrDefault();
|
||||
cmd.Clear();
|
||||
cmd.Append("SELECT COUNT(*) FROM UserPlaybackBehaviour WHERE user_id = @userId AND event_type = 2 AND YEAR(timestamp) = YEAR(GETDATE()) AND song_id IN (SELECT TOP 1 song_id FROM UserPlaybackBehaviour WHERE user_id = @userId AND event_type = 2 AND YEAR(timestamp) = YEAR(GETDATE()) GROUP BY song_id ORDER BY COUNT(song_id) DESC);");
|
||||
var mostListenedSongCount = _connection.Query<int>(cmd.ToString(), new { userId }).FirstOrDefault();
|
||||
return new Tuple<SongBasicDetails, decimal>(mostPlayedSong, (decimal)mostListenedSongCount / totalSongs);
|
||||
}
|
||||
|
||||
public Tuple<string, decimal> GetMostPlayedArtistPercentile(int userId)
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT TOP 1 sd.artist_id as Artist_Id, COUNT(*) AS Start_Listen_Events FROM UserPlaybackBehaviour ub JOIN SongBasicDetails sd ON ub.song_id = sd.song_id WHERE ub.user_id = @userId AND ub.event_type = 2 AND YEAR(timestamp) = YEAR(GETDATE()) GROUP BY sd.artist_id ORDER BY COUNT(*) DESC;");
|
||||
var response = _connection.Query<MostPlayedArtistInfo>(cmd.ToString(), new { userId }).FirstOrDefault();
|
||||
cmd.Clear();
|
||||
cmd.Append("SELECT name FROM AuthorDetails WHERE artist_id = @artist_Id");
|
||||
var mostPlayedArtist = _connection.Query<string>(cmd.ToString(), new { response.Artist_Id }).FirstOrDefault();
|
||||
cmd.Clear();
|
||||
cmd.Append("SELECT COUNT(*) FROM UserPlaybackBehaviour WHERE user_id = @userId AND event_type = 2 AND YEAR(timestamp) = YEAR(GETDATE());");
|
||||
var totalSongs = _connection.Query<int>(cmd.ToString(), new { userId }).FirstOrDefault();
|
||||
cmd.Clear();
|
||||
return new Tuple<string, decimal>(mostPlayedArtist, (decimal)response.Start_Listen_Events / totalSongs);
|
||||
}
|
||||
|
||||
public List<string> GetTop5Genres(int userId)
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT TOP 5 sb.genre FROM UserPlaybackBehaviour ub JOIN SongBasicDetails sb ON ub.song_id = sb.song_id WHERE ub.user_id = @userId AND ub.event_type = 2 AND YEAR(ub.timestamp) = YEAR(GETDATE()) GROUP BY sb.genre ORDER BY COUNT(*) DESC;");
|
||||
return _connection.Query<string>(cmd.ToString(), new { userId }).ToList();
|
||||
}
|
||||
|
||||
public List<string> NewGenresDiscovered(int userId)
|
||||
{
|
||||
//new genres where first song was played for the first time in the current year
|
||||
//var cmd = new StringBuilder();
|
||||
//cmd.Append("SELECT genre FROM SongBasicDetails WHERE song_id IN (SELECT song_id FROM UserPlaybackBehaviour WHERE user_id = @userId AND event_type = 1 AND YEAR(timestamp) = YEAR(GETDATE()) GROUP BY song_id HAVING COUNT(song_id) = 1);");
|
||||
|
||||
//select all genres that have been played in current year but not in previous year
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT DISTINCT genre FROM SongBasicDetails WHERE song_id IN (SELECT song_id FROM UserPlaybackBehaviour WHERE user_id = @userId AND event_type = 2 AND YEAR(timestamp) = YEAR(GETDATE()) GROUP BY song_id) AND genre NOT IN (SELECT genre FROM SongBasicDetails WHERE song_id IN (SELECT song_id FROM UserPlaybackBehaviour WHERE user_id = @userId AND event_type = 2 AND YEAR(timestamp) = YEAR(GETDATE()) - 1 GROUP BY song_id));");
|
||||
return _connection.Query<string>(cmd.ToString(), new { userId }).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using Dapper;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TechTitans.Models;
|
||||
|
||||
namespace TechTitans.Repositories
|
||||
{
|
||||
public class TestRepository : Repository<Test>
|
||||
{
|
||||
public Test TestMethod()
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM Test");
|
||||
return _connection.Query<Test>(cmd.ToString()).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
public class TestDemographicDetails : Repository<UserDemographicsDetails>
|
||||
{
|
||||
public UserDemographicsDetails TestMethod()
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM UserDemographicsDetails");
|
||||
return _connection.Query<UserDemographicsDetails>(cmd.ToString()).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
public class TestAuthorDetails : Repository<AuthorDetails>
|
||||
{
|
||||
public AuthorDetails TestMethod()
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM AuthorDetails");
|
||||
// return _connection.Query<Test>(cmd.ToString()).FirstOrDefault();
|
||||
return _connection.Query<AuthorDetails>(cmd.ToString()).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
public class TestAdDistributionData : Repository<AdDistributionData>
|
||||
{
|
||||
public AdDistributionData TestMethod()
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM AdDistributionData");
|
||||
return _connection.Query<AdDistributionData>(cmd.ToString()).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
public class TestSongBasicDetails : Repository<SongBasicDetails>
|
||||
{
|
||||
public SongBasicDetails TestMethod()
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM SongBasicDetails");
|
||||
return _connection.Query<SongBasicDetails>(cmd.ToString()).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
public class TestUserPlaybackBehaviour : Repository<UserPlaybackBehaviour>
|
||||
{
|
||||
public UserPlaybackBehaviour TestMethod()
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM UserPlaybackBehaviour");
|
||||
return _connection.Query<UserPlaybackBehaviour>(cmd.ToString()).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
public class TestSongRecommendationDetails : Repository<SongRecommendationDetails>
|
||||
{
|
||||
public SongRecommendationDetails TestMethod()
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM SongRecommendationDetails");
|
||||
return _connection.Query<SongRecommendationDetails>(cmd.ToString()).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
public class TestSongFeatures : Repository<SongFeatures>
|
||||
{
|
||||
public SongFeatures TestMethod()
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM SongFeatures");
|
||||
return _connection.Query<SongFeatures>(cmd.ToString()).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
public class TestTrends : Repository<Trends>
|
||||
{
|
||||
public Trends TestMethod()
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM Trends");
|
||||
return _connection.Query<Trends>(cmd.ToString()).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Dapper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TechTitans.Models;
|
||||
|
||||
namespace TechTitans.Repositories
|
||||
{
|
||||
internal class UserPlaybackBehaviourRepository : Repository<UserPlaybackBehaviour>
|
||||
{
|
||||
public UserPlaybackBehaviour GetUserPlaybackBehaviour(int userId, int songId, DateTime timestamp)
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM UserPlaybackBehaviour WHERE user_id = @userId AND song_id = @songId AND timestamp = @timestamp");
|
||||
return _connection.Query<UserPlaybackBehaviour>(cmd.ToString(), new { userId, songId, timestamp }).FirstOrDefault();
|
||||
}
|
||||
|
||||
public List<UserPlaybackBehaviour> GetUserPlaybackBehaviour(int userId, int songId)
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT * FROM UserPlaybackBehaviour WHERE user_id = @userId AND song_id = @songId");
|
||||
return _connection.Query<UserPlaybackBehaviour>(cmd.ToString(), new { userId, songId }).ToList();
|
||||
}
|
||||
|
||||
public List<UserPlaybackBehaviour> GetUserPlaybackBehaviour(int userId)
|
||||
{
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT user_id as User_Id, song_id as Song_Id, event_type as Event_Type, timestamp as Timestamp FROM UserPlaybackBehaviour WHERE user_id = @userId");
|
||||
return _connection.Query<UserPlaybackBehaviour>(cmd.ToString(), new { userId }).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TechTitans.Repositories;
|
||||
using TechTitans.Models;
|
||||
using Dapper;
|
||||
|
||||
namespace TechTitans.Repositories
|
||||
{
|
||||
internal class UserRepository : Repository<SongBasicDetails>
|
||||
{
|
||||
public SongBasicInfo SongBasicDetailsToSongBasicInfo(SongBasicDetails songBasicDetails)
|
||||
{
|
||||
var artistId = songBasicDetails.Artist_Id;
|
||||
var cmd = new StringBuilder();
|
||||
cmd.Append("SELECT name FROM AuthorDetails WHERE artist_id = @artistId");
|
||||
var artistName = _connection.Query<string>(cmd.ToString(), new { artistId }).FirstOrDefault();
|
||||
return new SongBasicInfo
|
||||
{
|
||||
SongId = songBasicDetails.Song_Id,
|
||||
Name = songBasicDetails.Name,
|
||||
Genre = songBasicDetails.Genre,
|
||||
Subgenre = songBasicDetails.Subgenre,
|
||||
Artist = artistName,
|
||||
Language = songBasicDetails.Language,
|
||||
Country = songBasicDetails.Country,
|
||||
Album = songBasicDetails.Album,
|
||||
Image = songBasicDetails.Image
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="456" height="456" fill="#512BD4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 228 B |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 643 KiB |
|
After Width: | Height: | Size: 935 KiB |
|
After Width: | Height: | Size: 396 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="7.5 7.5 50 62.5" enable-background="new 7.5 7.5 50 50" xml:space="preserve"><path fill="#AA0000" d="M32.5,20.083c-13.418,0-24.334,10.916-24.334,24.334c0,0.276,0.224,0.5,0.5,0.5h47.668c0.276,0,0.5-0.224,0.5-0.5 C56.834,30.999,45.918,20.083,32.5,20.083z"/></svg>
|
||||
|
After Width: | Height: | Size: 383 B |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,15 @@
|
||||
Any raw assets you want to be deployed with your application can be placed in
|
||||
this directory (and child directories). Deployment of the asset to your application
|
||||
is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
|
||||
|
||||
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||
|
||||
These files will be deployed with you package and will be accessible using Essentials:
|
||||
|
||||
async Task LoadMauiAsset()
|
||||
{
|
||||
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
|
||||
using var reader = new StreamReader(stream);
|
||||
|
||||
var contents = reader.ReadToEnd();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xaml-comp compile="true" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||
|
||||
<!-- Note: For Android please see also Platforms\Android\Resources\values\colors.xml -->
|
||||
|
||||
<Color x:Key="Primary">#512BD4</Color>
|
||||
<Color x:Key="PrimaryDark">#ac99ea</Color>
|
||||
<Color x:Key="PrimaryDarkText">#242424</Color>
|
||||
<Color x:Key="Secondary">#DFD8F7</Color>
|
||||
<Color x:Key="SecondaryDarkText">#9880e5</Color>
|
||||
<Color x:Key="Tertiary">#2B0B98</Color>
|
||||
|
||||
<Color x:Key="White">White</Color>
|
||||
<Color x:Key="Black">Black</Color>
|
||||
<Color x:Key="Magenta">#D600AA</Color>
|
||||
<Color x:Key="MidnightBlue">#190649</Color>
|
||||
<Color x:Key="OffBlack">#1f1f1f</Color>
|
||||
|
||||
<Color x:Key="Gray100">#E1E1E1</Color>
|
||||
<Color x:Key="Gray200">#C8C8C8</Color>
|
||||
<Color x:Key="Gray300">#ACACAC</Color>
|
||||
<Color x:Key="Gray400">#919191</Color>
|
||||
<Color x:Key="Gray500">#6E6E6E</Color>
|
||||
<Color x:Key="Gray600">#404040</Color>
|
||||
<Color x:Key="Gray900">#212121</Color>
|
||||
<Color x:Key="Gray950">#141414</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/>
|
||||
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/>
|
||||
<SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/>
|
||||
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/>
|
||||
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/>
|
||||
|
||||
<SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/>
|
||||
<SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/>
|
||||
<SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/>
|
||||
<SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/>
|
||||
<SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/>
|
||||
<SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/>
|
||||
<SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/>
|
||||
<SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/>
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,453 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xaml-comp compile="true" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||
|
||||
<Style TargetType="ActivityIndicator">
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="IndicatorView">
|
||||
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/>
|
||||
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="StrokeShape" Value="Rectangle"/>
|
||||
<Setter Property="StrokeThickness" Value="1"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="BoxView">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource PrimaryDarkText}}" />
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}}" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="BorderWidth" Value="0"/>
|
||||
<Setter Property="CornerRadius" Value="8"/>
|
||||
<Setter Property="Padding" Value="14,10"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PointerOver" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="CheckBox">
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="DatePicker">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Editor">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Entry">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Frame">
|
||||
<Setter Property="HasShadow" Value="False" />
|
||||
<Setter Property="BorderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ImageButton">
|
||||
<Setter Property="Opacity" Value="1" />
|
||||
<Setter Property="BorderColor" Value="Transparent"/>
|
||||
<Setter Property="BorderWidth" Value="0"/>
|
||||
<Setter Property="CornerRadius" Value="0"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PointerOver" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Label">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Span">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Label" x:Key="Headline">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" />
|
||||
<Setter Property="FontSize" Value="32" />
|
||||
<Setter Property="HorizontalOptions" Value="Center" />
|
||||
<Setter Property="HorizontalTextAlignment" Value="Center" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Label" x:Key="SubHeadline">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" />
|
||||
<Setter Property="FontSize" Value="24" />
|
||||
<Setter Property="HorizontalOptions" Value="Center" />
|
||||
<Setter Property="HorizontalTextAlignment" Value="Center" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ListView">
|
||||
<Setter Property="SeparatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="RefreshControlColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Picker">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ProgressBar">
|
||||
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="RadioButton">
|
||||
<Setter Property="BackgroundColor" Value="Transparent"/>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="RefreshView">
|
||||
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="SearchBar">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
|
||||
<Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="SearchHandler">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Shadow">
|
||||
<Setter Property="Radius" Value="15" />
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Offset" Value="10,10" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Slider">
|
||||
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="SwipeItem">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Switch">
|
||||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="ThumbColor" Value="{StaticResource White}" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="On">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Off">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TimePicker">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent"/>
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Page" ApplyToDerivedTypes="True">
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Shell" ApplyToDerivedTypes="True">
|
||||
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||
<Setter Property="Shell.ForegroundColor" Value="{OnPlatform WinUI={StaticResource Primary}, Default={StaticResource White}}" />
|
||||
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" />
|
||||
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="Shell.NavBarHasShadow" Value="False" />
|
||||
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="NavigationPage">
|
||||
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
|
||||
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TabbedPage">
|
||||
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="TabNavButton" TargetType="Button">
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="TextColor" Value="White" />
|
||||
<Setter Property="FontSize" Value="18" />
|
||||
<Setter Property="CornerRadius" Value="3"/>
|
||||
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="ButtonStates">
|
||||
<VisualState x:Name="Pressed">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="BackgroundColor" Value="LightGray" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Normal">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,40 @@
|
||||
-- connect to the database SongBasicDetails
|
||||
insert into AuthorDetails values(1, 'Dumiyei')
|
||||
insert into AuthorDetails values(2, 'Dobu')
|
||||
insert into AuthorDetails values(3, 'Danilica')
|
||||
insert into AuthorDetails values(4, 'Iediy')
|
||||
insert into AuthorDetails values(5, 'Dyanana')
|
||||
insert into AuthorDetails values(6, 'Boghidy')
|
||||
insert into AuthorDetails values(7, 'MaineKraft boy')
|
||||
insert into AuthorDetails values(8, 'Tudie')
|
||||
|
||||
insert into UserDemographicsDetails values (1, 'Dumi', 'male', '2002-01-01', 'Romania', 'english', 'motherfucker', 1)
|
||||
insert into UserDemographicsDetails values (2, 'Andy', 'other', '2003-03-21', 'Nigeria', 'french', 'niggher', 0)
|
||||
|
||||
insert into SongBasicDetails VALUES
|
||||
(1, 'American Boy', 'hip-hop', 'chicago', 7, 'english', 'USA', '-', 'http://plm.com');
|
||||
|
||||
insert into Trends VALUES
|
||||
('hip-hop', 'english', 'USA', 1)
|
||||
|
||||
insert into AdDistributionData VALUES
|
||||
(1, 1, 'hip-hop', 'english', 10, 2023)
|
||||
|
||||
insert into UserPlaybackBehaviour VALUES
|
||||
(1, 1, 1, '2023-12-12 7:25:45')
|
||||
|
||||
insert into SongRecommendationDetails VALUES
|
||||
(1, 15, 4, 1503, 23, 10, 2023)
|
||||
|
||||
insert into SongFeatures values
|
||||
(1, 2)
|
||||
select * from UserPlaybackBehaviour
|
||||
|
||||
--UserDemographicsDetails
|
||||
--AuthorDetails
|
||||
--SongBasicDetails
|
||||
--Trends
|
||||
--AdDistributionData
|
||||
--UserPlaybackBehaviour
|
||||
--SongRecommendationDetails
|
||||
--SongFeatures
|
||||
@@ -0,0 +1,172 @@
|
||||
using TechTitans.Models;
|
||||
using TechTitans.Repositories;
|
||||
|
||||
namespace TechTitans.Services
|
||||
{
|
||||
public class ArtistSongDashboardController
|
||||
{
|
||||
private Repository<SongBasicDetails> SongRepo = new Repository<SongBasicDetails>();
|
||||
private Repository<SongFeatures> FeatureRepo = new Repository<SongFeatures>();
|
||||
private Repository<SongRecommendationDetails> SongRecommendationRepo = new Repository<SongRecommendationDetails>();
|
||||
private Repository<AuthorDetails> ArtistRepo = new Repository<AuthorDetails>();
|
||||
|
||||
|
||||
//converts song details to song info
|
||||
public SongBasicInfo songBasicDetailsToInfo(SongBasicDetails song)
|
||||
{
|
||||
SongBasicInfo songInfo = new SongBasicInfo();
|
||||
songInfo.SongId = song.Song_Id;
|
||||
songInfo.Name = song.Name;
|
||||
songInfo.Genre = song.Genre;
|
||||
songInfo.Subgenre = song.Subgenre;
|
||||
songInfo.Language = song.Language;
|
||||
songInfo.Country = song.Country;
|
||||
songInfo.Album = song.Album;
|
||||
songInfo.Image = song.Image;
|
||||
foreach (AuthorDetails artist in ArtistRepo.GetAll())
|
||||
{
|
||||
if (artist.Artist_Id == song.Artist_Id)
|
||||
{
|
||||
songInfo.Artist = artist.Name;
|
||||
}
|
||||
}
|
||||
foreach (SongFeatures feature in FeatureRepo.GetAll())
|
||||
{
|
||||
if (feature.Song_Id == song.Song_Id)
|
||||
{
|
||||
songInfo.Features.Add(feature.ToString());
|
||||
}
|
||||
}
|
||||
return songInfo;
|
||||
}
|
||||
|
||||
|
||||
//get all artist's publish song (returns List<Entity>)
|
||||
public List<SongBasicInfo> getAllArtistSongs(int artistId)
|
||||
{
|
||||
List<SongBasicInfo> artistSongs = new List<SongBasicInfo>();
|
||||
foreach (SongBasicDetails song in SongRepo.GetAll())
|
||||
{
|
||||
if (song.Artist_Id == artistId)
|
||||
{
|
||||
SongBasicInfo songInfo = songBasicDetailsToInfo(song);
|
||||
artistSongs.Add(songInfo);
|
||||
}
|
||||
}
|
||||
return artistSongs;
|
||||
}
|
||||
|
||||
//search by string in titles (returns list of songs, case insensitive)
|
||||
|
||||
public List<SongBasicInfo> searchByTitle(string title)
|
||||
{
|
||||
List<SongBasicInfo> songs = new List<SongBasicInfo>();
|
||||
foreach (SongBasicDetails song in SongRepo.GetAll())
|
||||
{
|
||||
if (song.Name.ToLower().Trim().Contains(title.ToLower()))
|
||||
{
|
||||
SongBasicInfo songInfo = songBasicDetailsToInfo(song);
|
||||
songs.Add(songInfo);
|
||||
}
|
||||
}
|
||||
return songs;
|
||||
}
|
||||
|
||||
|
||||
//gets song info by song id
|
||||
public SongBasicInfo getSongInfo(int songId)
|
||||
{
|
||||
foreach (SongBasicDetails song in SongRepo.GetAll())
|
||||
{
|
||||
if (song.Song_Id == songId)
|
||||
{
|
||||
SongBasicInfo songInfo = songBasicDetailsToInfo(song);
|
||||
return songInfo;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//gets song recommendation details by song id
|
||||
public SongRecommendationDetails getSongDetails(int songId)
|
||||
{
|
||||
foreach (SongRecommendationDetails songDetails in SongRecommendationRepo.GetAll())
|
||||
{
|
||||
if (songDetails.Song_Id == songId)
|
||||
{
|
||||
return songDetails;
|
||||
}
|
||||
}
|
||||
|
||||
return new SongRecommendationDetails();
|
||||
|
||||
}
|
||||
|
||||
//gets artist info by song id
|
||||
public AuthorDetails getArtistInfo(int SongId)
|
||||
{
|
||||
foreach (SongBasicDetails song in SongRepo.GetAll())
|
||||
{
|
||||
if (song.Song_Id == SongId)
|
||||
{
|
||||
foreach (AuthorDetails artist in ArtistRepo.GetAll())
|
||||
{
|
||||
if (artist.Artist_Id == song.Artist_Id)
|
||||
{
|
||||
return artist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AuthorDetails getMostPublishedAuthor()
|
||||
{
|
||||
Dictionary<int, int> artistCount = new Dictionary<int, int>();
|
||||
foreach (SongBasicDetails song in SongRepo.GetAll())
|
||||
{
|
||||
if (artistCount.ContainsKey(song.Artist_Id))
|
||||
{
|
||||
artistCount[song.Artist_Id]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
artistCount.Add(song.Artist_Id, 1);
|
||||
}
|
||||
}
|
||||
int max = 0;
|
||||
int artistId = 0;
|
||||
foreach (KeyValuePair<int, int> entry in artistCount)
|
||||
{
|
||||
if (entry.Value > max)
|
||||
{
|
||||
max = entry.Value;
|
||||
artistId = entry.Key;
|
||||
}
|
||||
}
|
||||
foreach (AuthorDetails artist in ArtistRepo.GetAll())
|
||||
{
|
||||
if (artist.Artist_Id == artistId)
|
||||
{
|
||||
return artist;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public List<SongBasicInfo> getSongsForMainPage()
|
||||
{
|
||||
List<SongBasicInfo> songs = new List<SongBasicInfo>();
|
||||
int artistId = getMostPublishedAuthor().Artist_Id;
|
||||
foreach (SongBasicDetails song in SongRepo.GetAll())
|
||||
{
|
||||
if (song.Artist_Id == artistId)
|
||||
{
|
||||
SongBasicInfo songInfo = songBasicDetailsToInfo(song);
|
||||
songs.Add(songInfo);
|
||||
}
|
||||
}
|
||||
return songs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
//using System.Windows.Forms;
|
||||
using TechTitans.Models;
|
||||
using TechTitans.Repositories;
|
||||
using TechTitans.Enums;
|
||||
|
||||
namespace TechTitans.Services
|
||||
{
|
||||
internal class FullDetailsOnSongController
|
||||
{
|
||||
//private readonly Repository<SongBasicDetails> SongRepo = new();
|
||||
//private readonly Repository<SongRecommendationDetails> SongRecommendationRepo = new();
|
||||
private readonly Repository<UserPlaybackBehaviour> UserPlaybackBehaviourRepo = new();
|
||||
private readonly Repository<AdDistributionData> AdDistributionDataRepo = new();
|
||||
public FullDetailsOnSong GetFullDetailsOnSong(int songId) {
|
||||
FullDetailsOnSong currentSongDetails = new();
|
||||
DateTime start = new();
|
||||
bool found = false;
|
||||
foreach (UserPlaybackBehaviour action in UserPlaybackBehaviourRepo.GetAll()) {
|
||||
|
||||
if (action.Song_Id == songId) {
|
||||
found = true;
|
||||
// string message;
|
||||
// message = action.Event_Type.ToString() + " " + action.Timestamp.ToString() + " " + action.Song_Id.ToString() + " " + action.User_Id.ToString() + "\n";
|
||||
// MessageBox.Show(message);
|
||||
|
||||
switch (action.Event_Type) {
|
||||
case PlaybackEventType.start_play:
|
||||
start = action.Timestamp;
|
||||
break;
|
||||
case PlaybackEventType.end_play:
|
||||
int minutes = (action.Timestamp - start).Minutes;
|
||||
currentSongDetails.TotalMinutesListened += minutes;
|
||||
currentSongDetails.TotalPlays++;
|
||||
break;
|
||||
case PlaybackEventType.like:
|
||||
currentSongDetails.TotalLikes++;
|
||||
break;
|
||||
case PlaybackEventType.dislike:
|
||||
currentSongDetails.TotalDislikes++;
|
||||
break;
|
||||
case PlaybackEventType.skip:
|
||||
currentSongDetails.TotalSkips++;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// MessageBox.Show(currentSongDetails.TotalMinutesListened.ToString());
|
||||
if (!found) {
|
||||
// MessageBox.Show("Song not found");
|
||||
return null;
|
||||
}
|
||||
return currentSongDetails;
|
||||
}
|
||||
public FullDetailsOnSong GetCurrentMonthDetails(int songId) {
|
||||
FullDetailsOnSong currentSongDetails = new();
|
||||
foreach (UserPlaybackBehaviour action in UserPlaybackBehaviourRepo.GetAll()) {
|
||||
if (action.Song_Id == songId && action.Timestamp.Month == DateTime.Now.Month && action.Timestamp.Year == DateTime.Now.Year) {
|
||||
switch (action.Event_Type) {
|
||||
case PlaybackEventType.start_play:
|
||||
break;
|
||||
case PlaybackEventType.end_play:
|
||||
int minutes = (action.Timestamp - DateTime.Now).Minutes;
|
||||
currentSongDetails.TotalMinutesListened += minutes;
|
||||
currentSongDetails.TotalPlays++;
|
||||
break;
|
||||
case PlaybackEventType.like:
|
||||
currentSongDetails.TotalLikes++;
|
||||
break;
|
||||
case PlaybackEventType.dislike:
|
||||
currentSongDetails.TotalDislikes++;
|
||||
break;
|
||||
case PlaybackEventType.skip:
|
||||
currentSongDetails.TotalSkips++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return currentSongDetails;
|
||||
}
|
||||
public AdDistributionData GetActiveAd(int songId) {
|
||||
foreach (AdDistributionData ad in AdDistributionDataRepo.GetAll()) {
|
||||
if (ad.Song_Id == songId && ad.Month == DateTime.Now.Month && ad.Year == DateTime.Now.Year) {
|
||||
return ad;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TechTitans.Repositories;
|
||||
using TechTitans.Models;
|
||||
using Dapper;
|
||||
using TechTitans.ViewModels;
|
||||
using TechTitans.Enums;
|
||||
|
||||
namespace TechTitans.Services
|
||||
{
|
||||
internal class RecapService
|
||||
{
|
||||
SongBasicDetailsRepository songBasicDetailsRepository = new SongBasicDetailsRepository();
|
||||
UserPlaybackBehaviourRepository userPlaybackBehaviourRepository = new UserPlaybackBehaviourRepository();
|
||||
|
||||
public List<SongBasicInfo> Top5MostListenedSongs(int userId)
|
||||
{
|
||||
var top5Songs = songBasicDetailsRepository.GetTop5MostListenedSongs(userId);
|
||||
List<SongBasicInfo> top5SongsInfo = new List<SongBasicInfo>();
|
||||
foreach (var song in top5Songs)
|
||||
{
|
||||
top5SongsInfo.Add(songBasicDetailsRepository.SongBasicDetailsToSongBasicInfo(song));
|
||||
}
|
||||
return top5SongsInfo;
|
||||
}
|
||||
|
||||
public Tuple<SongBasicInfo, decimal> MostPlayedSongPercentile(int userId)
|
||||
{
|
||||
var mostPlayedSong = songBasicDetailsRepository.GetMostPlayedSongPercentile(userId);
|
||||
return new Tuple<SongBasicInfo, decimal>(songBasicDetailsRepository.SongBasicDetailsToSongBasicInfo(mostPlayedSong.Item1), mostPlayedSong.Item2);
|
||||
}
|
||||
|
||||
public Tuple<string, decimal> MostPlayedArtistPercentile(int userId)
|
||||
{
|
||||
return songBasicDetailsRepository.GetMostPlayedArtistPercentile(userId);
|
||||
}
|
||||
|
||||
public int MinutesListened(int userId)
|
||||
{
|
||||
//get list of all userplaybackbehaviour for a userid sorted ascending by timestamp and go over them calculating the difference between the timestamps and summing them up
|
||||
var userEvents = userPlaybackBehaviourRepository.GetUserPlaybackBehaviour(userId);
|
||||
int minutesListened = 0;
|
||||
//for every start and end event pair, calculate the difference in minutes and add it to the total
|
||||
for (int i = 0; i < userEvents.Count; i++)
|
||||
{
|
||||
if (userEvents[i].Event_Type == PlaybackEventType.start_play)
|
||||
{
|
||||
for (int j = i + 1; j < userEvents.Count; j++)
|
||||
{
|
||||
if (userEvents[j].Event_Type == PlaybackEventType.end_play)
|
||||
{
|
||||
minutesListened += (int)(userEvents[j].Timestamp - userEvents[i].Timestamp).TotalMinutes;
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return minutesListened;
|
||||
}
|
||||
|
||||
public List<string> Top5Genres(int userId)
|
||||
{
|
||||
return this.songBasicDetailsRepository.GetTop5Genres(userId);
|
||||
}
|
||||
|
||||
public List<string> NewGenresDiscovered(int userId)
|
||||
{
|
||||
return this.songBasicDetailsRepository.NewGenresDiscovered(userId);
|
||||
}
|
||||
|
||||
public ListenerPersonality ListenerPersonality(int userId)
|
||||
{
|
||||
var userEvents = userPlaybackBehaviourRepository.GetUserPlaybackBehaviour(userId);
|
||||
int playCount = 0;
|
||||
for(int i = 0; i < userEvents.Count; i++)
|
||||
{
|
||||
if ((userEvents[i].Event_Type == PlaybackEventType.start_play) && (userEvents[i].Timestamp.Year == DateTime.Now.Year))
|
||||
{
|
||||
playCount++;
|
||||
}
|
||||
}
|
||||
if(playCount > 100)
|
||||
{
|
||||
return Enums.ListenerPersonality.Melophile;
|
||||
}
|
||||
var newGenres = NewGenresDiscovered(userId);
|
||||
if(newGenres.Count > 3)
|
||||
{
|
||||
return Enums.ListenerPersonality.Explorer;
|
||||
}
|
||||
if(playCount < 10)
|
||||
{
|
||||
return Enums.ListenerPersonality.Casual;
|
||||
}
|
||||
return Enums.ListenerPersonality.Vanilla;
|
||||
}
|
||||
|
||||
public EndOfYearRecapViewModel GenerateEndOfYearRecap(int userId)
|
||||
{
|
||||
var recap = new EndOfYearRecapViewModel();
|
||||
recap.Top5MostListenedSongs = Top5MostListenedSongs(userId);
|
||||
recap.MostPlayedSongPercentile = MostPlayedSongPercentile(userId);
|
||||
recap.MostPlayedArtistPercentile = MostPlayedArtistPercentile(userId);
|
||||
recap.MinutesListened = MinutesListened(userId);
|
||||
recap.Top5Genres = Top5Genres(userId);
|
||||
recap.NewGenresDiscovered = NewGenresDiscovered(userId);
|
||||
recap.ListenerPersonality = ListenerPersonality(userId);
|
||||
return recap;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TechTitans.Models;
|
||||
using TechTitans.Repositories;
|
||||
namespace TechTitans.Services
|
||||
{
|
||||
public class TopGenresController
|
||||
{
|
||||
private Repository<SongBasicDetails> SongRepo = new Repository<SongBasicDetails>();
|
||||
private Repository<SongRecommendationDetails> SongRecommendationRepo= new Repository<SongRecommendationDetails>();
|
||||
|
||||
public void getTop3Genres(int month,int year,Label genre1,Label minutes1,Label percentage1 , Label genre2, Label minutes2,Label percentage2, Label genre3 ,Label minutes3, Label percentage3) {
|
||||
int totalMinutes = 0;
|
||||
Dictionary<String, int> genreCount = new Dictionary<String, int>();
|
||||
foreach (SongBasicDetails song in SongRepo.GetAll()) {
|
||||
foreach (SongRecommendationDetails songDetails in SongRecommendationRepo.GetAll())
|
||||
{
|
||||
if (songDetails.Song_Id == song.Song_Id && songDetails.Month == month && songDetails.Year == year)
|
||||
{
|
||||
totalMinutes += songDetails.Minutes_Listened;
|
||||
if (genreCount.ContainsKey(song.Genre))
|
||||
{
|
||||
genreCount[song.Genre] += songDetails.Minutes_Listened;
|
||||
}
|
||||
else
|
||||
{
|
||||
genreCount.Add(song.Genre, songDetails.Minutes_Listened);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sortedDict = from entry in genreCount orderby entry.Value descending select entry;
|
||||
int count = 0;
|
||||
foreach (KeyValuePair<String, int> entry in sortedDict)
|
||||
{
|
||||
switch(count)
|
||||
{
|
||||
case 0:
|
||||
genre1.Text = entry.Key;
|
||||
minutes1.Text = entry.Value.ToString();
|
||||
percentage1.Text = ((entry.Value / totalMinutes) * 100).ToString();
|
||||
break;
|
||||
case 1:
|
||||
genre2.Text = entry.Key;
|
||||
minutes2.Text = entry.Value.ToString();
|
||||
percentage2.Text = ((entry.Value / totalMinutes) * 100).ToString();
|
||||
break;
|
||||
case 2:
|
||||
genre3.Text = entry.Key;
|
||||
minutes3.Text = entry.Value.ToString();
|
||||
percentage3.Text = ((entry.Value / totalMinutes) * 100).ToString();
|
||||
break;
|
||||
}
|
||||
if(count ==2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
public void top3SubGenres(int month, int year, Label genre1, Label minutes1, Label percentage1, Label genre2, Label minutes2, Label percentage2, Label genre3, Label minutes3, Label percentage3) {
|
||||
Dictionary<String, int> subgenreCount = new Dictionary<String, int>();
|
||||
int totalMinutes = 0;
|
||||
foreach (SongBasicDetails song in SongRepo.GetAll())
|
||||
{
|
||||
foreach (SongRecommendationDetails songDetails in SongRecommendationRepo.GetAll())
|
||||
{
|
||||
|
||||
if (songDetails.Song_Id == song.Song_Id && songDetails.Month == month && songDetails.Year == year)
|
||||
{
|
||||
totalMinutes += songDetails.Minutes_Listened;
|
||||
if (subgenreCount.ContainsKey(song.Subgenre))
|
||||
{
|
||||
subgenreCount[song.Subgenre] += songDetails.Minutes_Listened;
|
||||
}
|
||||
else
|
||||
{
|
||||
subgenreCount.Add(song.Subgenre, songDetails.Minutes_Listened);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sortedDict = from entry in subgenreCount orderby entry.Value descending select entry;
|
||||
int count = 0;
|
||||
foreach (KeyValuePair<String, int> entry in sortedDict)
|
||||
{
|
||||
switch (count)
|
||||
{
|
||||
case 0:
|
||||
genre1.Text = entry.Key;
|
||||
minutes1.Text = entry.Value.ToString();
|
||||
percentage1.Text = ((entry.Value / totalMinutes) * 100).ToString();
|
||||
break;
|
||||
case 1:
|
||||
genre2.Text = entry.Key;
|
||||
minutes2.Text = entry.Value.ToString();
|
||||
percentage2.Text = ((entry.Value / totalMinutes) * 100).ToString();
|
||||
break;
|
||||
case 2:
|
||||
genre3.Text = entry.Key;
|
||||
minutes3.Text = entry.Value.ToString();
|
||||
percentage3.Text = ((entry.Value / totalMinutes) * 100).ToString();
|
||||
break;
|
||||
}
|
||||
if (count == 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TechTitans.Models;
|
||||
using TechTitans.Repositories;
|
||||
namespace TechTitans.Services
|
||||
{
|
||||
internal class UserService
|
||||
{
|
||||
private UserRepository SongRepo= new UserRepository();
|
||||
|
||||
public List<SongBasicInfo> get_recently_played() {
|
||||
List<SongBasicInfo> list_song=new List<SongBasicInfo>();
|
||||
foreach (SongBasicDetails song in SongRepo.GetAll()){
|
||||
SongBasicInfo song_info = SongRepo.SongBasicDetailsToSongBasicInfo(song);
|
||||
list_song.Add(song_info);
|
||||
}
|
||||
return list_song.Take(6).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0-android;net8.0-maccatalyst;net8.0-ios</TargetFrameworks>
|
||||
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
|
||||
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
|
||||
|
||||
<!-- Note for MacCatalyst:
|
||||
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
|
||||
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.
|
||||
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;
|
||||
either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
|
||||
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->
|
||||
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>TechTitans</RootNamespace>
|
||||
<UseMaui>true</UseMaui>
|
||||
<SingleProject>true</SingleProject>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<!-- Display name -->
|
||||
<ApplicationTitle>TechTitans</ApplicationTitle>
|
||||
|
||||
<!-- App Identifier -->
|
||||
<ApplicationId>com.companyname.techtitans</ApplicationId>
|
||||
|
||||
<!-- Versions -->
|
||||
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
|
||||
<ApplicationVersion>1</ApplicationVersion>
|
||||
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
|
||||
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
|
||||
<Configurations>Debug;Release;Android Emulator</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- App Icon -->
|
||||
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
|
||||
|
||||
<!-- Splash Screen -->
|
||||
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
|
||||
|
||||
<!-- Images -->
|
||||
<MauiImage Include="Resources\Images\*" />
|
||||
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />
|
||||
|
||||
<!-- Custom Fonts -->
|
||||
<MauiFont Include="Resources\Fonts\*" />
|
||||
|
||||
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
|
||||
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="appsettings.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Maui" Version="8.0.1" />
|
||||
<PackageReference Include="Dapper" Version="2.1.35" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.14" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.14" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.88.7" />
|
||||
<PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="2.88.7" />
|
||||
<PackageReference Include="SkiaSharp.Views.Maui.Core" Version="2.88.7" />
|
||||
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Views\AnalystDashboard.xaml.cs">
|
||||
<DependentUpon>AnalystDashboard.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<MauiXaml Update="Views\AnalystPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\ArtistPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\Artist\ArtistSongDashboard.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\BackHomeButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\EndOfYearRecap\FirstScreen.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\EndOfYearRecap\ListenerPersonalityScreen.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\EndOfYearRecap\MinutesListenedScreen.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\EndOfYearRecap\MostListenedGenresScreen.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\EndOfYearRecap\MostPlayedArtistScreen.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\EndOfYearRecap\MostPlayedSongScreen.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\EndOfYearRecap\NewGenresScreen.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\EndOfYearRecap\Top5SongsScreen.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\SongItem.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\User\SearchButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\User\UserSongDashboard.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\EndOfYearRecap.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\MainPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\Components\Piechart.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\AnalystDashboard.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\SearchPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="Views\UserPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
</ItemGroup>
|
||||
|
||||
<ProjectExtensions><VisualStudio><UserProperties XamarinHotReloadDebuggerTimeoutExceptionTechTitansHideInfoBar="True" /></VisualStudio></ProjectExtensions>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.002.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TechTitans", "TechTitans.csproj", "{6923E125-F765-4039-A8BB-1A445E8AE258}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6923E125-F765-4039-A8BB-1A445E8AE258}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6923E125-F765-4039-A8BB-1A445E8AE258}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6923E125-F765-4039-A8BB-1A445E8AE258}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6923E125-F765-4039-A8BB-1A445E8AE258}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C4D38F63-6A7E-48AF-BCD4-DD367B8A6BF8}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.ComponentModel;
|
||||
using TechTitans.Enums;
|
||||
using TechTitans.Models;
|
||||
|
||||
namespace TechTitans.ViewModels
|
||||
{
|
||||
class ArtistSongDashboardViewModel
|
||||
{
|
||||
public SongBasicInfo SongInfo { get; set; }
|
||||
public AuthorDetails ArtistInfo { get; set; }
|
||||
public SongRecommendationDetails SongDetails { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
|
||||
using System.ComponentModel;
|
||||
using TechTitans.Enums;
|
||||
using TechTitans.Models;
|
||||
|
||||
namespace TechTitans.ViewModels
|
||||
{
|
||||
public class EndOfYearRecapViewModel
|
||||
{
|
||||
public List<SongBasicInfo> Top5MostListenedSongs { get; set; }
|
||||
public Tuple<SongBasicInfo, decimal> MostPlayedSongPercentile { get; set; }
|
||||
public Tuple<string, decimal> MostPlayedArtistPercentile { get; set; }
|
||||
public int MinutesListened { get; set; }
|
||||
public List<string> Top5Genres { get; set; }
|
||||
public List<string> NewGenresDiscovered { get; set; }
|
||||
public ListenerPersonality ListenerPersonality { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TechTitans.Views.AnalystDashboard"
|
||||
Title="AnalystDashboard">
|
||||
<VerticalStackLayout>
|
||||
<Label
|
||||
Text="Dashboard"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="Center" />
|
||||
<VerticalStackLayout Spacing="15" Padding="10, 0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Column="0" Text="Total Minutes Listened" />
|
||||
<Label Grid.Column="1" Text="Total Plays" />
|
||||
<Label Grid.Column="2" Text="Total Likes" />
|
||||
<Label Grid.Column="3" Text="Total Dislikes" />
|
||||
<Label Grid.Column="4" Text="Total Skips" />
|
||||
</Grid>
|
||||
<Grid x:Name="Dashboard">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Column="0" Text="{Binding TotalMinutesListened}" />
|
||||
<Label Grid.Column="1" Text="{Binding TotalPlays}" />
|
||||
<Label Grid.Column="2" Text="{Binding TotalLikes}" />
|
||||
<Label Grid.Column="3" Text="{Binding TotalDislikes}" />
|
||||
<Label Grid.Column="4" Text="{Binding TotalSkips}" />
|
||||
</Grid>
|
||||
</VerticalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</ContentPage>
|
||||
@@ -0,0 +1,16 @@
|
||||
using TechTitans.Models;
|
||||
using TechTitans.Services;
|
||||
//using System.IO;
|
||||
namespace TechTitans.Views;
|
||||
|
||||
public partial class AnalystDashboard : ContentPage
|
||||
{
|
||||
public AnalystDashboard()
|
||||
{
|
||||
InitializeComponent();
|
||||
FullDetailsOnSongController fullDetailsOnSongController = new FullDetailsOnSongController();
|
||||
FullDetailsOnSong FullDetails = fullDetailsOnSongController.GetFullDetailsOnSong(201);
|
||||
FullDetailsOnSong CurrentMonth = fullDetailsOnSongController.GetCurrentMonthDetails(201);
|
||||
this.BindingContext = CurrentMonth;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--import pt Components namesapace ca sa putem refolosi componente (this some DRY shit)
|
||||
asta e syntaxa: xmlns:controls="clr-namespace:TechTitans.Views.Components"-->
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:custom="clr-namespace:TechTitans.Views.Components"
|
||||
x:Class="TechTitans.Views.AnalystPage"
|
||||
Title="AnalystPage">
|
||||
<VerticalStackLayout Margin="15,0">
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<StackLayout Padding="10">
|
||||
<Picker Title="Select Month:" x:Name="MonthPicker" SelectedIndex="0" >
|
||||
<Picker.ItemsSource>
|
||||
<x:Array Type="{x:Type x:Int32}">
|
||||
<x:Int32>1</x:Int32>
|
||||
<x:Int32>2</x:Int32>
|
||||
<x:Int32>3</x:Int32>
|
||||
<x:Int32>4</x:Int32>
|
||||
<x:Int32>5</x:Int32>
|
||||
<x:Int32>6</x:Int32>
|
||||
<x:Int32>7</x:Int32>
|
||||
<x:Int32>8</x:Int32>
|
||||
<x:Int32>9</x:Int32>
|
||||
<x:Int32>10</x:Int32>
|
||||
<x:Int32>11</x:Int32>
|
||||
<x:Int32>12</x:Int32>
|
||||
</x:Array>
|
||||
</Picker.ItemsSource>
|
||||
</Picker>
|
||||
</StackLayout>
|
||||
|
||||
<StackLayout Padding="10">
|
||||
<Picker Title="Select Year:" x:Name="YearPicker" SelectedIndex="0" >
|
||||
<Picker.ItemsSource>
|
||||
<x:Array Type="{x:Type x:Int32}">
|
||||
<x:Int32>2020</x:Int32>
|
||||
<x:Int32>2021</x:Int32>
|
||||
<x:Int32>2022</x:Int32>
|
||||
<x:Int32>2023</x:Int32>
|
||||
<x:Int32>2024</x:Int32>
|
||||
<x:Int32>2025</x:Int32>
|
||||
<x:Int32>2026</x:Int32>
|
||||
<x:Int32>2027</x:Int32>
|
||||
<x:Int32>2028</x:Int32>
|
||||
<x:Int32>2029</x:Int32>
|
||||
<x:Int32>2030</x:Int32>
|
||||
</x:Array>
|
||||
</Picker.ItemsSource>
|
||||
</Picker>
|
||||
</StackLayout>
|
||||
<Button Text="Show Top 3s" Clicked="OnShowTop3Clicked" HeightRequest="40" HorizontalOptions="CenterAndExpand"/>
|
||||
</StackLayout>
|
||||
<BoxView Color="Gray" HeightRequest="2" HorizontalOptions="FillAndExpand" Margin="0, 5" />
|
||||
<StackLayout Orientation="Vertical" Spacing="20">
|
||||
<!-- First row -->
|
||||
<StackLayout x:Name="Top3Genres">
|
||||
<Label Text="Top 3 Genres" FontSize="30"/>
|
||||
<HorizontalStackLayout Spacing="20">
|
||||
<VerticalStackLayout>
|
||||
<Label Text="Genre" FontSize="20"/>
|
||||
<BoxView Color="Gray" HeightRequest="2" HorizontalOptions="FillAndExpand" Margin="0, 5" />
|
||||
<Label x:Name="Genre1Name" HorizontalOptions="Center" />
|
||||
<Label x:Name="Genre2Name" HorizontalOptions="Center" />
|
||||
<Label x:Name="Genre3Name" HorizontalOptions="Center" />
|
||||
</VerticalStackLayout>
|
||||
<VerticalStackLayout>
|
||||
<Label Text="Total Listens" FontSize="20"/>
|
||||
<BoxView Color="Gray" HeightRequest="2" HorizontalOptions="FillAndExpand" Margin="0, 5" />
|
||||
<Label x:Name="Genre1Minutes" HorizontalOptions="Center"/>
|
||||
<Label x:Name="Genre2Minutes" HorizontalOptions="Center"/>
|
||||
<Label x:Name="Genre3Minutes" HorizontalOptions="Center"/>
|
||||
</VerticalStackLayout>
|
||||
<VerticalStackLayout>
|
||||
<Label Text="Percentage" FontSize="20"/>
|
||||
<BoxView Color="Gray" HeightRequest="2" HorizontalOptions="FillAndExpand" Margin="0, 5" />
|
||||
<Label x:Name="Percentage1" HorizontalOptions="Center"/>
|
||||
<Label x:Name="Percentage2" HorizontalOptions="Center"/>
|
||||
<Label x:Name="Percentage3" HorizontalOptions="Center"/>
|
||||
</VerticalStackLayout>
|
||||
</HorizontalStackLayout>
|
||||
</StackLayout>
|
||||
<BoxView Color="Gray" HeightRequest="2" HorizontalOptions="FillAndExpand" Margin="0, 5" />
|
||||
<StackLayout>
|
||||
<Label Text="Top 3 Subgenres" FontSize="30"/>
|
||||
<HorizontalStackLayout Spacing="20">
|
||||
<VerticalStackLayout>
|
||||
<Label Text="Genre" FontSize="20"/>
|
||||
<BoxView Color="Gray" HeightRequest="2" HorizontalOptions="FillAndExpand" Margin="0, 5" />
|
||||
<Label x:Name="Subgenre1Name" />
|
||||
<Label x:Name="Subgenre2Name" />
|
||||
<Label x:Name="Subgenre3Name" />
|
||||
</VerticalStackLayout>
|
||||
<VerticalStackLayout>
|
||||
<Label Text="Total Listens" FontSize="20"/>
|
||||
<BoxView Color="Gray" HeightRequest="2" HorizontalOptions="FillAndExpand" Margin="0, 5" />
|
||||
<Label x:Name="Subgenre1Minutes" />
|
||||
<Label x:Name="Subgenre2Minutes" />
|
||||
<Label x:Name="Subgenre3Minutes" />
|
||||
</VerticalStackLayout>
|
||||
<VerticalStackLayout>
|
||||
<Label Text="Percentage" FontSize="20"/>
|
||||
<BoxView Color="Gray" HeightRequest="2" HorizontalOptions="FillAndExpand" Margin="0, 5" />
|
||||
<Label x:Name="Subgenre1Percentage"/>
|
||||
<Label x:Name="Subgenre2Percentage"/>
|
||||
<Label x:Name="Subgenre3Percentage"/>
|
||||
</VerticalStackLayout>
|
||||
</HorizontalStackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</VerticalStackLayout>
|
||||
|
||||
</ContentPage>
|
||||
@@ -0,0 +1,58 @@
|
||||
using TechTitans.Models;
|
||||
using TechTitans.Services;
|
||||
using System.IO;
|
||||
|
||||
|
||||
namespace TechTitans.Views;
|
||||
|
||||
public partial class AnalystPage : ContentPage
|
||||
{
|
||||
|
||||
private TopGenresController topGenresController;
|
||||
private Dictionary<String, int> genreCount = new Dictionary<String, int>();
|
||||
private Dictionary<String, int> subgenreCount = new Dictionary<String, int>();
|
||||
public AnalystPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
topGenresController = new TopGenresController();
|
||||
|
||||
}
|
||||
|
||||
public void ClearText()
|
||||
{
|
||||
Genre1Name.Text = "";
|
||||
Genre1Minutes.Text = "";
|
||||
Genre2Name.Text = "";
|
||||
Genre2Minutes.Text = "";
|
||||
Genre3Name.Text = "";
|
||||
Genre3Minutes.Text = "";
|
||||
}
|
||||
|
||||
private void OnShowTop3Clicked(object sender, EventArgs e)
|
||||
{
|
||||
ClearText();
|
||||
int monthInt = 0;
|
||||
int yearInt = 0;
|
||||
var month = MonthPicker.SelectedItem;
|
||||
var year = YearPicker.SelectedItem;
|
||||
if (month != null && year != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// make them ints
|
||||
monthInt = Convert.ToInt32(month);
|
||||
yearInt = Convert.ToInt32(year);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
|
||||
topGenresController.getTop3Genres(monthInt, yearInt,Genre1Name,Genre1Minutes,Percentage1,Genre2Name,Genre2Name,Percentage2,Genre3Name,Genre3Minutes,Percentage3);
|
||||
topGenresController.top3SubGenres(monthInt, yearInt,Subgenre1Name,Subgenre1Minutes,Subgenre1Percentage,Subgenre2Name,Subgenre2Minutes,Subgenre2Percentage,Subgenre3Name,Subgenre3Minutes,Subgenre3Percentage);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--import pt Components namesapace ca sa putem refolosi componente (this some DRY shit)
|
||||
asta e syntaxa: xmlns:controls="clr-namespace:TechTitans.Views.Components"-->
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:custom="clr-namespace:TechTitans.Views.Components"
|
||||
x:Class="TechTitans.Views.ArtistPage"
|
||||
Title="Welcome DummyArtist69!">
|
||||
<VerticalStackLayout>
|
||||
<Label
|
||||
Text="Your Top Songs"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="Start"
|
||||
FontAttributes="Bold"
|
||||
FontSize="16"
|
||||
Margin="10,0,0,0"
|
||||
/>
|
||||
<BoxView Color="#6E6E6E" HeightRequest="2" HorizontalOptions="FillAndExpand" Margin="10,5"/>
|
||||
<VerticalStackLayout Spacing="15" Padding="10, 0">
|
||||
<Grid x:Name="SongsGrid">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
</Grid>
|
||||
</VerticalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</ContentPage>
|
||||
@@ -0,0 +1,133 @@
|
||||
namespace TechTitans.Views;
|
||||
using TechTitans.Views.Components.Artist;
|
||||
using TechTitans.Views.Components;
|
||||
using TechTitans.Models;
|
||||
using TechTitans.Services;
|
||||
|
||||
public partial class ArtistPage : ContentPage
|
||||
{
|
||||
public ArtistSongDashboardController service = new();
|
||||
public ArtistPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
LoadSongs();
|
||||
}
|
||||
|
||||
private void LoadSongs()
|
||||
{
|
||||
var songs = service.getSongsForMainPage(); // Get your list of songs from somewhere (e.g., database, API, local storage)
|
||||
|
||||
// initial row
|
||||
SongsGrid.RowDefinitions.Add(new RowDefinition());
|
||||
|
||||
|
||||
// Loop through each song and dynamically create SongItem controls
|
||||
int rowIndex = 0;
|
||||
int columnIndex = 0;
|
||||
foreach (var song in songs)
|
||||
{
|
||||
var songItem = new SongItem(); // Create a new instance of SongItem
|
||||
songItem.BindingContext = song; // Set the song as the binding context of the SongItem
|
||||
songItem.Margin = new Thickness(0, 5, 0, 5); // Set margin as needed
|
||||
|
||||
// Add TapGestureRecognizer to handle tap event
|
||||
var tapGestureRecognizer = new TapGestureRecognizer();
|
||||
tapGestureRecognizer.Tapped += SongItem_Tapped;
|
||||
songItem.GestureRecognizers.Add(tapGestureRecognizer);
|
||||
|
||||
// Set the row and column of the SongItem in the grid
|
||||
Grid.SetRow(songItem, rowIndex);
|
||||
Grid.SetColumn(songItem, columnIndex);
|
||||
// Add the SongItem to the grid
|
||||
SongsGrid.Children.Add(songItem);
|
||||
columnIndex++;
|
||||
if (columnIndex == 2) // bun cod
|
||||
{
|
||||
columnIndex = 0;
|
||||
rowIndex++;
|
||||
SongsGrid.RowDefinitions.Add(new RowDefinition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SongItem_Tapped(object sender, System.EventArgs e)
|
||||
{
|
||||
// open ArtistSongDashboard page with song details
|
||||
var songItem = (SongItem)sender;
|
||||
var songInfo = songItem.BindingContext as SongBasicInfo;
|
||||
Navigation.PushAsync(new ArtistSongDashboard(songInfo));
|
||||
}
|
||||
|
||||
// Sample method to get list of songs (replace this with your actual method)
|
||||
private List<SongBasicInfo> GetSongs()
|
||||
{
|
||||
// mocked songs, to be replaced with actual data retrieval from db
|
||||
return new List<SongBasicInfo>
|
||||
{
|
||||
new SongBasicInfo
|
||||
{
|
||||
SongId = 10,
|
||||
Name = "Song 1",
|
||||
Artist = "Artist 1",
|
||||
Image = "song_img_default.png"
|
||||
},
|
||||
new SongBasicInfo
|
||||
{
|
||||
SongId = 201,
|
||||
Name = "Song 2",
|
||||
Artist = "Artist 2",
|
||||
Image = "song_img_default.png"
|
||||
},
|
||||
new SongBasicInfo
|
||||
{
|
||||
SongId = 2,
|
||||
Name = "Song 3",
|
||||
Artist = "Artist 3",
|
||||
Image = "song_img_default.png"
|
||||
},
|
||||
new SongBasicInfo
|
||||
{
|
||||
SongId = 3,
|
||||
Name = "Song 4",
|
||||
Artist = "Artist 4",
|
||||
Image = "song_img_default.png"
|
||||
},
|
||||
new SongBasicInfo
|
||||
{
|
||||
SongId = 4,
|
||||
Name = "Song 5",
|
||||
Artist = "Artist 5",
|
||||
Image = "song_img_default.png"
|
||||
},
|
||||
new SongBasicInfo
|
||||
{
|
||||
SongId = 5,
|
||||
Name = "Song 6",
|
||||
Artist = "Artist 6",
|
||||
Image = "song_img_default.png"
|
||||
},
|
||||
new SongBasicInfo
|
||||
{
|
||||
SongId = 6,
|
||||
Name = "Song 7",
|
||||
Artist = "Artist 7",
|
||||
Image = "song_img_default.png"
|
||||
},
|
||||
new SongBasicInfo
|
||||
{
|
||||
SongId = 7,
|
||||
Name = "Song 8",
|
||||
Artist = "Artist 8",
|
||||
Image = "song_img_default.png"
|
||||
},
|
||||
new SongBasicInfo
|
||||
{
|
||||
SongId = 8,
|
||||
Name = "Song 9",
|
||||
Artist = "Artist 9",
|
||||
Image = "song_img_default.png"
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:custom="clr-namespace:TechTitans.Views.Components"
|
||||
x:Class="TechTitans.Views.Components.Artist.ArtistSongDashboard"
|
||||
Title="Song Dashboard">
|
||||
|
||||
<VerticalStackLayout>
|
||||
<VerticalStackLayout Padding="20" Spacing="10">
|
||||
<Image
|
||||
x:Name="SongImage"
|
||||
HorizontalOptions="Start"
|
||||
HeightRequest="256"
|
||||
WidthRequest="256"
|
||||
/>
|
||||
<Label
|
||||
x:Name="SongTitle"
|
||||
Text=""
|
||||
FontSize="32"
|
||||
FontAttributes="Bold"
|
||||
WidthRequest="256"
|
||||
HorizontalOptions="Start"
|
||||
/>
|
||||
<Label
|
||||
x:Name="SongArtist"
|
||||
Text=""
|
||||
FontSize="20"
|
||||
TextColor="#6E6E6E"
|
||||
Margin="0,-10,0,0"
|
||||
HorizontalOptions="Start"
|
||||
/>
|
||||
<Label
|
||||
x:Name="SongAlbum"
|
||||
Text=""
|
||||
FontSize="24"
|
||||
HorizontalOptions="Start"
|
||||
/>
|
||||
</VerticalStackLayout>
|
||||
<!--linie f ghetto-->
|
||||
<BoxView Color="Gray" HeightRequest="2" HorizontalOptions="FillAndExpand" Margin="10, 5" />
|
||||
<HorizontalStackLayout HorizontalOptions="CenterAndExpand" Spacing="10">
|
||||
<VerticalStackLayout>
|
||||
<Button
|
||||
Text="Info"
|
||||
TextColor="#6E6E6E"
|
||||
FontAttributes="Bold"
|
||||
Style="{StaticResource TabNavButton}"
|
||||
Clicked="OnInfoClick"
|
||||
/>
|
||||
<BoxView x:Name="InfoBoxView" Color="#6E6E6E" HeightRequest="2" HorizontalOptions="FillAndExpand"/>
|
||||
</VerticalStackLayout>
|
||||
<VerticalStackLayout>
|
||||
<Button
|
||||
Text="Performance"
|
||||
TextColor="#6E6E6E"
|
||||
FontAttributes="Bold"
|
||||
Style="{StaticResource TabNavButton}"
|
||||
Clicked="OnPerformanceCLick"
|
||||
/>
|
||||
<BoxView x:Name="PerformanceBoxView" Color="#1E1E1E" HeightRequest="2" HorizontalOptions="FillAndExpand"/>
|
||||
</VerticalStackLayout>
|
||||
</HorizontalStackLayout>
|
||||
<Frame
|
||||
CornerRadius="10"
|
||||
Margin="20,20,20,0"
|
||||
Padding="10"
|
||||
BackgroundColor="#6E6E6E"
|
||||
>
|
||||
<HorizontalStackLayout Spacing="40" HorizontalOptions="Center">
|
||||
<VerticalStackLayout Spacing="20" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
|
||||
<Label
|
||||
x:Name="label1"
|
||||
Text=""
|
||||
FontSize="16"
|
||||
/>
|
||||
<Label
|
||||
x:Name="label2"
|
||||
Text=""
|
||||
FontSize="16"
|
||||
/>
|
||||
<Label
|
||||
x:Name="label3"
|
||||
Text=""
|
||||
FontSize="16"
|
||||
/>
|
||||
<Label
|
||||
x:Name="label4"
|
||||
Text=""
|
||||
FontSize="16"
|
||||
/>
|
||||
</VerticalStackLayout>
|
||||
<VerticalStackLayout Spacing="20" VerticalOptions="FillAndExpand" HorizontalOptions="EndAndExpand">
|
||||
<Label
|
||||
x:Name="content1"
|
||||
Text=""
|
||||
FontSize="16"
|
||||
/>
|
||||
<Label
|
||||
x:Name="content2"
|
||||
Text=""
|
||||
FontSize="16"
|
||||
/>
|
||||
<Label
|
||||
x:Name="content3"
|
||||
Text=""
|
||||
FontSize="16"
|
||||
/>
|
||||
<Label
|
||||
x:Name="content4"
|
||||
Text=""
|
||||
FontSize="16"
|
||||
/>
|
||||
</VerticalStackLayout>
|
||||
</HorizontalStackLayout>
|
||||
|
||||
</Frame>
|
||||
</VerticalStackLayout>
|
||||
</ContentPage>
|
||||
@@ -0,0 +1,85 @@
|
||||
using TechTitans.Models;
|
||||
using TechTitans.ViewModels;
|
||||
using TechTitans.Services;
|
||||
namespace TechTitans.Views.Components.Artist;
|
||||
|
||||
public partial class ArtistSongDashboard : ContentPage
|
||||
{
|
||||
public ArtistSongDashboardController service = new ();
|
||||
// alt domain song type cu mai multe detalii
|
||||
int songId;
|
||||
ArtistSongDashboardViewModel viewModel;
|
||||
public ArtistSongDashboard(SongBasicInfo song)
|
||||
{
|
||||
songId = song.SongId;
|
||||
InitializeComponent();
|
||||
populateViewModel(songId);
|
||||
LoadPage();
|
||||
}
|
||||
private void populateViewModel(int songID)
|
||||
{
|
||||
viewModel = new ArtistSongDashboardViewModel() {
|
||||
SongInfo = service.getSongInfo(songID),
|
||||
SongDetails = service.getSongDetails(songID),
|
||||
ArtistInfo = service.getArtistInfo(songID)
|
||||
};
|
||||
}
|
||||
private void LoadPage()
|
||||
{
|
||||
SongImage.Source = viewModel.SongInfo.Image;
|
||||
SongTitle.Text = viewModel.SongInfo.Name;
|
||||
SongArtist.Text = "by " + viewModel.ArtistInfo.Name;
|
||||
SongAlbum.Text = "from " + viewModel.SongInfo.Album;
|
||||
|
||||
// set song info panel
|
||||
label1.Text = "Genre:";
|
||||
content1.Text = viewModel.SongInfo.Genre;
|
||||
label2.Text = "Subgenre:";
|
||||
content2.Text = viewModel.SongInfo.Subgenre;
|
||||
label3.Text = "Country:";
|
||||
content3.Text = viewModel.SongInfo.Country;
|
||||
label4.Text = "Language:";
|
||||
content4.Text = viewModel.SongInfo.Language;
|
||||
}
|
||||
|
||||
// private ArtistSongDashboardViewModel getMockedViewModel()
|
||||
//{
|
||||
// var mockedModel = new ArtistSongDashboardViewModel()
|
||||
// {
|
||||
// SongInfo = new SongBasicInfo(),
|
||||
// SongDetails = new SongRecommendationDetails(),
|
||||
// ArtistInfo = new AuthorDetails(),
|
||||
// };
|
||||
// return mockedModel;
|
||||
//}
|
||||
|
||||
private void OnInfoClick(object sender, EventArgs e)
|
||||
{
|
||||
InfoBoxView.Color = Color.FromArgb("#6E6E6E");
|
||||
PerformanceBoxView.Color = Color.FromArgb("#1E1E1E");
|
||||
|
||||
label1.Text = "Genre:";
|
||||
content1.Text = viewModel.SongInfo.Genre;
|
||||
label2.Text = "Subgenre:";
|
||||
content2.Text = viewModel.SongInfo.Subgenre;
|
||||
label3.Text = "Country:";
|
||||
content3.Text = viewModel.SongInfo.Country;
|
||||
label4.Text = "Language:";
|
||||
content4.Text = viewModel.SongInfo.Language;
|
||||
}
|
||||
|
||||
private void OnPerformanceCLick(object sender, EventArgs e)
|
||||
{
|
||||
PerformanceBoxView.Color = Color.FromArgb("#6E6E6E");
|
||||
InfoBoxView.Color = Color.FromArgb("#1E1E1E");
|
||||
|
||||
label1.Text = "Minutes Listened:";
|
||||
content1.Text = viewModel.SongDetails.Minutes_Listened.ToString();
|
||||
label2.Text = "Total Plays:";
|
||||
content2.Text = viewModel.SongDetails.Number_Of_Plays.ToString();
|
||||
label3.Text = "Likes:";
|
||||
content3.Text = viewModel.SongDetails.Likes.ToString();
|
||||
label4.Text = "Dislikes:";
|
||||
content4.Text = viewModel.SongDetails.Dislikes.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TechTitans.Views.Components.BackHomeButton">
|
||||
<VerticalStackLayout>
|
||||
<Button
|
||||
x:Name="HomeBtn"
|
||||
Text="Go Home"
|
||||
Clicked="OnBackClick"
|
||||
HorizontalOptions="Start"
|
||||
Margin="15,0,0,0"
|
||||
/>
|
||||
<!--xaml e retardat ca se ia left,top,right,bottom la margin si restu in loc sa inceapa de la top ca in css-->
|
||||
</VerticalStackLayout>
|
||||
</ContentView>
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace TechTitans.Views.Components;
|
||||
|
||||
public partial class BackHomeButton : ContentView
|
||||
{
|
||||
public BackHomeButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnBackClick(object sender, EventArgs e) => Application.Current.MainPage = new NavigationPage(new MainPage());
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TechTitans.Views.Components.EndOfYearRecap.FirstScreen">
|
||||
<StackLayout x:Name="Background" BackgroundColor="#0A14C8" VerticalOptions="FillAndExpand">
|
||||
<Label
|
||||
Text="Sounds like you had quite the 2023. Let's play it back..."
|
||||
VerticalOptions="Start"
|
||||
HorizontalOptions="Center"
|
||||
FontSize="25"
|
||||
Padding="20,40,20,20"
|
||||
TextColor="White"/>
|
||||
<StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
|
||||
<Image
|
||||
Source= "first_screen_1.jpg"
|
||||
HeightRequest="256"
|
||||
WidthRequest="256"
|
||||
Aspect="Fill"
|
||||
x:Name="GenericImage"
|
||||
/>
|
||||
</StackLayout>
|
||||
|
||||
</StackLayout>
|
||||
</ContentView>
|
||||
@@ -0,0 +1,44 @@
|
||||
namespace TechTitans.Views.Components.EndOfYearRecap;
|
||||
|
||||
public partial class FirstScreen : ContentView
|
||||
{
|
||||
public FirstScreen()
|
||||
{
|
||||
InitializeComponent();
|
||||
ChangeImageAndBackgraound();
|
||||
}
|
||||
|
||||
private async void ChangeImageAndBackgraound()
|
||||
{
|
||||
await Task.Delay(3000);
|
||||
var imagesource = new FileImageSource
|
||||
{
|
||||
File = "first_screen_2.jpg"
|
||||
};
|
||||
GenericImage.Source = imagesource;
|
||||
Background.BackgroundColor = new Color(200, 20, 200);
|
||||
await Task.Delay(3000);
|
||||
imagesource = new FileImageSource
|
||||
{
|
||||
File = "first_screen_3.jpg"
|
||||
};
|
||||
GenericImage.Source = imagesource;
|
||||
Background.BackgroundColor = new Color(100, 200, 100);
|
||||
await Task.Delay(3000);
|
||||
imagesource = new FileImageSource
|
||||
{
|
||||
File = "first_screen_4.jpg"
|
||||
};
|
||||
GenericImage.Source = imagesource;
|
||||
Background.BackgroundColor = new Color(200, 200, 20);
|
||||
await Task.Delay(3000);
|
||||
imagesource = new FileImageSource
|
||||
{
|
||||
File = "first_screen_1.jpg"
|
||||
};
|
||||
GenericImage.Source = imagesource;
|
||||
Background.BackgroundColor = new Color(10, 20, 200);
|
||||
ChangeImageAndBackgraound();
|
||||
|
||||
}
|
||||
}
|
||||