Piotrekol / StreamCompanion

osu! information extractor, ranging from selected map info to live play data
MIT License
369 stars 59 forks source link

Need help about fast/late indicator in game overlay #364

Closed C4P741N-TH closed 2 months ago

C4P741N-TH commented 1 year ago

I write some gui program to read hit error from file.txt and it will show fast/late indicator. I want to implement with osu!StreamCompanion plugin to show in game overlay. Can u advise me?


using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace osu_judgement_gui
{
    public partial class Form1 : Form
    {
        private string selectedFilePath;
        private FileSystemWatcher fileWatcher;
        private long lastPosition = 0;
        private Timer calculateTimer;

        public Form1()
        {
            InitializeComponent();
            calculateTimer = new Timer();
            calculateTimer.Interval = 100; // Adjust the interval as needed
            calculateTimer.Tick += CalculateAverageTimer_Tick;
            this.FormBorderStyle = FormBorderStyle.FixedSingle;
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (fileWatcher != null)
            {
                fileWatcher.EnableRaisingEvents = false;
                fileWatcher.Dispose();
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
            openFileDialog.Multiselect = false;

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                selectedFilePath = openFileDialog.FileName;
                ReadFileAsync(selectedFilePath); // Don't use await here as we don't want to wait for the file read to complete.
                StartFileWatcher(selectedFilePath);
                calculateTimer.Start(); // Start the timer when a new file is selected
            }
        }

        private async void ReadFileAsync(string filePath)
        {
            try
            {
                using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                using (var streamReader = new StreamReader(fileStream))
                {
                    // Set the position to the last read line
                    if (lastPosition > 0)
                        fileStream.Position = lastPosition;

                    while (!streamReader.EndOfStream)
                    {
                        string line = await streamReader.ReadLineAsync();
                        UpdateTextBoxes(line);
                        lastPosition = fileStream.Position; // Update the last position after each read.
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error reading the file: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void StartFileWatcher(string filePath)
        {
            fileWatcher = new FileSystemWatcher();
            fileWatcher.Path = Path.GetDirectoryName(filePath);
            fileWatcher.Filter = Path.GetFileName(filePath);
            fileWatcher.NotifyFilter = NotifyFilters.LastWrite;
            fileWatcher.Changed += OnFileChanged;
            fileWatcher.EnableRaisingEvents = true;
        }

        private void OnFileChanged(object sender, FileSystemEventArgs e)
        {
            // Avoid cross-thread issues by invoking on the UI thread.
            Invoke(new Action(() =>
            {
                ReadFileAsync(selectedFilePath);
            }));
        }

        private void UpdateTextBoxes(string line)
        {
            if (!string.IsNullOrEmpty(selectedFilePath))
            {
                try
                {
                    string[] numbers = line.Split(',');
                    if (numbers.Length > 0 && int.TryParse(numbers[numbers.Length - 1], out int lastValue))
                    {
                        if (lastValue > 11)
                        {
                            textBox2.Text = "Late";
                            textBox3.Text = lastValue.ToString();
                        }
                        else if (lastValue < -11)
                        {
                            textBox2.Text = "Fast";
                            textBox3.Text = lastValue.ToString();
                        }
                        else if (lastValue > -11 && lastValue < 11)
                        {
                            textBox2.Text = "Perfect";
                            textBox3.Text = lastValue.ToString();
                        }
                        else
                        {
                            textBox2.Text = "";
                            textBox3.Text = lastValue.ToString();
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error display indicator: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void CalculateAverageTimer_Tick(object sender, EventArgs e)
        {
            calculateTimer.Stop(); // Stop the timer during the calculation
            CalculateAverage();
            calculateTimer.Start(); // Start the timer again after the calculation is done
        }

        private void CalculateAverage()
        {
            if (!string.IsNullOrEmpty(selectedFilePath))
            {
                try
                {
                    // Read all lines in the file
                    string[] lines = File.ReadAllLines(selectedFilePath);

                    if (lines.Length > 0)
                    {
                        // Parse the values and calculate the average
                        double sum = 0;
                        int count = 0;
                        foreach (string line in lines)
                        {
                            string[] numbers = line.Split(',');
                            foreach (string number in numbers)
                            {
                                if (double.TryParse(number, out double value))
                                {
                                    sum += value;
                                    count++;
                                }
                            }
                        }

                        if (count > 0)
                        {
                            double average = sum / count;
                            textBox4.Text = Math.Round(average,2).ToString();
                        }
                    }
                }
                catch (Exception ex)
                {

                }
            }
        }
    }
}```