Commits

Mark Heath  committed c35c23f

more refactoring ready to support multiple contests

  • Participants
  • Parent commits e24f4ef

Comments (0)

Files changed (13)

File MusicRater/Model/Contest.cs

     /// </summary>
     public class Contest
     {
-        public Contest(string fileName)
+        private readonly ContestInfo contestInfo;
+
+        public Contest(ContestInfo contestInfo)
         {
-            FileName = fileName;
+            this.contestInfo = contestInfo;
             Criteria = new List<Criteria>();
             Tracks = new List<Track>();
         }
         /// <summary>
         /// The Filename that should be used to save this contest within isolated store
         /// </summary>
-        public string FileName { get; private set; }
+        public string FileName { get { return contestInfo.IsoStoreFileName; } }
 
         /// <summary>
         /// The URL to load contest track info from (KVR OSC metadata on archive.org only supported at the moment)
         /// </summary>
-        public string LoadUrl { get; set; }
+        public string TrackListUrl { get { return contestInfo.TrackListUrl; } }
 
         /// <summary>
         /// The judging criteria for this contest
         /// <summary>
         /// A friendly name for this contest
         /// </summary>
-        public string Name { get; set; }
+        public string Name { get { return contestInfo.Name; } }
     }
 }

File MusicRater/Model/ContestInfo.cs

+namespace MusicRater.Model
+{
+    /// <summary>
+    /// Information about a contest
+    /// </summary>
+    public class ContestInfo
+    {
+        /// <summary>
+        /// A friendly name for this contest
+        /// </summary>
+        public string Name { get; set; }
+        /// <summary>
+        /// URL to download tracklist
+        /// </summary>
+        public string TrackListUrl { get; set; }
+        /// <summary>
+        /// File name to use in iso store
+        /// </summary>
+        public string IsoStoreFileName { get; set; }
+    }
+}

File MusicRater/MusicRater.csproj

     <Compile Include="DummyViewModels\DummyRatingControlViewModel.cs" />
     <Compile Include="DummyViewModels\DummyTrackListControlViewModel.cs" />
     <Compile Include="Model\Contest.cs" />
+    <Compile Include="Model\ContestInfo.cs" />
     <Compile Include="MvvmUtils\DialogCloser.cs" />
     <Compile Include="Persistence\IIsolatedStore.cs" />
     <Compile Include="Persistence\IsolatedStore.cs" />
     <Compile Include="MvvmUtils\BoolToVisibilityConverter.cs" />
-    <Compile Include="Persistence\CombinedContestLoader.cs" />
+    <Compile Include="Persistence\ContestLoader.cs" />
     <Compile Include="Model\Criteria.cs" />
     <Compile Include="DummyViewModels\DummyErrorMessageViewModel.cs" />
     <Compile Include="DummyViewModels\DummyMainWindowViewModel.cs" />
     </Compile>
     <Compile Include="Persistence\IsolatedStoreContestLoader.cs" />
     <Compile Include="Persistence\IContestLoader.cs" />
-    <Compile Include="Persistence\KvrContestLoader.cs" />
+    <Compile Include="Persistence\KvrTrackListLoader.cs" />
     <Compile Include="MvvmUtils\ExtensionMethods.cs" />
     <Compile Include="MvvmUtils\SecondsToTimeDisplayConverter.cs" />
     <Compile Include="ViewModels\AnonymiseCommand.cs" />

File MusicRater/Persistence/CombinedContestLoader.cs

-using System;
-using System.Linq;
-
-namespace MusicRater
-{
-    public class CombinedContestLoader : IContestLoader
-    {
-        private readonly IContestLoader firstTimeLoader;
-        private readonly IContestLoader subsequentLoader;
-
-        public CombinedContestLoader(IContestLoader firstTimeLoader, IContestLoader subsequentLoader)
-        {
-            this.firstTimeLoader = firstTimeLoader;
-            this.subsequentLoader = subsequentLoader;
-            subsequentLoader.Loaded += loader_Loaded;
-        }
-
-        public void BeginLoad()
-        {
-            subsequentLoader.BeginLoad();
-        }
-
-        void loader_Loaded(object sender, ContestLoadedEventArgs e)
-        {
-            if (e.Error == null && e.Contest != null)
-            {
-                RaiseLoadedEvent(e);
-            }
-            else
-            {
-                firstTimeLoader.Loaded += (s, args) => RaiseLoadedEvent(args);
-                firstTimeLoader.BeginLoad();
-            }
-        }
-
-        private void RaiseLoadedEvent(ContestLoadedEventArgs e)
-        {
-            if (Loaded != null)
-            {
-                Loaded(this, e);
-            }
-        }
-
-        public event EventHandler<ContestLoadedEventArgs> Loaded;
-    }
-}

