예제 #1
0
        private void MenuFileClose_Click(object sender, EventArgs e)
        {
            log.Debug("EditorForm::MenuFileClose_Click() {");

            if (hasUnsavedChanges)
            {
                try
                {
                    DialogResult result = MessageBox.Show("There are unsaved changes. Save?", "Information",
                                                          MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);

                    switch (result)
                    {
                    case DialogResult.Yes:
                        if (!SaveToFile())
                        {
                            log.Debug("EditorForm::MenuFileClose_Click() } // cancelled (save existing)");
                            return;
                        }
                        break;

                    case DialogResult.No:
                        break;

                    default:
                    case DialogResult.Cancel:
                        log.Debug("EditorForm::MenuFileClose_Click() } // cancelled (save existing)");
                        return;
                    }
                }
                catch (Exception ex)
                {
                    log.Error("Failed to close scoreboard: Failed to save existing scoreboard.", ex);
                    MessageBox.Show("Failed to close scoreboard: Failed to save existing scoreboard: " + ex.Message, "Error",
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }

            try
            {
                scoreboard        = null;
                hasUnsavedChanges = false;
                UpdateScores();
                UpdateControls();
            }
            catch (Exception ex)
            {
                log.Error("Failed to close scoreboard.", ex);
                MessageBox.Show("Failed to close scoreboard: " + ex.Message, "Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            log.Debug("EditorForm::MenuFileClose_Click() }");
        }
예제 #2
0
        public static void SaveToFile(Scoreboard scoreboard, Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentException("Failed to save scoreboard to file: Argument 'stream' is null.");
            }
            if (scoreboard == null)
            {
                throw new ArgumentException("Failed to save scoreboard to file: Argument 'scoreboard' is null.");
            }

            using (TextWriter writer = new StreamWriter(stream, Encoding.UTF8))
            {
                string[] teams      = scoreboard.Teams;
                string[] categories = scoreboard.Categories;
                decimal[,] scores = scoreboard.Scores;

                writer.Write(scoreboard.ExpectedNumberOfCategories + "\\" + scoreboard.ExpectedNumberOfTeams);

                foreach (string team in teams)
                {
                    writer.Write(",\"");
                    writer.Write(team);
                    writer.Write("\"");
                }
                writer.Write("\n");

                for (int i = 0; i < categories.Length; ++i)
                {
                    writer.Write("\"");
                    writer.Write(categories[i]);
                    writer.Write("\"");

                    for (int j = 0; j < teams.Length; ++j)
                    {
                        writer.Write(",");
                        writer.Write(scores[j, i].ToString(CultureInfo.InvariantCulture));
                    }
                    writer.Write("\n");
                }
            }
        }
예제 #3
0
        public static Scoreboard LoadFromFile(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentException("Failed to load scoreboard from file: Argument 'stream' is null.");
            }

            ScoreboardFile file;

            using (StreamReader reader = new StreamReader(stream))
            {
                file = JsonConvert.DeserializeObject <ScoreboardFile>(reader.ReadToEnd());
            }

            if (file.ExpectedNumberOfTeams < file.Teams.Length || file.Teams.Length != file.Scores.GetLength(0))
            {
                throw new ArgumentException("Failed to load scoreboard from file: Invalid number of teams.");
            }
            if (file.ExpectedNumberOfCategories < file.Categories.Length || file.Categories.Length != file.Scores.GetLength(1))
            {
                throw new ArgumentException("Failed to load scoreboard from file: Invalid number of categories.");
            }

            Scoreboard scoreboard = new Scoreboard(file.ExpectedNumberOfTeams, file.ExpectedNumberOfCategories);

            for (int i = 0; i < file.Teams.Length; ++i)
            {
                scoreboard.AddTeam(file.Teams[i]);
            }
            decimal[] scores = new decimal[file.Teams.Length];
            for (int i = 0; i < file.Categories.Length; ++i)
            {
                for (int j = file.Teams.Length - 1; j >= 0; --j)
                {
                    scores[j] = file.Scores[j, i];
                }
                scoreboard.AddCategory(file.Categories[i], scores);
            }

            return(scoreboard);
        }
예제 #4
0
        private void LoadFromFile()
        {
            log.Debug("EditorForm::LoadFromFile() {");

            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.InitialDirectory = string.IsNullOrEmpty(fileName) ? Environment.SpecialFolder.MyDocuments.ToString() : fileName;
                openFileDialog.Filter           = "CSV files (*.csv)|*.csv|JSON files (*.json)|*.json";
                openFileDialog.FilterIndex      = 1;
                openFileDialog.RestoreDirectory = true;

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    fileName = openFileDialog.FileName;
                    switch (Path.GetExtension(fileName))
                    {
                    case ".csv":
                        scoreboard = CsvHandler.LoadFromFile(openFileDialog.OpenFile());
                        break;

                    case ".json":
                        scoreboard = JsonHandler.LoadFromFile(openFileDialog.OpenFile());
                        break;

                    default:
                        throw new ArgumentException("Unknown file format: '" + Path.GetExtension(fileName) + "'.");
                    }
                    hasUnsavedChanges = false;
                    NumericInputAnimationLength.Value = GetSuggestedAnimationLength();
                    UpdateScores();
                    UpdateControls();
                }
            }

            log.Debug("EditorForm::LoadFromFile() }");
        }
