<commit_before>package rv.ui.screens;

import java.awt.Color;
import java.awt.Font;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
import javax.media.opengl.GL2;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;
import js.jogl.view.Camera3D;
import js.jogl.view.Viewport;
import js.math.BoundingBox;
import js.math.vector.Vec3f;
import rv.Viewer;
import rv.comm.drawing.annotations.AgentAnnotation;
import rv.comm.rcssserver.GameState;
import rv.ui.view.RobotVantageBase;
import rv.ui.view.RobotVantageFirstPerson;
import rv.ui.view.RobotVantageThirdPerson;
import rv.world.ISelectable;
import rv.world.Team;
import rv.world.WorldModel;
import rv.world.objects.Agent;
import com.jogamp.opengl.util.awt.TextRenderer;
import com.jogamp.opengl.util.gl2.GLUT;

public abstract class ViewerScreenBase implements Screen, KeyListener, MouseListener,
        MouseMotionListener, GameState.GameStateChangeListener, WorldModel.SelectionChangeListener {

    enum AgentOverheadType {
        NONE, ANNOTATIONS, IDS
    }

    enum RobotVantageType {
        NONE, FIRST_PERSON, THIRD_PERSON
    }

    protected final Viewer          viewer;

    private final Field2DOverlay    fieldOverlay;
    protected final List<Screen>    overlays          = new ArrayList<>();

    protected final TextRenderer    overlayTextRenderer;
    private final List<TextOverlay> textOverlays      = new ArrayList<>();

    private RobotVantageBase        robotVantage      = null;
    private RobotVantageType        robotVantageType  = RobotVantageType.NONE;

    private AgentOverheadType       agentOverheadType = AgentOverheadType.ANNOTATIONS;
    protected final TextRenderer    tr;

    private int                     prevScoreL        = -1;
    private int                     prevScoreR        = -1;
    private boolean                 showNumPlayers    = false;

    public ViewerScreenBase(Viewer viewer) {
        this.viewer = viewer;
        overlays.add(new GameStateOverlay(viewer));
        fieldOverlay = new Field2DOverlay(viewer.getWorldModel());
        overlays.add(fieldOverlay);

        overlayTextRenderer = new TextRenderer(new Font("Arial", Font.PLAIN, 48), true, false);
        Font font = new Font("Arial", Font.BOLD, 16);
        tr = new TextRenderer(font, true, false);
    }

    @Override
    public void render(GL2 gl, GLU glu, GLUT glut, Viewport vp) {
        // text overlays
        tr.beginRendering(viewer.getScreen().w, viewer.getScreen().h);
        if (agentOverheadType != AgentOverheadType.NONE) {
            renderAgentOverheads(viewer.getWorldModel().getLeftTeam());
            renderAgentOverheads(viewer.getWorldModel().getRightTeam());
        }
        // draw number of agents on each team
        if (showNumPlayers) {
            Team lt = viewer.getWorldModel().getLeftTeam();
            tr.setColor(Color.white);
            tr.draw(String.format("%s : %d", lt.getName(), lt.getAgents().size()), 10, 10);
            Team rt = viewer.getWorldModel().getRightTeam();
            String s = String.format("%s : %d", rt.getName(), rt.getAgents().size());
            tr.draw(s, (int) (vp.w - tr.getBounds(s).getWidth() - 10), 10);
        }
        tr.endRendering();

        for (Screen overlay : overlays)
            overlay.render(gl, glu, glut, vp);

        vp.apply(gl);
        if (textOverlays.size() > 0)
            renderTextOverlays(vp.w, vp.h);
    }

    private void renderAgentOverheads(Team team) {
        ISelectable selected = viewer.getWorldModel().getSelectedObject();

        for (int i = 0; i < team.getAgents().size(); i++) {
            Agent a = team.getAgents().get(i);
            BoundingBox b = a.getBoundingBox();
            if (b == null)
                continue;
            Vec3f p = b.getCenter();
            p.y = 1;
            String text = "" + a.getID();

            AgentAnnotation aa = a.getAnnotation();
            if (aa != null && agentOverheadType == AgentOverheadType.ANNOTATIONS) {
                renderBillboardText(aa.getText(), p, aa.getColor());
            } else if (agentOverheadType == AgentOverheadType.IDS) {
                float[] color;
                if (selected != null && selected == a) {
                    color = new float[] { 1, 1, 1, 1 };
                } else
                    color = team.getTeamMaterial().getDiffuse();
                renderBillboardText(text, p, color);
            }<commit_msg>Render showNumPlayers texts with a black outline<commit_after>package rv.ui.screens;

import java.awt.Color;
import java.awt.Font;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
import javax.media.opengl.GL2;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;
import js.jogl.view.Camera3D;
import js.jogl.view.Viewport;
import js.math.BoundingBox;
import js.math.vector.Vec3f;
import rv.Viewer;
import rv.comm.drawing.annotations.AgentAnnotation;
import rv.comm.rcssserver.GameState;
import rv.ui.view.RobotVantageBase;
import rv.ui.view.RobotVantageFirstPerson;
import rv.ui.view.RobotVantageThirdPerson;
import rv.world.ISelectable;
import rv.world.Team;
import rv.world.WorldModel;
import rv.world.objects.Agent;
import com.jogamp.opengl.util.awt.TextRenderer;
import com.jogamp.opengl.util.gl2.GLUT;

public abstract class ViewerScreenBase implements Screen, KeyListener, MouseListener,
        MouseMotionListener, GameState.GameStateChangeListener, WorldModel.SelectionChangeListener {

    enum AgentOverheadType {
        NONE, ANNOTATIONS, IDS
    }

    enum RobotVantageType {
        NONE, FIRST_PERSON, THIRD_PERSON
    }

    protected final Viewer          viewer;

    private final Field2DOverlay    fieldOverlay;
    protected final List<Screen>    overlays          = new ArrayList<>();

    protected final TextRenderer    overlayTextRenderer;
    private final List<TextOverlay> textOverlays      = new ArrayList<>();

    private RobotVantageBase        robotVantage      = null;
    private RobotVantageType        robotVantageType  = RobotVantageType.NONE;

    private AgentOverheadType       agentOverheadType = AgentOverheadType.ANNOTATIONS;
    protected final TextRenderer    tr;

    private int                     prevScoreL        = -1;
    private int                     prevScoreR        = -1;
    private boolean                 showNumPlayers    = false;

    public ViewerScreenBase(Viewer viewer) {
        this.viewer = viewer;
        overlays.add(new GameStateOverlay(viewer));
        fieldOverlay = new Field2DOverlay(viewer.getWorldModel());
        overlays.add(fieldOverlay);

        overlayTextRenderer = new TextRenderer(new Font("Arial", Font.PLAIN, 48), true, false);
        Font font = new Font("Arial", Font.BOLD, 16);
        tr = new TextRenderer(font, true, false);
    }

    @Override
    public void render(GL2 gl, GLU glu, GLUT glut, Viewport vp) {
        // text overlays
        tr.beginRendering(viewer.getScreen().w, viewer.getScreen().h);
        if (agentOverheadType != AgentOverheadType.NONE) {
            renderAgentOverheads(viewer.getWorldModel().getLeftTeam());
            renderAgentOverheads(viewer.getWorldModel().getRightTeam());
        }
        // draw number of agents on each team
        if (showNumPlayers) {
            Team lt = viewer.getWorldModel().getLeftTeam();
            renderOutlinedText(formatNumTeamPlayers(lt), 10, 10);

            Team rt = viewer.getWorldModel().getRightTeam();
            String s = formatNumTeamPlayers(rt);
            renderOutlinedText(s, (int) (vp.w - tr.getBounds(s).getWidth() - 10), 10);
        }
        tr.endRendering();

        for (Screen overlay : overlays)
            overlay.render(gl, glu, glut, vp);

        vp.apply(gl);
        if (textOverlays.size() > 0)
            renderTextOverlays(vp.w, vp.h);
    }

    private String formatNumTeamPlayers(Team team) {
        return String.format("%s : %d", team.getName(), team.getAgents().size());
    }

    private void renderOutlinedText(String s, int x, int y) {
        int delta = 1;
        tr.setColor(0, 0, 0, 0.5f);
        tr.draw(s, x - delta, y - delta);
        tr.draw(s, x - delta, y + delta);
        tr.draw(s, x + delta, y - delta);
        tr.draw(s, x + delta, y + delta);
        tr.draw(s, x + delta, y);
        tr.draw(s, x - delta, y);
        tr.draw(s, x, y + delta);
        tr.draw(s, x, y - delta);

        tr.setColor(Color.white);
        tr.draw(s, x, y);
    }

    private void renderAgentOverheads(Team team) {
        ISelectable selected = viewer.getWorldModel().getSelectedObject();

        for (int i = 0; i < team.getAgents().size(); i++) {
            Agent a = team.getAgents().get(i);
            BoundingBox b = a.getBoundingBox();
            if (b == null)
                continue;
            Vec3f p = b.getCenter();
            p.y = 1;
            String text = "" + a.getID();

            AgentAnnotation aa = a.getAnnotation();
            if (aa != null && agentOverheadType == AgentOverheadType.ANNOTATIONS) {
                renderBillboardText(aa.getText(), p, aa.getColor());
            } else if (agentOverheadType == AgentOverheadType.IDS) {
                float[] color;
                if (selected != null && selected == a) {
                    color = new float[] { 1, 1, 1, 1 };
                } else
                    color = team.getTeamMaterial().getDiffuse();
                renderBillboardText(text, p, color);
            }
{'fraction_non_alphanumeric': 0.11240979774367314, 'fraction_numerical': 0.0065047260900498016, 'mean_word_length': 2.4660091581542796, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, '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': '4900862', 'n_tokens_mistral': 3050, 'n_tokens_neox': 2908, 'n_words': 657}