File MusicRater/Persistence/ContestLoader.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MusicRater.Model;
+
+namespace MusicRater
+{
+    public class ContestLoader
+    {
+        private readonly ContestInfo contestInfo;
+        private readonly IsolatedStoreContestLoader isoLoader;
+        private readonly KvrTrackListLoader kvrLoader;
+
+        public ContestLoader(ContestInfo contestInfo, IIsolatedStore isoStore, Criteria[] defaultCriteria)
+        {
+            this.contestInfo = contestInfo;
+            this.isoLoader = new IsolatedStoreContestLoader(contestInfo.IsoStoreFileName, isoStore);
+            this.kvrLoader = new KvrTrackListLoader(contestInfo.TrackListUrl, defaultCriteria);
+            
+        }
+
+        public void BeginLoad()
+        {
+            var contest = isoLoader.Load();
+            if (contest == null)
+            {
+                kvrLoader.Loaded += OnTracksLoaded;
+                kvrLoader.BeginLoad();
+            }
+            else
+            {
+                OnLoaded(new LoadedEventArgs<Contest>(contest));
+            }
+        }
+
+        void OnTracksLoaded(object sender, LoadedEventArgs<List<Track>> e)
+        {
+            if (e.Error == null && e.Result != null)
+            {
+                OnLoaded(new LoadedEventArgs<Contest>(e.Error));
+            }
+            else
+            {
+                var contest = new Contest(contestInfo);
+                contest.Tracks.AddRange(e.Result);
+                OnLoaded(new LoadedEventArgs<Contest>(contest));
+            }
+        }
+
+        public event EventHandler<LoadedEventArgs<Contest>> Loaded;
+
+        protected virtual void OnLoaded(LoadedEventArgs<Contest> e)
+        {
+            EventHandler<LoadedEventArgs<Contest>> handler = Loaded;
+            if (handler != null) handler(this, e);
+        }
+    }
+}

File MusicRater/Persistence/IContestLoader.cs

 
 namespace MusicRater
 {
-    public interface IContestLoader
+    public class LoadedEventArgs<T> : EventArgs
     {
-        void BeginLoad();
-        event EventHandler<ContestLoadedEventArgs> Loaded;
-    }
-
-    public class ContestLoadedEventArgs : EventArgs
-    {
-        public ContestLoadedEventArgs(Contest contest)
+        public LoadedEventArgs(T result)
         {
-            Contest = contest;
+            Result = result;
         }
 
-        public ContestLoadedEventArgs(Exception error)
+        public LoadedEventArgs(Exception error)
         {
             Error = error;
         }
 
         public Exception Error { get; set; }
-        public Contest Contest { get; private set; }
+        public T Result { get; private set; }
     }
 }

File MusicRater/Persistence/IsolatedStore.cs

 
         public IsolatedStore()
         {
-            this.isoStore = IsolatedStorageFile.GetUserStoreForApplication();
+            isoStore = IsolatedStorageFile.GetUserStoreForApplication();
         }
 
         public bool FileExists(string fileName)
 
         public void Dispose()
         {
-            this.isoStore.Dispose();
+            isoStore.Dispose();
             GC.SuppressFinalize(this);
         }
 

File MusicRater/Persistence/IsolatedStoreContestLoader.cs

 using System;
