コード例 #1
0
        public HttpResponseMessage getResponse(HttpListenerRequest req)
        {
            if (req.AcceptTypes == null)
            {
                //TODO: topkek return new HttpResponseMessage(HttpStatusCode.NotAcceptable);
            }

            var msg = new HttpResponseMessage();

            var ruri = req.RawUrl;

            if (ruri.Contains("?"))
            {
                ruri = ruri.Remove(ruri.IndexOf("?"));
            }
            var locList = ruri.Split('/').ToList();

            locList.RemoveAll(a => a == "");

            msg.StatusCode = HttpStatusCode.OK;
            LineLog.Debug("rendering response...");
            return(this.Render(req, locList.ToArray()));

            //<html><head><script src='/script.js'></script></head><body><button id='button1' style='width:50px' onclick='javascript:startProgress();'>Start</button></body></html>
        }
コード例 #2
0
ファイル: Program.Saves.cs プロジェクト: cooye/RuneManager
        public static LoadSaveResult SaveLoadouts(string filename = "loads.json")
        {
            LineLog.Debug($"Saving loads to {filename}");

            if (Loads.Count > 0)
            {
                try
                {
                    // keep a single recent backup
                    if (File.Exists(filename))
                    {
                        File.Copy(filename, filename + ".backup", true);
                    }
                    var str = JsonConvert.SerializeObject(Loads, Formatting.Indented);
                    File.WriteAllText(filename, str);
                    return(LoadSaveResult.Success);
                }
                catch (Exception e)
                {
                    LineLog.Error($"Error while saving loads {e.GetType()}", e);
                    throw;
                }
            }
            return(LoadSaveResult.EmptyFile);
        }
コード例 #3
0
ファイル: Program.Saves.cs プロジェクト: cooye/RuneManager
        public static LoadSaveResult LoadBuilds(string filename = "builds.json")
        {
            if (!File.Exists(filename))
            {
                LineLog.Error($"{filename} wasn't found.");
                return(LoadSaveResult.FileNotFound);
            }
            LineLog.Debug($"Loading {filename} as builds.");
            var bstr = File.ReadAllText(filename);

            return(LoadBuildData(bstr));
        }
コード例 #4
0
ファイル: Program.Saves.cs プロジェクト: cooye/RuneManager
        public static LoadSaveResult SaveBuilds(string filename = "builds.json")
        {
            LineLog.Debug($"Saving builds to {filename}");
            // TODO: fix this mess
            foreach (Build bb in Builds)
            {
                if (bb.Mon != null && bb.Mon.FullName != "Missingno")
                {
                    if (!bb.DownloadAwake || (Program.Data.GetMonster(bb.Mon.FullName) != null && Program.Data.GetMonster(bb.Mon.FullName).FullName != "Missingno"))
                    {
                        bb.MonName = bb.Mon.FullName;
                        bb.MonId   = bb.Mon.Id;
                    }
                    else
                    {
                        if (Program.Data.GetMonster(bb.Mon.Id).FullName != "Missingno")
                        {
                            bb.MonId   = bb.Mon.Id;
                            bb.MonName = Program.Data.GetMonster(bb.Mon.Id).FullName;
                        }
                    }
                }
            }

            // only write if there are builds, may save some files
            if (Program.Builds.Count > 0)
            {
                try
                {
                    // keep a single recent backup
                    if (File.Exists(filename))
                    {
                        File.Copy(filename, filename + ".backup", true);
                    }
                    var str = JsonConvert.SerializeObject(Program.Builds, Formatting.Indented);
                    File.WriteAllText(filename, str);
                    return(LoadSaveResult.Success);
                }
                catch (Exception e)
                {
                    LineLog.Error($"Error while saving builds {e.GetType()}", e);
                    throw;
                    //MessageBox.Show(e.ToString());
                }
            }
            return(LoadSaveResult.Failure);
        }
