diff --git a/osrs-toolbox/Models/CompetitionOverlayModel.cs b/osrs-toolbox/Models/CompetitionOverlayModel.cs
new file mode 100644
index 0000000..4869621
--- /dev/null
+++ b/osrs-toolbox/Models/CompetitionOverlayModel.cs
@@ -0,0 +1,85 @@
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows;
+
+namespace osrs_toolbox
+{
+ public abstract class CompetitionOverlayModel : ModelBase
+ {
+ private int _competitionId = -1;
+ private int _groupId = -1;
+ private string _playerName = string.Empty;
+ private string _testOutput = string.Empty;
+ private StackPanel _gridOutput = new StackPanel();
+ private Visibility _controlsVisible = Visibility.Visible;
+ private string _toggleButtonText = string.Empty;
+ private bool _hideOtherPlayers = false;
+ private bool _hideZeroKC = false;
+
+ private ICommand _update;
+ private ICommand _toggleVisibility;
+ private ICommand _closeApp;
+
+ public int CompetitionID
+ {
+ get { return _competitionId; }
+ set { SetProperty(ref _competitionId, value, nameof(CompetitionID)); }
+ }
+ public int GroupID
+ {
+ get { return _groupId; }
+ set { SetProperty(ref _groupId, value, nameof(GroupID)); }
+ }
+ public string PlayerName
+ {
+ get { return _playerName; }
+ set { SetProperty(ref _playerName, value, nameof(PlayerName)); }
+ }
+ public string TestOutput
+ {
+ get { return _testOutput; }
+ set { SetProperty(ref _testOutput, value, nameof(TestOutput)); }
+ }
+ public StackPanel GridOutput
+ {
+ get { return _gridOutput; }
+ set { SetProperty(ref _gridOutput, value, nameof(GridOutput)); }
+ }
+ public Visibility ControlsVisible
+ {
+ get { return _controlsVisible; }
+ set { SetProperty(ref _controlsVisible, value, nameof(ControlsVisible)); }
+ }
+ public string ToggleButtonText
+ {
+ get { return _toggleButtonText; }
+ set { SetProperty(ref _toggleButtonText, value, nameof(ToggleButtonText)); }
+ }
+ public bool HideOtherPlayers
+ {
+ get { return _hideOtherPlayers; }
+ set { SetProperty(ref _hideOtherPlayers, value, nameof(HideOtherPlayers)); }
+ }
+ public bool HideZeroKC
+ {
+ get { return _hideZeroKC; }
+ set { SetProperty(ref _hideZeroKC, value, nameof(HideZeroKC)); }
+ }
+
+ public ICommand Update
+ {
+ get { return _update; }
+ set { SetProperty(ref _update, value, nameof(Update)); }
+ }
+ public ICommand ToggleVisibility
+ {
+ get { return _toggleVisibility; }
+ set { SetProperty(ref _toggleVisibility, value, nameof(ToggleVisibility)); }
+ }
+ public ICommand CloseApp
+ {
+ get { return _closeApp; }
+ set { SetProperty(ref _closeApp, value, nameof(CloseApp)); }
+ }
+ }
+}
diff --git a/osrs-toolbox/ViewModels/CompetitionOverlayViewModel.cs b/osrs-toolbox/ViewModels/CompetitionOverlayViewModel.cs
new file mode 100644
index 0000000..2dbf367
--- /dev/null
+++ b/osrs-toolbox/ViewModels/CompetitionOverlayViewModel.cs
@@ -0,0 +1,185 @@
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Threading;
+using System.Windows;
+
+namespace osrs_toolbox
+{
+ public class CompetitionOverlayViewModel : CompetitionOverlayModel
+ {
+ public CompetitionOverlayViewModel()
+ {
+ InitializeVariables();
+ InitializeCommands();
+ InitializeTimer();
+ }
+
+ private void InitializeVariables()
+ {
+ CompetitionID = 80030;
+ GroupID = 11197;
+ PlayerName = "kalakoi";
+ TestOutput = string.Empty;
+ GridOutput = new StackPanel();
+ ControlsVisible = Visibility.Visible;
+ ToggleButtonText = "V";
+ HideOtherPlayers = false;
+ HideZeroKC = false;
+ }
+
+ private void InitializeCommands()
+ {
+ Update = new RelayCommand(DoUpdate);
+ CloseApp = new RelayCommand(DoCloseApp);
+ ToggleVisibility = new RelayCommand(DoToggleControls);
+ }
+
+ private void InitializeTimer()
+ {
+ DispatcherTimer dt = new DispatcherTimer();
+ dt.Interval = TimeSpan.FromSeconds(5);
+ dt.Tick += new EventHandler(TimerTick);
+ dt.Start();
+ }
+
+ private void TimerTick(object sender, EventArgs e)
+ {
+ DoUpdate(null);
+ }
+
+ private void DoUpdate(object obj)
+ {
+ GridOutput = new StackPanel();
+ Competition c = new Competition();
+ try
+ {
+ c = WiseOldMan.GetCompetition(CompetitionID);
+ }
+ catch
+ {
+ GridOutput.Children.Add(new OutlinedTextBlock()
+ {
+ Text = "Failed to load competition data",
+ Margin = new Thickness(3),
+ StrokeThickness = 1,
+ Stroke = Brushes.Black,
+ Fill = Brushes.White,
+ FontSize = 20,
+ VerticalAlignment = VerticalAlignment.Center,
+ HorizontalAlignment = HorizontalAlignment.Left,
+ FontWeight = FontWeights.ExtraBold,
+ TextWrapping = TextWrapping.Wrap
+ });
+ OnPropertyChanged(nameof(GridOutput));
+ return;
+ }
+
+ int KCSum = 0;
+ string TempOut = c.title;
+ GridOutput.Children.Add(new OutlinedTextBlock()
+ {
+ Text = c.title,
+ Margin = new Thickness(3),
+ StrokeThickness = 1,
+ Stroke = Brushes.Black,
+ Fill = Brushes.White,
+ FontSize = 20,
+ VerticalAlignment = VerticalAlignment.Center,
+ HorizontalAlignment = HorizontalAlignment.Left,
+ FontWeight = FontWeights.ExtraBold,
+ TextWrapping = TextWrapping.Wrap
+ });
+ foreach (CompetitionParticipation cp in c.participations)
+ {
+ StackPanel SubStack = new StackPanel()
+ {
+ Orientation = Orientation.Horizontal
+ };
+
+ Image typeImage = new Image();
+ if (cp.player.type == "ironman")
+ typeImage.Source = ExternalResources.IronImage;
+ else typeImage.Source = ExternalResources.MainImage;
+ typeImage.IsHitTestVisible = false;
+
+ SubStack.Children.Add(typeImage);
+
+ SubStack.Children.Add(new OutlinedTextBlock()
+ {
+ Text = cp.player.displayName,
+ Margin = new Thickness(3),
+ StrokeThickness = 1,
+ Stroke = Brushes.Black,
+ Fill = PlayerName.ToUpper() == cp.player.displayName.ToUpper() ? Brushes.Green : Brushes.White,
+ FontSize = 20,
+ FontWeight = FontWeights.ExtraBold,
+ VerticalAlignment = VerticalAlignment.Center,
+ HorizontalAlignment = HorizontalAlignment.Left,
+ IsHitTestVisible = false
+ });
+
+ SubStack.Children.Add(new OutlinedTextBlock()
+ {
+ Text = string.Format(" - {0} KC", cp.progress.gained.ToString()),
+ Margin = new Thickness(3),
+ StrokeThickness = 1,
+ Stroke = Brushes.Black,
+ Fill = Brushes.White,
+ FontSize = 20,
+ FontWeight = FontWeights.ExtraBold,
+ VerticalAlignment = VerticalAlignment.Center,
+ HorizontalAlignment = HorizontalAlignment.Left,
+ IsHitTestVisible = false
+ });
+
+ KCSum += cp.progress.gained;
+
+ bool AddToDisplay = true;
+ if (HideOtherPlayers && PlayerName.ToUpper() != cp.player.displayName.ToUpper())
+ AddToDisplay = false;
+ else if (HideZeroKC && cp.progress.gained == 0 && PlayerName.ToUpper() != cp.player.displayName.ToUpper())
+ AddToDisplay = false;
+
+ if (AddToDisplay)
+ GridOutput.Children.Add(SubStack);
+ }
+ GridOutput.Children.Add(new OutlinedTextBlock()
+ {
+ Text = string.Format("Total KC: {0}", KCSum),
+ Margin = new Thickness(3),
+ StrokeThickness = 1,
+ Stroke = Brushes.Black,
+ Fill = Brushes.White,
+ FontSize = 20,
+ FontWeight = FontWeights.ExtraBold,
+ VerticalAlignment = VerticalAlignment.Center,
+ HorizontalAlignment = HorizontalAlignment.Left,
+ IsHitTestVisible = false
+ });
+ OnPropertyChanged(nameof(GridOutput));
+ }
+
+ private void DoCloseApp(object obj)
+ {
+ Application.Current.Shutdown();
+ }
+
+ private void DoToggleControls(object obj)
+ {
+ if (ControlsVisible == Visibility.Visible)
+ {
+ ControlsVisible = Visibility.Collapsed;
+ Application.Current.MainWindow.ResizeMode = ResizeMode.NoResize;
+ Application.Current.MainWindow.Topmost = true;
+ ToggleButtonText = ">";
+ }
+ else
+ {
+ ControlsVisible = Visibility.Visible;
+ Application.Current.MainWindow.ResizeMode = ResizeMode.CanResizeWithGrip;
+ Application.Current.MainWindow.Topmost = false;
+ ToggleButtonText = "V";
+ }
+ }
+ }
+}
diff --git a/osrs-toolbox/Views/CompetitionOverlayView.xaml b/osrs-toolbox/Views/CompetitionOverlayView.xaml
new file mode 100644
index 0000000..80b8eed
--- /dev/null
+++ b/osrs-toolbox/Views/CompetitionOverlayView.xaml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/osrs-toolbox/Views/CompetitionOverlayView.xaml.cs b/osrs-toolbox/Views/CompetitionOverlayView.xaml.cs
new file mode 100644
index 0000000..fc5bf2c
--- /dev/null
+++ b/osrs-toolbox/Views/CompetitionOverlayView.xaml.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace osrs_toolbox
+{
+ ///
+ /// Interaction logic for CompetitionOverlayView.xaml
+ ///
+ public partial class CompetitionOverlayView : Window
+ {
+ public CompetitionOverlayView()
+ {
+ InitializeComponent();
+ }
+
+ private void Window_MouseDown(object sender, MouseButtonEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ DragMove();
+ }
+ }
+}