-using System.Net;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Documents;
-using System.Windows.Ink;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Animation;
-using System.Windows.Shapes;
-using System.Collections.Generic;
 using MusicRater.Model;
 
 namespace MusicRater
 {
-    public class IsolatedStoreContestLoader : IContestLoader
+    public class IsolatedStoreContestLoader
     {
         private readonly IIsolatedStore isoStore;
         private readonly string fileName;
             this.isoStore = isoStore;
         }
 
-        public void BeginLoad()
+        public Contest Load()
         {
             var repo = new RatingsRepository(isoStore);
-            var contest = repo.Load(this.fileName);
+            var contest = repo.Load(fileName);
             if (contest != null)
             {
-                KvrContestLoader.Shuffle(contest.Tracks, new Random());
+                KvrTrackListLoader.Shuffle(contest.Tracks, new Random());
             }
-            OnLoaded(new ContestLoadedEventArgs(contest));
+            return contest;
         }
 
-        public event EventHandler<ContestLoadedEventArgs> Loaded;
-
-        protected virtual void OnLoaded(ContestLoadedEventArgs e)
-        {
-            EventHandler<ContestLoadedEventArgs> handler = Loaded;
-            if (handler != null) handler(this, e);
-        }
     }
 }

File MusicRater/Persistence/KvrContestLoader.cs

-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using System.Xml.Linq;
-using MusicRater.Model;
-
-namespace MusicRater
-{
-    public class KvrContestLoader : IContestLoader
-    {
-        public event EventHandler<ContestLoadedEventArgs> Loaded;
-
-        private readonly string fileName;
-        private readonly string loadUrl;
-
-        public KvrContestLoader(string fileName, string loadUrl)
-        {
-            this.fileName = fileName;
-            this.loadUrl = loadUrl;
-        }
-
-        public void BeginLoad()
-        {
-            var wc = new WebClient();
-            Uri uri = new Uri(loadUrl, UriKind.Absolute);
-            wc.DownloadStringCompleted += wc_DownloadStringCompleted;
-            wc.DownloadStringAsync(uri);
-        }
-
-        void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
-        {
-            if (e.Error == null)
-            {
-                string path = loadUrl.Substring(0,loadUrl.LastIndexOf('/')+1);
-                LoadTrackList(e.Result, path);
-            }
-            else
-            {
-                OnLoaded(new ContestLoadedEventArgs(e.Error));
-            }
-        }
-
-        void LoadTrackList(string xml, string prefix)
-        {
-            var contest = new Contest(fileName);
-            contest.Criteria.Add(new Criteria("Song Writing"));
-            contest.Criteria.Add(new Criteria("Sounds"));
-            contest.Criteria.Add(new Criteria("Production"));
-            XDocument xdoc = XDocument.Parse(xml);
-            foreach (var file in xdoc.Element("files").Elements("file"))
-            {
-                string audioFileName = file.Attribute("name").Value;
-                if (audioFileName.EndsWith(".mp3", StringComparison.OrdinalIgnoreCase))
-                {
-                    var t = new Track(from c in contest.Criteria select new Rating(c));
-                    var titleElement = file.Element("title");
-                    if (titleElement != null)
-                    {
-                        string title = file.Element("title").Value;
-                        string sep = " - ";
-                        int index = title.IndexOf(sep);
-                        if (index == -1)
-                        {
-                            sep = "-";
-                            index = title.IndexOf(sep);
-                        }
-                        t.Author = index == -1 ? "Unknown" : title.Substring(0, index);
-                        t.Title = index == -1 ? title : title.Substring(index + sep.Length);
-                        t.Title = t.Title.Trim();
-                    }
-                    else
-                    {
-                        // work it out from the MP3 name
-                        string nameOnly = audioFileName.Substring(0, audioFileName.Length - 4);
-                        int index = nameOnly.IndexOf("-");
-                        t.Author = index == -1 ? "Unknown" : nameOnly.Substring(0, index);
-                        t.Title = index == -1 ? nameOnly : nameOnly.Substring(index + 1);
-                    }
-                    t.Url = prefix + audioFileName;
-                    contest.Tracks.Add(t);
-                }
-            }
-            Shuffle(contest.Tracks, new Random());
-            OnLoaded(new ContestLoadedEventArgs(contest));
-        }
-
-        public static void Shuffle<T>(IList<T> list, Random rng)
-        {
-            // Note i > 0 to avoid final pointless iteration
-            for (int i = list.Count - 1; i > 0; i--)
-            {
-                // Swap element "i" with a random earlier element it (or itself)
-                int swapIndex = rng.Next(i + 1);
-                T tmp = list[i];
-                list[i] = list[swapIndex];
-                list[swapIndex] = tmp;
-            }
-        }
-
-
-        protected virtual void OnLoaded(ContestLoadedEventArgs e)
-        {
-            EventHandler<ContestLoadedEventArgs> handler = Loaded;
-            if (handler != null) handler(this, e);
-        }
-    }
-}