コード例 #5
0
        /// <summary>
        /// Dispatches a thread to listen for the incoming Remote App connection
        /// </summary>
        public void Start()
        {
            try {
                try {
                    //if (!NetAclChecker.HasFirewall("WebSocketMulti", true, true, true, 80))
                    //	NetAclChecker.AddFirewall("WebSocketMulti", true, true, true, 80);
                    //if (!NetAclChecker.HasFirewall("WebSocketMulti", true, true, true, 81))
                    //	NetAclChecker.AddFirewall("WebSocketMulti", true, true, true, 81);

                    NetAclChecker.AddAddress($"http://*:7676/");


                    listener = new HttpListener();
                    listener.Prefixes.Add("http://*:7676/");
                    listener.Start();
                }
                catch {
                    LineLog.Error("Failed to bind to *, binding to localhost");
                    listener = new HttpListener();
                    listener.Prefixes.Add("http://localhost:7676/");
                    listener.Start();
                }

                LineLog.Info("Server is listening on " + listener.Prefixes.First());
                isRunning = true;
            }
            catch (Exception e) {
                LineLog.Error("Failed to start server", e);
                throw;
            }

            Task.Factory.StartNew(() => {
                try {
                    while (isRunning)
                    {
                        //LineLog.Info("Waiting for a connection...");
                        var context = listener.GetContext();
                        new Thread(() => RemoteManageLoop(context)).Start();
                    }
                }
                catch (Exception e) {
                    LineLog.Error("Failed while running server", e);
                }
                isRunning = false;
            }, TaskCreationOptions.LongRunning);
        }
コード例 #6
0
ファイル: Program.Saves.cs プロジェクト: cooye/RuneManager
        public static LoadSaveResult SaveGoals(string filename = "goals.json")
        {
            LineLog.Debug($"Saving loads to {filename}");

            try
            {
                // keep a single recent backup
                var str = JsonConvert.SerializeObject(Goals, Formatting.Indented);
                File.WriteAllText(filename, str);
                return(LoadSaveResult.Success);
            }
            catch (Exception e)
            {
                LineLog.Error($"Error while saving loads {e.GetType()}", e);
                throw;
            }
        }
コード例 #7
0
ファイル: Program.Saves.cs プロジェクト: cooye/RuneManager
        public static LoadSaveResult LoadLoadouts(string filename = "loads.json")
        {
            try
            {
                string text   = File.ReadAllText(filename);
                var    lloads = JsonConvert.DeserializeObject <Loadout[]>(text);
                Loads.Clear();

                foreach (var load in lloads)
                {
                    if (load.RuneIDs != null)
                    {
                        for (int i = 0; i < 6; i++)
                        {
                            var ids = load.RuneIDs[i];
                            load.Runes[i] = Program.Data.Runes.FirstOrDefault(r => r.Id == ids);
                            if (load.Runes[i] != null)
                            {
                                load.Runes[i].UsedInBuild = true;
                                if (load.HasManageStats)
                                {
                                    foreach (var ms in load.ManageStats[i])
                                    {
                                        load.Runes[i].ManageStats.AddOrUpdate(ms.Key, ms.Value, (s, d) => ms.Value);
                                    }
                                }
                            }
                        }
                    }
                    load.Shrines = Data.Shrines;
                    Loads.Add(load);
                }
                return(LoadSaveResult.Success);
            }
            catch (Exception e)
            {
                LineLog.Error($"Error while loading loads {e.GetType()}", e);
                //MessageBox.Show("Error occurred loading Save JSON.\r\n" + e.GetType() + "\r\nInformation is saved to error_save.txt");
                File.WriteAllText("error_loads.txt", e.ToString());
                throw;
            }
        }
