School Commit Init

This commit is contained in:
2024-08-31 12:07:21 +03:00
commit 0b130ee18c
2801 changed files with 4720552 additions and 0 deletions
+25
View File
@@ -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));
}
}
}
+28
View File
@@ -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
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 710 KiB

Binary file not shown.

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 935 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

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();
}
}

Some files were not shown because too many files have changed in this diff Show More