File MusicRater/Persistence/KvrTrackListLoader.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Xml.Linq;
+using MusicRater.Model;
+
+namespace MusicRater
+{
+    public class KvrTrackListLoader
+    {
+        public event EventHandler<LoadedEventArgs<List<Track>>> Loaded;
+
+        private readonly string loadUrl;
+        private readonly Criteria[] defaultCriteria;
+
+        public KvrTrackListLoader(string loadUrl, Criteria[] defaultCriteria)
+        {
+            this.loadUrl = loadUrl;
+            this.defaultCriteria = defaultCriteria;
+        }
+
+        public void BeginLoad()
+        {
+            var wc = new WebClient();
+            Uri uri = new Uri(loadUrl, UriKind.Absolute);
+            wc.DownloadStringCompleted += wc_DownloadStringCompleted;
+            wc.DownloadStringAsync(uri);
+        }
+
+        void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
+        {
+            if (e.Error == null)
+            {
+                string path = loadUrl.Substring(0,loadUrl.LastIndexOf('/')+1);
+                LoadTrackList(e.Result, path);
+            }
+            else
+            {
+                OnLoaded(new LoadedEventArgs<List<Track>>(e.Error));
+            }
+        }
+
+        void LoadTrackList(string xml, string prefix)
+        {
+            var tracks = new List<Track>();
+            var xdoc = XDocument.Parse(xml);
+            foreach (var file in xdoc.Element("files").Elements("file"))
+            {
+                string audioFileName = file.Attribute("name").Value;
+                if (audioFileName.EndsWith(".mp3", StringComparison.OrdinalIgnoreCase))
+                {
+                    var t = new Track(from c in defaultCriteria select new Rating(c));
+                    var titleElement = file.Element("title");
+                    if (titleElement != null)
+                    {
+                        string title = file.Element("title").Value;
+                        string sep = " - ";
+                        int index = title.IndexOf(sep);
+                        if (index == -1)
+                        {
+                            sep = "-";
+                            index = title.IndexOf(sep);
+                        }
+                        t.Author = index == -1 ? "Unknown" : title.Substring(0, index);
+                        t.Title = index == -1 ? title : title.Substring(index + sep.Length);
+                        t.Title = t.Title.Trim();
+                    }
+                    else
+                    {
+                        // work it out from the MP3 name
+                        string nameOnly = audioFileName.Substring(0, audioFileName.Length - 4);
+                        int index = nameOnly.IndexOf("-");
+                        t.Author = index == -1 ? "Unknown" : nameOnly.Substring(0, index);
+                        t.Title = index == -1 ? nameOnly : nameOnly.Substring(index + 1);
+                    }
+                    t.Url = prefix + audioFileName;
+                    tracks.Add(t);
+                }
+            }
+            Shuffle(tracks, new Random());
+            OnLoaded(new LoadedEventArgs<List<Track>> (tracks));
+        }
+
+        public static void Shuffle<T>(IList<T> list, Random rng)
+        {
+            // Note i > 0 to avoid final pointless iteration
+            for (int i = list.Count - 1; i > 0; i--)
+            {
+                // Swap element "i" with a random earlier element it (or itself)
+                int swapIndex = rng.Next(i + 1);
+                T tmp = list[i];
+                list[i] = list[swapIndex];
+                list[swapIndex] = tmp;
+            }
+        }
+
+
+        protected virtual void OnLoaded(LoadedEventArgs<List<Track>>  e)
+        {
+            EventHandler<LoadedEventArgs<List<Track>>> handler = Loaded;
+            if (handler != null) handler(this, e);
+        }
+    }
+
+}