コード例 #8
0
ファイル: Program.Saves.cs プロジェクト: cooye/RuneManager
 public static LoadSaveResult LoadGoals(string filename = "goals.json")
 {
     try
     {
         LineLog.Debug("Loading goals");
         if (File.Exists(filename))
         {
             string text = File.ReadAllText(filename);
             Goals = JsonConvert.DeserializeObject <Goals>(text);
         }
         else
         {
             Goals = new Goals();
         }
         return(LoadSaveResult.Success);
     }
     catch (Exception e)
     {
         LineLog.Error($"Error while loading goals {e.GetType()}", e);
         File.WriteAllText("error_goals.txt", e.ToString());
         throw;
     }
 }
コード例 #9
0
        public async void RemoteManageLoop(HttpListenerContext context)
        {
            try {
                LineLog.Debug("serving: " + context.Request.RawUrl);
                var req  = context.Request;
                var resp = context.Response;

                var msg = getResponse(req);
                resp.StatusCode = (int)msg.StatusCode;
                LineLog.Debug("returning: " + resp.StatusCode);
                foreach (var h in msg.Headers)
                {
                    foreach (var v in h.Value)
                    {
                        resp.Headers.Add(h.Key, v);
                    }
                }

                if (resp.StatusCode != 303)
                {
                    using (var output = resp.OutputStream) {
                        byte[] outBytes = Encoding.UTF8.GetBytes("Critical Failure");
                        bool   expires  = false;
                        if (msg.Content is StringContent)
                        {
                            var    qw = msg.Content as StringContent;
                            string qq = await qw.ReadAsStringAsync();

                            resp.ContentType = mimeTypes.Where(t => req.Url.AbsolutePath.EndsWith(t.Key)).FirstOrDefault().Value;
                            if (resp.ContentType == null)
                            {
                                resp.ContentType = "text/html";                                                 // Default to HTML
                            }
                            outBytes = Encoding.UTF8.GetBytes(qq);
                        }
                        else if (msg.Content is FileContent)
                        {
                            var qw = msg.Content as FileContent;
                            resp.ContentType = qw.Type;
                            if (resp.ContentType == null)
                            {
                                resp.ContentType = "application/octet-stream";                                  // Should always be set, but bin just incase
                            }
                            //resp.Headers.Add("Content-Disposition", $"attachment; filename=\"{qw.FileName}\"");
                            outBytes = await qw.ReadAsByteArrayAsync();
                        }
                        else if (msg.Content is ByteArrayContent)
                        {
                            var qw = msg.Content as ByteArrayContent;
                            resp.ContentType = mimeTypes.Where(t => req.Url.AbsolutePath.EndsWith(t.Key)).FirstOrDefault().Value;
                            if (resp.ContentType == null)
                            {
                                resp.ContentType = "application/octet-stream";                                  // Default to binary
                            }
                            outBytes = await qw.ReadAsByteArrayAsync();
                        }
                        else if (msg.Content is StreamContent)
                        {
                            var qw = msg.Content as StreamContent;
                            using (var ms = new MemoryStream()) {
                                var stream = await qw.ReadAsStreamAsync();

                                stream.CopyTo(ms);
                                //resp.ContentType = "application/octet-stream"
                                outBytes = ms.ToArray();
                            }
                        }
                        //resp.Headers.Add("Content-language", "en-au");
                        resp.Headers.Add("Access-Control-Allow-Origin: *");
                        resp.Headers.Add("Access-Control-Allow-Methods: *");

                        if (expires)
                        {
                            resp.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate");
                            resp.Headers.Add("Pragma", "no-cache");
                            resp.Headers.Add("Expires", "Wed, 16 Jul 1969 13:32:00 UTC");
                        }

                        if ((outBytes.Length > 0) && (resp.ContentType != "image/png"))                             // Don't compress empty responses or compressed file types
                        {
                            var enc = req.Headers.GetValues("Accept-Encoding");

                            if (enc?.Contains("gzip") ?? false)
                            {
                                using (MemoryStream ms = new MemoryStream())
                                    using (System.IO.Compression.GZipStream gs = new System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Compress)) {
                                        gs.Write(outBytes, 0, outBytes.Length);
                                        gs.Flush();
                                        gs.Close();                                     // https://stackoverflow.com/questions/3722192/how-do-i-use-gzipstream-with-system-io-memorystream#comment3929538_3722263
                                        ms.Flush();
                                        outBytes = ms.ToArray();
                                    }
                                resp.Headers.Add("Content-Encoding", "gzip");
                            }
                            else if (enc?.Any(a => a.ToLowerInvariant() == "deflate") ?? false)
                            {
                                using (MemoryStream ms = new MemoryStream()) {
                                    using (System.IO.Compression.DeflateStream ds = new System.IO.Compression.DeflateStream(ms, System.IO.Compression.CompressionMode.Compress)) {
                                        ds.Write(outBytes, 0, outBytes.Length);
                                        ds.Flush();
                                    }
                                    ms.Flush();
                                    outBytes = ms.ToArray();
                                }
                                resp.Headers.Add("Content-Encoding", "deflate");
                            }
                        }

                        resp.ContentLength64 = outBytes.Length;
                        try {
                            output.Write(outBytes, 0, outBytes.Length);
                        }
                        catch (Exception ex) {
                            Program.LineLog.Error("Failed to write " + ex.GetType().ToString() + " " + ex.Message);
                        }
                    }
                }
                else
                {
                    resp.OutputStream.Close();
                }
            }
            catch (Exception e) {
                LineLog.Error("Something went wrong.", e);
                var resp = context.Response;
                resp.StatusCode = 500;
                using (var output = resp.OutputStream) {
                    byte[] outBytes = Encoding.UTF8.GetBytes(e.GetType() + ": " + e.Message);
                    resp.ContentLength64 = outBytes.Length;
                    try {
                        output.Write(outBytes, 0, outBytes.Length);
                    }
                    catch (Exception ex) {
                        Program.LineLog.Error("Failed to write " + ex.GetType().ToString() + " " + ex.Message);
                    }
                }
            }
        }