예제 #5
0
        public static Scoreboard LoadFromFile(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentException("Failed to load scoreboard from file: Argument 'stream' is null.");
            }

            using (TextReader reader = new StreamReader(stream))
            {
                string buffer = reader.ReadToEnd();

                string[][] rows = CsvParser.Parse(buffer, true, out string[] header);

                string[] dimens = header[0].Split('\\');

                if (!int.TryParse(dimens[0], out int expectedNumberOfCategories))
                {
                    throw new ArgumentException("Failed to load scoreboard fom file: Invalid number of categories in cell (0,0).");
                }
                if (!int.TryParse(dimens[1], out int expectedNumberOfTeams))
                {
                    throw new ArgumentException("Failed to load scoreboard fom file: Invalid number of teams in cell (0,0).");
                }
                // first column contains category names
                if (header.Length > expectedNumberOfTeams + 1)
                {
                    throw new ArgumentException("Failed to load scoreboard fom file: Invalid number of columns in header.");
                }
                // header (row containing team names) is separate
                if (rows.Length > expectedNumberOfCategories)
                {
                    throw new ArgumentException("Failed to load scoreboard fom file: Invalid number of rows.");
                }
                for (int i = rows.Length - 1; i >= 0; --i)
                {
                    if (rows[i].Length != header.Length)
                    {
                        throw new ArgumentException("Failed to load scoreboard fom file: Invalid number columns in row " + (i + 1) + ".");
                    }
                }

                Scoreboard scoreboard = new Scoreboard(expectedNumberOfTeams, expectedNumberOfCategories);

                for (int i = 1; i < header.Length; ++i)
                {
                    scoreboard.AddTeam(header[i]);
                }
                decimal[] scores = new decimal[header.Length - 1];
                for (int i = 0; i < rows.Length; ++i)
                {
                    for (int j = header.Length - 2; j >= 0; --j)
                    {
                        if (!decimal.TryParse(rows[i][j + 1], NumberStyles.AllowDecimalPoint,
                                              CultureInfo.InvariantCulture, out scores[j]))
                        {
                            throw new ArgumentException("Failed to load scoreboard fom file: Invalid score for team '" + header[j + 1]
                                                        + "' at category '" + rows[i][0] + "'.");
                        }
                    }
                    scoreboard.AddCategory(rows[i][0], scores);
                }

                return(scoreboard);
            }
        }