File MusicRater/Persistence/RatingsRepository.cs

             
             var tracksElement = new XElement("Tracks", trackNodes);
             var contestElement = new XElement("Contest",
-                                              new XElement("LoadUrl", contest.LoadUrl),
+                                              new XElement("TrackListUrl", contest.TrackListUrl),
                                               new XElement("FileName", contest.FileName),
                                               new XElement("Name", contest.Name),
                                               tracksElement);
             }
             using (var reader = isolatedStore.OpenFile(fileName))
             {
-                var contest = new Contest(fileName);
+                var contestInfo = new ContestInfo() {IsoStoreFileName = fileName};
+                var contest = new Contest(contestInfo);
                 var doc = XDocument.Load(reader);
-                foreach (var trackNode in doc.Element("Tracks").Elements("Track"))
+                foreach (var trackNode in doc.Element("Contest").Element("Tracks").Elements("Track"))
                 {
                     var track = CreateTrackFromNode(trackNode, criteria);
                     contest.Tracks.Add(track);
                 if (contestElement != null)
                 {
 
-                    var loadUrlElement = doc.Element("LoadUrl");
+                    var loadUrlElement = doc.Element("TrackListUrl");
                     if (loadUrlElement != null)
-                        contest.LoadUrl = loadUrlElement.Value;
+                        contestInfo.TrackListUrl = loadUrlElement.Value;
 
                     var nameElement = doc.Element("Name");
                     if (nameElement != null)
-                        contest.Name = nameElement.Value;
+                        contestInfo.Name = nameElement.Value;
                 }
                 return contest;
             }

File MusicRater/ViewModels/MainPageViewModel.cs

             //"http://www.archive.org/download/KvrOsc35Diva/KvrOsc35Diva_files.xml"
             //this.contest = new Contest("KVR-OSC-46.xml", "http://www.archive.org/download/KvrOsc46TripleCheese/KvrOsc46TripleCheese_files.xml");
 
-            var kvrLoader = new KvrContestLoader("KVR-OSC-46.xml", "http://www.archive.org/download/KvrOsc46TripleCheese/KvrOsc46TripleCheese_files.xml");
-            var isoLoader = new IsolatedStoreContestLoader("KVR-OSC-46.xml", isoStore);
-            IContestLoader loader = new CombinedContestLoader(kvrLoader, isoLoader);
+            var contestInfo = new ContestInfo()
+                                  {
+                                      IsoStoreFileName = "KVR-OSC-46.xml",
+                                      TrackListUrl = "http://www.archive.org/download/KvrOsc46TripleCheese/KvrOsc46TripleCheese_files.xml",
+                                      Name = "OSC 46 (Triple Cheese)"
+                                  };
+            var defaultCriteria = new[]
+                                      {
+                                          new Criteria("Songwriting"),
+                                          new Criteria("Sound Design"),
+                                          new Criteria("Production")
+                                      };
+
+            var loader = new ContestLoader(contestInfo, isoStore, defaultCriteria);
             loader.Loaded += OnContestLoaded;
             this.IsLoading = true;
             loader.BeginLoad();
             RaisePropertyChanged("DownloadProgress");
         }
 
-        void OnContestLoaded(object sender, ContestLoadedEventArgs e)
+        void OnContestLoaded(object sender, LoadedEventArgs<Contest> e)
         {
             if (e.Error != null)
             {
             }
             else
             {
-                this.contest = e.Contest;
-                foreach (var t in e.Contest.Tracks)
+                this.contest = e.Result;
+                foreach (var t in e.Result.Tracks)
                 {
                     var trackViewModel = new TrackViewModel(t);
                     trackViewModel.AnonymousMode = this.AnonCommand.AnonymousMode;

File MusicRater/ViewModels/OpenContestWindowViewModel.cs

             }
         }
 
+
         private static readonly List<string> knownContests = new List<string>()
             {
                 "http://www.archive.org/download/KvrOsc28TyrellN6/KvrOsc28TyrellN6_files.xml",
             };
 
     }
+
+
+
 }