コード例 #10
0
        // TODO: pull more of the App-dependant stuff out
        private static void runBuild(Build build, Save data, BuildSettings bSettings)
        {
            try
            {
                if (build == null)
                {
                    LineLog.Info("Build is null");
                    return;
                }
                // TODO: show this somewhere
                if (currentBuild != null)
                {
                    throw new InvalidOperationException("Already running a build");
                }
                if (build.IsRunning)
                {
                    throw new InvalidOperationException("This build is already running");
                }
                currentBuild = build;

                LineLog.Info("Starting watch " + build.ID + " " + build.MonName);

                Stopwatch buildTime = Stopwatch.StartNew();

                // TODO: get builds to use the settings directly
                build.RunesUseEquipped     = bSettings.RunesUseEquipped;
                build.RunesUseLocked       = bSettings.RunesUseLocked;
                build.BuildGenerate        = bSettings.BuildGenerate;
                build.BuildTake            = bSettings.BuildTake;
                build.BuildTimeout         = bSettings.BuildTimeout;
                build.Shrines              = bSettings.Shrines;
                build.BuildDumpBads        = bSettings.BuildDumpBads;
                build.BuildSaveStats       = bSettings.BuildSaveStats;
                build.BuildGoodRunes       = bSettings.BuildGoodRunes;
                build.RunesOnlyFillEmpty   = bSettings.RunesOnlyFillEmpty;
                build.RunesDropHalfSetStat = bSettings.RunesDropHalfSetStat;
                build.IgnoreLess5          = bSettings.IgnoreLess5;


                BuildsPrintTo?.Invoke(null, PrintToEventArgs.GetEvent(build, "Runes..."));
                if (build.Type == BuildType.Link)
                {
                    build.CopyFrom(build.LinkBuild);
                }

                // unlock runes on current loadout (if present)
                var load = Loads.FirstOrDefault(l => l.BuildID == build.ID);
                if (load != null)
                {
                    load.Unlock();
                }

                build.GenRunes(data);

                #region Check enough runes
                string nR = "";
                for (int i = 0; i < build.Runes.Length; i++)
                {
                    if (build.Runes[i] != null && build.Runes[i].Length == 0)
                    {
                        nR += (i + 1) + " ";
                    }
                }

                if (nR != "")
                {
                    BuildsPrintTo?.Invoke(null, PrintToEventArgs.GetEvent(build, ":( " + nR + "Runes"));
                    return;
                }
                #endregion

                build.BuildPrintTo += BuildsPrintTo;
                build.BuildProgTo  += BuildsProgressTo;

                EventHandler <ProgToEventArgs> qw = (bq, s) => {
                    if (runToken.IsCancellationRequested)
                    {
                        build.Cancel();
                    }
                };
                build.BuildProgTo += qw;

                var result = build.GenBuilds();

                buildTime.Stop();
                build.Time = buildTime.ElapsedMilliseconds;
                LineLog.Info("Stopping watch " + build.ID + " " + build.MonName + " @ " + buildTime.ElapsedMilliseconds);

                if (build.Best != null)
                {
                    BuildsPrintTo?.Invoke(null, PrintToEventArgs.GetEvent(build, "Best"));

                    build.Best.Current.BuildID = build.ID;

                    #region Get the rune diff
                    build.Best.Current.Lock();
                    build.Best.Current.RecountDiff(build.Mon.Id);
                    #endregion

                    //currentBuild = null;
                    build.Best.Current.Time = build.Time;

                    var dmon = Program.Data.GetMonster(build.Best.Id);

                    var dmonld = dmon.Current.Leader;
                    var dmonsh = dmon.Current.Shrines;
                    dmon.Current.Leader  = build.Best.Current.Leader;
                    dmon.Current.Shrines = build.Best.Current.Shrines;
                    var dmonfl = dmon.Current.FakeLevel;
                    var dmonps = dmon.Current.PredictSubs;
                    dmon.Current.FakeLevel   = build.Best.Current.FakeLevel;
                    dmon.Current.PredictSubs = build.Best.Current.PredictSubs;
                    var dmonbf = dmon.Current.Buffs;
                    dmon.Current.Buffs = build.Best.Current.Buffs;

                    var ds = build.CalcScore(dmon.GetStats());
                    var cs = build.CalcScore(build.Best.Current.GetStats(build.Best));
                    build.Best.Current.DeltaPoints = cs - ds;

                    dmon.Current.Leader      = dmonld;
                    dmon.Current.Shrines     = dmonsh;
                    dmon.Current.FakeLevel   = dmonfl;
                    dmon.Current.PredictSubs = dmonps;
                    dmon.Current.Buffs       = dmonbf;

                    Loads.Add(build.Best.Current);

                    // if we are on the hunt of good runes.
                    if (GoodRunes && bSettings.BuildSaveStats && build.Type != BuildType.Lock)
                    {
                        var theBest = build.Best;
                        int count   = 0;
                        // we must progressively ban more runes from the build to find second-place runes.
                        //GenDeep(b, 0, printTo, ref count);
                        RunBanned(build, ++count, theBest.Current.Runes.Where(r => r.Slot % 2 != 0).Select(r => r.Id).ToArray());
                        RunBanned(build, ++count, theBest.Current.Runes.Where(r => r.Slot % 2 == 0).Select(r => r.Id).ToArray());
                        RunBanned(build, ++count, theBest.Current.Runes.Select(r => r.Id).ToArray());

                        // after messing all that shit up
                        build.Best = theBest;
                    }

                    #region Save Build stats

                    /* TODO: put Excel on Program */
                    if (bSettings.BuildSaveStats && build.Type != BuildType.Lock)
                    {
                        BuildsPrintTo?.Invoke(null, PrintToEventArgs.GetEvent(build, "Excel"));
                        RuneSheet.StatsExcelBuild(build, build.Mon, build.Best.Current, true);
                    }

                    BuildsPrintTo?.Invoke(null, PrintToEventArgs.GetEvent(build, "Clean"));
                    // clean up for GC
                    if (build.BuildUsage != null)
                    {
                        build.BuildUsage.loads.Clear();
                    }
                    if (build.RuneUsage != null)
                    {
                        build.RuneUsage.runesGood.Clear();
                        build.RuneUsage.runesUsed.Clear();
                    }
                    build.RuneUsage  = null;
                    build.BuildUsage = null;
                    /**/
                    #endregion
                }

                build.BuildPrintTo -= BuildsPrintTo;
                build.BuildProgTo  -= qw;
                build.BuildProgTo  -= BuildsProgressTo;

                //if (plsDie)
                //    printTo?.Invoke("Canned");
                //else
                if (build.Best != null)
                {
                    BuildsPrintTo?.Invoke(null, PrintToEventArgs.GetEvent(build, "Done"));
                }
                else
                {
                    BuildsPrintTo?.Invoke(null, PrintToEventArgs.GetEvent(build, result + " :("));
                }

                LineLog.Info("Cleaning up");
                //b.isRun = false;
                //currentBuild = null;
            }
            catch (Exception e)
            {
                LineLog.Error("Error during build " + build.ID + " " + e.Message + Environment.NewLine + e.StackTrace);
            }
            finally
            {
                currentBuild = null;
                LineLog.Info("Cleaned");
            }
        }

        private static void RunBanned(Build b, int c, params ulong[] doneIds)
        {
            LineLog.Info("Running ban");
            try
            {
                b.BanEmTemp(doneIds);

                b.RunesUseLocked       = false;
                b.RunesUseEquipped     = Program.Settings.UseEquipped;
                b.BuildSaveStats       = true;
                b.RunesOnlyFillEmpty   = Program.FillRunes;
                b.BuildGoodRunes       = GoodRunes;
                b.RunesDropHalfSetStat = Program.GoFast;
                b.IgnoreLess5          = Program.Settings.IgnoreLess5;
                b.GenRunes(Program.Data);

                b.BuildTimeout  = 0;
                b.BuildTake     = 0;
                b.BuildGenerate = 0;
                b.BuildDumpBads = true;
                var result = b.GenBuilds($"{c} ");
                b.BuildGoodRunes = false;
                LineLog.Info("ran ban with result: " + result);
            }
            catch (Exception ex)
            {
                LineLog.Error("Running ban failed ", ex);
            }
            finally
            {
                b.BanEmTemp(new ulong[] { });
                b.BuildSaveStats = false;
                b.GenRunes(Program.Data);
                LineLog.Info("Ban finished");
            }
        }

        public static void RunBuilds(bool skipLoaded, int runTo = -1)
        {
            if (Program.Data == null)
            {
                return;
            }

            if (isRunning)
            {
                if (runTask != null && runTask.Status != TaskStatus.Running)
                {
                    throw new Exception("Already running builds!");
                }
                else
                {
                    runSource.Cancel();
                    return;
                }
            }
            isRunning = true;

            try
            {
                if (runTask != null && runTask.Status == TaskStatus.Running)
                {
                    runSource.Cancel();
                    //if (currentBuild != null)
                    //   currentBuild.isRun = false;
                    //plsDie = true;
                    isRunning = false;
                    return;
                }
                //plsDie = false;

                List <int> loady = new List <int>();

                if (!skipLoaded)
                {
                    ClearLoadouts();
                    foreach (var r in Program.Data.Runes)
                    {
                        r.ManageStats.AddOrUpdate("buildScoreIn", 0, (k, v) => 0);
                        r.ManageStats.AddOrUpdate("buildScoreTotal", 0, (k, v) => 0);
                    }
                }

                List <Build> toRun = new List <Build>();
                foreach (var build in Builds.OrderBy(b => b.Priority))
                {
                    if ((!skipLoaded || !Loads.Any(l => l.BuildID == build.ID)) && (runTo == -1 || build.Priority <= runTo))
                    {
                        toRun.Add(build);
                    }
                }

                /*
                 * bool collect = true;
                 * int newPri = 1;
                 * // collect the builds
                 * List<ListViewItem> list5 = new List<ListViewItem>();
                 * foreach (ListViewItem li in buildList.Items)
                 * {
                 *  li.SubItems[0].Text = newPri.ToString();
                 *  (li.Tag as Build).priority = newPri++;
                 *
                 *  if (loady.Contains((li.Tag as Build).ID))
                 *      continue;
                 *
                 *  if ((li.Tag as Build).ID == runTo)
                 *      collect = false;
                 *
                 *  if (collect)
                 *      list5.Add(li);
                 *
                 *  li.SubItems[3].Text = "";
                 * }
                 */

                runSource = new CancellationTokenSource();
                runToken  = runSource.Token;
                runTask   = Task.Factory.StartNew(() => {
                    if (Program.Data.Runes != null && !skipLoaded)
                    {
                        foreach (Rune r in Program.Data.Runes)
                        {
                            r.Swapped = false;
                            r.ResetStats();
                        }
                    }

                    foreach (Build bbb in toRun)
                    {
                        runBuild(bbb, Program.Settings.MakeStats);
                        if (runToken.IsCancellationRequested || bbb.Best == null)
                        {
                            break;
                        }
                    }

                    if (!runToken.IsCancellationRequested && Program.Settings.MakeStats)
                    {
                        if (!skipLoaded)
                        {
                            Program.RuneSheet.StatsExcelRunes(true);
                        }
                        try
                        {
                            Program.RuneSheet.StatsExcelSave(true);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex);
                        }
                    }
                    isRunning = false;
                }, runSource.Token);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message + Environment.NewLine + e.StackTrace, e.GetType().ToString());
            }
        }