예제 #6
0
        private async void ButtonOk_Click(object sender, EventArgs e)
        {
            try
            {
                ProgressBarImport.Visible = true;
                ButtonOk.Visible          = false;
                ButtonCancel.Visible      = false;
                ProgressBarImport.Value   = 0;

                string url = TextBoxUrl.Text;

                if (url.EndsWith("/"))
                {
                    url = url.Substring(0, url.Length - 1);
                }

                if (previousUrl != url)
                {
                    previousCookieContainer = new CookieContainer();
                }

                HttpClient client = new HttpClient(new HttpClientHandler()
                {
                    CookieContainer = previousCookieContainer
                });
                HttpResponseMessage response;

                ProgressBarImport.Value = 25;

                if (!CheckBoxExistingAuth.Checked)
                {
                    HttpContent content = new StringContent(JsonConvert.SerializeObject(new LoginData()
                    {
                        Name     = TextBoxName.Text,
                        Password = TextBoxPassword.Text
                    }, serializerSettings), Encoding.UTF8, "application/json");

                    response = await client.PostAsync(url + "/mods", content);

                    if (!response.IsSuccessStatusCode)
                    {
                        throw new Exception("Failed to import from remote: Login failed: (" + response.StatusCode + ")" + response.ReasonPhrase);
                    }
                }
                else
                {
                    await Task.Delay(100);
                }

                ProgressBarImport.Value = 50;

                response = await client.GetAsync(url + "/standings");

                if (!response.IsSuccessStatusCode)
                {
                    throw new Exception("Failed to import from remote: (" + response.StatusCode + ")" + response.ReasonPhrase);
                }
                await Task.Delay(100);

                ProgressBarImport.Value = 75;

                Scoreboard = JsonHandler.LoadFromFile(await response.Content.ReadAsStreamAsync());

                await Task.Delay(100);

                ProgressBarImport.Value = 100;

                previousUrl = url;

                await Task.Delay(100);

                DialogResult = DialogResult.OK;
                Close();
            }
            catch (Exception ex)
            {
                log.Error("Failed to import from remote.", ex);
                MessageBox.Show("Failed to import from remote: " + ex.Message, "Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                ProgressBarImport.Visible = false;
                ButtonOk.Visible          = true;
                ButtonCancel.Visible      = true;
            }
        }
예제 #7
0
        private void MenuFileImportFromRemote_Click(object sender, EventArgs e)
        {
            log.Debug("EditorForm::MenuFileImportFromRemote_Click() {");

            if (hasUnsavedChanges)
            {
                try
                {
                    DialogResult result = MessageBox.Show("There are unsaved changes. Save?", "Information",
                                                          MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);

                    switch (result)
                    {
                    case DialogResult.Yes:
                        if (!SaveToFile())
                        {
                            log.Debug("EditorForm::MenuFileImportFromRemote_Click() } // cancelled (save existing)");
                            return;
                        }
                        break;

                    case DialogResult.No:
                        break;

                    default:
                    case DialogResult.Cancel:
                        log.Debug("EditorForm::MenuFileImportFromRemote_Click() } // cancelled (save existing)");
                        return;
                    }
                }
                catch (Exception ex)
                {
                    log.Error("Failed to import from remote: Failed to save existing scoreboard.", ex);
                    MessageBox.Show("Failed to import from remote: Failed to save existing scoreboard: " + ex.Message, "Error",
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);

                    log.Debug("EditorForm::MenuFileImportFromRemote_Click() }");
                    return;
                }
            }

            try
            {
                ImportFromRemoteForm importFromRemoteForm = new ImportFromRemoteForm();
                importFromRemoteForm.StartPosition = FormStartPosition.CenterParent;
                DialogResult result = importFromRemoteForm.ShowDialog(this);

                if (result != DialogResult.OK)
                {
                    log.Debug("EditorForm::MenuFileImportFromRemote_Click() } // cancelled");
                    return;
                }

                scoreboard = importFromRemoteForm.Scoreboard;

                hasUnsavedChanges = true;
                NumericInputAnimationLength.Value = GetSuggestedAnimationLength();
                UpdateScores();
                UpdateControls();
            }
            catch (Exception ex)
            {
                log.Error("Failed to import from remote.", ex);
                MessageBox.Show("Failed to import from remote: " + ex.Message, "Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            log.Debug("EditorForm::MenuFileImportFromRemote_Click() }");
        }
예제 #8
0
        private void MenuFileNewFromTemplate_Click(object sender, EventArgs e)
        {
            log.Debug("EditorForm::MenuFileNewFromTemplate_Click() {");

            if (hasUnsavedChanges)
            {
                try
                {
                    DialogResult result = MessageBox.Show("There are unsaved changes. Save?", "Information",
                                                          MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);

                    switch (result)
                    {
                    case DialogResult.Yes:
                        if (!SaveToFile())
                        {
                            log.Debug("EditorForm::MenuFileNewFromTemplate_Click() } // cancelled (save existing)");
                            return;
                        }
                        break;

                    case DialogResult.No:
                        break;

                    default:
                    case DialogResult.Cancel:
                        log.Debug("EditorForm::MenuFileNewFromTemplate_Click() } // cancelled (save existing)");
                        return;
                    }
                }
                catch (Exception ex)
                {
                    log.Error("Failed to import template: Failed to save existing scoreboard.", ex);
                    MessageBox.Show("Failed to import template: Failed to save existing scoreboard: " + ex.Message, "Error",
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);

                    log.Debug("EditorForm::MenuFileNewFromTemplate_Click() }");
                    return;
                }
            }

            try
            {
                using (OpenFileDialog openFileDialog = new OpenFileDialog())
                {
                    openFileDialog.InitialDirectory = string.IsNullOrEmpty(fileName) ? Environment.SpecialFolder.MyDocuments.ToString() : fileName;
                    openFileDialog.Filter           = "CSV files (*.csv)|*.csv|JSON files (*.json)|*.json";
                    openFileDialog.FilterIndex      = 1;
                    openFileDialog.RestoreDirectory = true;

                    Scoreboard template;

                    if (openFileDialog.ShowDialog() == DialogResult.OK)
                    {
                        fileName = openFileDialog.FileName;
                        switch (Path.GetExtension(fileName))
                        {
                        case ".csv":
                            template = CsvHandler.LoadFromFile(openFileDialog.OpenFile());
                            break;

                        case ".json":
                            template = JsonHandler.LoadFromFile(openFileDialog.OpenFile());
                            break;

                        default:
                            throw new ArgumentException("Unknown file format: '" + Path.GetExtension(fileName) + "'.");
                        }
                        hasUnsavedChanges = false;

                        scoreboard = new Scoreboard(template.ExpectedNumberOfTeams, template.ExpectedNumberOfCategories);
                        foreach (string team in template.Teams)
                        {
                            scoreboard.AddTeam(team);
                        }
                        NumericInputAnimationLength.Value = GetSuggestedAnimationLength();
                        UpdateScores();
                        UpdateControls();
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error("Failed to import template.", ex);
                MessageBox.Show("Failed to import template: " + ex.Message, "Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            log.Debug("EditorForm::MenuFileNewFromTemplate_Click() }");
        }
예제 #9
0
        private void MenuFileNew_Click(object sender, EventArgs e)
        {
            log.Debug("EditorForm::MenuFileNew_Click() {");

            if (hasUnsavedChanges)
            {
                try
                {
                    DialogResult result = MessageBox.Show("There are unsaved changes. Save?", "Information",
                                                          MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);

                    switch (result)
                    {
                    case DialogResult.Yes:
                        if (!SaveToFile())
                        {
                            log.Debug("EditorForm::MenuFileNew_Click() } // cancelled (save existing)");
                            return;
                        }
                        break;

                    case DialogResult.No:
                        break;

                    default:
                    case DialogResult.Cancel:
                        log.Debug("EditorForm::MenuFileNew_Click() } // cancelled (save existing)");
                        return;
                    }
                }
                catch (Exception ex)
                {
                    log.Error("Failed to create new scoreboard: Failed to save existing scoreboard.", ex);
                    MessageBox.Show("Failed to create new scoreboard: Failed to save existing scoreboard: " + ex.Message, "Error",
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);

                    log.Debug("EditorForm::MenuFileNew_Click() }");
                    return;
                }
            }

            try
            {
                NewScoreboardForm newScoreboardForm = new NewScoreboardForm();
                newScoreboardForm.StartPosition = FormStartPosition.CenterParent;
                DialogResult result = newScoreboardForm.ShowDialog(this);

                if (result != DialogResult.OK)
                {
                    log.Debug("EditorForm::MenuFileNew_Click() } // cancelled");
                    return;
                }

                scoreboard        = new Scoreboard(newScoreboardForm.NumberOfTeams, newScoreboardForm.NumberOfCategories);
                hasUnsavedChanges = false;
                NumericInputAnimationLength.Value = 3m;

                UpdateScores();
                UpdateControls();
            }
            catch (Exception ex)
            {
                log.Error("Failed to create new scoreboard.", ex);
                MessageBox.Show("Failed to create new scoreboard: " + ex.Message, "Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            log.Debug("EditorForm::MenuFileNew_Click() }");
        }
예제 #10
0
        public void StartAnimation(Scoreboard scoreboard, double animationLength, bool enableFireworks)
        {
            // precompute some values
            // and start render-thread/draw-loop

            isRunning     = true;
            keepRendering = true;

            this.animationLength = animationLength * 1000d;
            this.enableFireworks = enableFireworks;

            if (scoreboard == null)
            {
                throw new ArgumentException("Failed to show results: Argument 'scoreboard' is null.");
            }

            teams      = scoreboard.Teams;
            categories = scoreboard.Categories;
            scores     = scoreboard.Scores;
            int expectedNumberOfCategories = scoreboard.ExpectedNumberOfCategories;

            if (teams == null || teams.Length == 0 || categories == null || categories.Length == 0 || expectedNumberOfCategories == 0)
            {
                throw new ArgumentException("Failed to show results: Invalid scoreboard.");
            }

            decimal[] sortedTotalScores = scoreboard.TotalScores;
            Array.Sort(sortedTotalScores);
            bool maxScoreTie = sortedTotalScores.Length >= 2 && sortedTotalScores[sortedTotalScores.Length - 1] == sortedTotalScores[sortedTotalScores.Length - 2];

            sortedTotalScores = sortedTotalScores.Distinct().ToArray();
            maxScore          = sortedTotalScores[sortedTotalScores.Length - 1];

            // devide total into points where "teams finish"
            animationSpeedSlowdownDomain    = new float[sortedTotalScores.Length + 1];
            animationSpeedSlowdownDomain[0] = -0.01f;
            animationSpeedSlowdownDomain[sortedTotalScores.Length] = 100.01f;
            // get percentage of individual team scores w.r.t. to maxScore
            animationSpeedSlowdownImage    = new float[sortedTotalScores.Length + 1];
            animationSpeedSlowdownImage[0] = 0f;
            animationSpeedSlowdownImage[sortedTotalScores.Length] = 100f;
            for (int i = 1; i < sortedTotalScores.Length; ++i)
            {
                animationSpeedSlowdownDomain[i] = i * (100f / sortedTotalScores.Length);
                animationSpeedSlowdownImage[i]  = (float)(sortedTotalScores[i + sortedTotalScores.Length - animationSpeedSlowdownDomain.Length] * 100m / maxScore);
            }
            if (!maxScoreTie)
            {
                animationSpeedSlowdownDomain[sortedTotalScores.Length - 1] = 98f;
            }

            colorsCategories  = new Color[expectedNumberOfCategories];
            brushesCategories = new Brush[expectedNumberOfCategories--];
            for (int i = expectedNumberOfCategories; i >= 0; --i)
            {
                colorsCategories[i]  = Color.FromArgb(255, 150 - (i * 100 / expectedNumberOfCategories), 0);
                brushesCategories[i] = new SolidBrush(colorsCategories[i]);
            }

            // category name rects
            categoryNamesPos = new RectangleF[categories.Length];
            float height = categoryNamesHeight / categories.Length;

            for (int i = 0; i < categories.Length; ++i)
            {
                categoryNamesPos[i] = new RectangleF(
                    categoryNamesLeft,
                    categoryNamesBottom - (i + 1) * height,
                    categoryNamesWidth,
                    height);
            }

#if VISUALIZE_ANIMATION_SPEED
            RenderAnimationSpeed();
#else
            renderThread = new Thread(new ThreadStart(RenderThreadLoop));
            renderThread.Start();
#endif

            Invalidate();
        }