<commit_before>package com.puzzletimer.gui;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.JPanel;

import com.puzzletimer.models.Solution;
import com.puzzletimer.util.SolutionUtils;

@SuppressWarnings("serial")
public class GraphPanel extends JPanel {
    ArrayList<Long> solutionTimes;
    private long solutionIntervalStart;
    private long solutionIntervalEnd;
    ArrayList<Long> startTimes;
    long startIntervalStart;
    long startIntervalEnd;

    public GraphPanel(Solution[] solutions) {
        setBackground(Color.WHITE);
        setSolutions(solutions);
    }

    public void setSolutions(Solution[] solutions) {
        // apply +2, filter DNFs
        this.solutionTimes = new ArrayList<Long>();
        this.startTimes = new ArrayList<Long>();
        for (Solution solution : solutions) {
            long time = SolutionUtils.realTime(solution);
            if (time != Long.MAX_VALUE) {
                this.solutionTimes.add(time);
                this.startTimes.add(solution.getTiming().getStart().getTime());
            }
        }

        // define solution times interval size
        if (this.solutionTimes.size() == 0) {
            this.solutionIntervalStart = 17000;
            this.solutionIntervalEnd = 23000;
        } else {
            // mean
            long mean = 0;
            for (int i = 0; i < this.solutionTimes.size(); i++) {
                mean += this.solutionTimes.get(i);
            }
            mean /= this.solutionTimes.size();

            // standard deviation
            long variance = 0;
            for (int i = 0; i < this.solutionTimes.size(); i++) {
                variance += Math.pow(this.solutionTimes.get(i) - mean, 2d);
            }
            variance /= this.solutionTimes.size();

            long standardDeviation = (long) Math.sqrt(variance);

            this.solutionIntervalStart = mean - 3 * Math.max(50, standardDeviation);
            this.solutionIntervalEnd = mean + 3 * Math.max(50, standardDeviation);
        }

        // define start times interval size
        if (this.solutionTimes.size() == 0) {
            Date now = new Date();
            this.startIntervalStart = now.getTime() - 5000;
            this.startIntervalEnd = now.getTime() + 5000;
        } else if (this.solutionTimes.size() == 1) {
            this.startIntervalStart = this.startTimes.get(0) - 5000;
            this.startIntervalEnd = this.startTimes.get(0) + 5000;
        } else {
            this.startIntervalStart = this.startTimes.get(this.startTimes.size() - 1);
            this.startIntervalEnd = this.startTimes.get(0);
        }

        // repaint
        repaint();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        g2.setFont(new Font("Arial", Font.BOLD, 10));

        int hBase = 16;
        int wBase = 45;

        // draw vertical line<commit_msg>Support for zero length interval in graph panel<commit_after>package com.puzzletimer.gui;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.JPanel;

import com.puzzletimer.models.Solution;
import com.puzzletimer.util.SolutionUtils;

@SuppressWarnings("serial")
public class GraphPanel extends JPanel {
    ArrayList<Long> solutionTimes;
    private long solutionIntervalStart;
    private long solutionIntervalEnd;
    ArrayList<Long> startTimes;
    long startIntervalStart;
    long startIntervalEnd;

    public GraphPanel(Solution[] solutions) {
        setBackground(Color.WHITE);
        setSolutions(solutions);
    }

    public void setSolutions(Solution[] solutions) {
        // apply +2, filter DNFs
        this.solutionTimes = new ArrayList<Long>();
        this.startTimes = new ArrayList<Long>();
        for (Solution solution : solutions) {
            long time = SolutionUtils.realTime(solution);
            if (time != Long.MAX_VALUE) {
                this.solutionTimes.add(time);
                this.startTimes.add(solution.getTiming().getStart().getTime());
            }
        }

        // define solution times interval size
        if (this.solutionTimes.size() == 0) {
            this.solutionIntervalStart = 17000;
            this.solutionIntervalEnd = 23000;
        } else {
            // mean
            long mean = 0;
            for (int i = 0; i < this.solutionTimes.size(); i++) {
                mean += this.solutionTimes.get(i);
            }
            mean /= this.solutionTimes.size();

            // standard deviation
            long variance = 0;
            for (int i = 0; i < this.solutionTimes.size(); i++) {
                variance += Math.pow(this.solutionTimes.get(i) - mean, 2d);
            }
            variance /= this.solutionTimes.size();

            long standardDeviation = (long) Math.sqrt(variance);

            this.solutionIntervalStart = mean - 3 * Math.max(50, standardDeviation);
            this.solutionIntervalEnd = mean + 3 * Math.max(50, standardDeviation);
        }

        // define start times interval size
        if (this.solutionTimes.size() == 0) {
            Date now = new Date();
            this.startIntervalStart = now.getTime() - 5000;
            this.startIntervalEnd = now.getTime() + 5000;
        } else if (this.solutionTimes.size() == 1) {
            this.startIntervalStart = this.startTimes.get(0) - 5000;
            this.startIntervalEnd = this.startTimes.get(0) + 5000;
        } else {
            this.startIntervalStart = this.startTimes.get(this.startTimes.size() - 1);
            this.startIntervalEnd = this.startTimes.get(0);

            if (this.startIntervalStart == this.startIntervalEnd) {
                this.startIntervalStart = this.startTimes.get(0) - 5000;
                this.startIntervalEnd = this.startTimes.get(0) + 5000;
            }
        }

        // repaint
        repaint();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        g2.setFont(new Font("Arial", Font.BOLD, 10));

        int hBase = 16;
        int wBase = 45;

        // draw vertical line
{'fraction_non_alphanumeric': 0.11152196420647834, 'fraction_numerical': 0.018340482177192724, 'mean_word_length': 2.2017045454545454, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3616574', 'n_tokens_mistral': 2051, 'n_tokens_neox': 1881, 'n_words': 411}