コード例 #11
0
ファイル: Program.Saves.cs プロジェクト: cooye/RuneManager
        public static void SanitizeBuilds()
        {
            LineLog.Debug("processing builds");
            int current_pri = 1;

            foreach (Build b in Program.Builds.OrderBy(bu => bu.Priority))
            {
                int id = b.ID;
                if (b.ID == 0 || Program.Builds.Where(bu => bu != b).Select(bu => bu.ID).Any(bid => bid == b.ID))
                {
                    //id = buildList.Items.Count + 1;
                    id = 1;
                    while (Program.Builds.Any(bu => bu.ID == id))
                    {
                        id++;
                    }

                    foreach (var lb in Program.Builds.Where(bu => bu.LinkId == b.ID))
                    {
                        lb.LinkId = id;
                    }

                    b.ID = id;
                }
                if (b.Type == BuildType.Lock)
                {
                    b.Priority = 0;
                }
                else
                {
                    b.Priority = current_pri++;
                }

                // make sure bad things are removed
                foreach (var ftab in b.RuneFilters)
                {
                    foreach (var filter in ftab.Value)
                    {
                        if (filter.Key == "SPD")
                        {
                            filter.Value.Percent = null;
                        }
                        if (filter.Key == "ACC" || filter.Key == "RES" || filter.Key == "CR" || filter.Key == "CD")
                        {
                            filter.Value.Flat = null;
                        }
                    }
                }

                // upgrade builds, hopefully
                while (b.VERSIONNUM < Create.VERSIONNUM)
                {
                    switch (b.VERSIONNUM)
                    {
                    case 0:     // unversioned to 1
                        b.Threshold = b.Maximum;
                        b.Maximum   = new Stats();
                        break;

                    case 1:
                        foreach (var tabN in b.RuneScoring.Keys.ToArray())
                        {
                            var tab = b.RuneScoring[tabN];
                            if (tab.Type == FilterType.SumN)
                            {
                                tab.Count           = (int?)(tab.Value);
                                tab.Value           = null;
                                b.RuneScoring[tabN] = tab;
                            }
                        }
                        break;

                    case 2:
                        b.AutoRuneAmount = Build.AutoRuneAmountDefault;
                        break;
                    }
                    b.VERSIONNUM++;
                }
            }
        }