<commit_before>// Copyright 2013-2021, University of Colorado Boulder

/**
 * This node is used to display a user's results when they complete a level.
 *
 * @author <NAME>
 * @author <NAME> (PixelZoom, Inc.)
 */

import Property from '../../axon/js/Property.js';
import optionize from '../../phet-core/js/optionize.js';
import StringUtils from '../../phetcommon/js/util/StringUtils.js';
import PhetFont from '../../scenery-phet/js/PhetFont.js';
import { Color, Font, IColor, RichText, Text, VBox } from '../../scenery/js/imports.js';
import { PushButtonListener } from '../../sun/js/buttons/PushButtonModel.js';
import TextPushButton from '../../sun/js/buttons/TextPushButton.js';
import Panel, { PanelOptions } from '../../sun/js/Panel.js';
import Tandem from '../../tandem/js/Tandem.js';
import GameTimer from './GameTimer.js';
import ScoreDisplayStars from './ScoreDisplayStars.js';
import vegas from './vegas.js';
import vegasStrings from './vegasStrings.js';

type SelfOptions = {
  levelVisible?: boolean; // whether to display the level number
  ySpacing?: number;
  titleFont?: Font;
  infoFont?: Font;
  buttonFont?: Font;
  buttonFill?: IColor;
  starDiameter?: number;
  contentMaxWidth?: number | null; // applied as maxWidth to every subcomponent individually, not Panel's content
};

export type LevelCompletedNodeOptions = SelfOptions & PanelOptions;

export default class LevelCompletedNode extends Panel {

  private readonly disposeLevelCompletedNode: () => void;

  /**
   * @param level - the game level that has been completed
   * @param score
   * @param perfectScore
   * @param numberOfStars
   * @param timerEnabled
   * @param elapsedTime (in seconds)
   * @param bestTimeAtThisLevel (in seconds), null indicates no best time
   * @param isNewBestTime
   * @param continueFunction - function to call when the user presses the 'Continue' button
   * @param providedOptions
   */
  constructor( level: number, score: number, perfectScore: number, numberOfStars: number, timerEnabled: boolean,
               elapsedTime: number, bestTimeAtThisLevel: number | null, isNewBestTime: boolean,
               continueFunction: PushButtonListener, providedOptions?: LevelCompletedNodeOptions ) {

    const options = optionize<LevelCompletedNodeOptions, SelfOptions, PanelOptions, 'tandem'>( {

      // SelfOptions
      levelVisible: true, // whether to display the level number
      ySpacing: 30,
      titleFont: new PhetFont( { size: 28, weight: 'bold' } ),
      infoFont: new PhetFont( { size: 22, weight: 'bold' } ),
      buttonFont: new PhetFont( 26 ),
      buttonFill: new Color( 255, 255, 0 ),
      starDiameter: 62,
      contentMaxWidth: null,

      // PanelOptions
      fill: new Color( 180, 205, 255 ),
      stroke: 'black',
      lineWidth: 2,
      cornerRadius: 35,
      xMargin: 20,
      yMargin: 20,
      tandem: Tandem.REQUIRED
    }, providedOptions );

    // nodes to be added to the panel
    const children = [];

    // Title, which changes based on how the user did.
    const proportionCorrect = score / perfectScore;
    let titleText = vegasStrings.keepTrying;
    if ( proportionCorrect > 0.95 ) {
      titleText = vegasStrings.excellent;
    }
    else if ( proportionCorrect > 0.75 ) {
      titleText = vegasStrings.great;
    }
    else if ( proportionCorrect >= 0.5 ) {
      titleText = vegasStrings.good;
    }
    const title = new Text( titleText, {
      font: options.titleFont,
      maxWidth: options.contentMaxWidth
    } );
    children.push( title );

    // Progress indicator
    const scoreDisplayStars = new ScoreDisplayStars( new Property( score ), {<commit_msg>factor out constants for default fonts, convert default colors to strings<commit_after>// Copyright 2013-2021, University of Colorado Boulder

/**
 * This node is used to display a user's results when they complete a level.
 *
 * @author <NAME>
 * @author <NAME> (PixelZoom, Inc.)
 */

import Property from '../../axon/js/Property.js';
import optionize from '../../phet-core/js/optionize.js';
import StringUtils from '../../phetcommon/js/util/StringUtils.js';
import PhetFont from '../../scenery-phet/js/PhetFont.js';
import { Font, IColor, RichText, Text, VBox } from '../../scenery/js/imports.js';
import { PushButtonListener } from '../../sun/js/buttons/PushButtonModel.js';
import TextPushButton from '../../sun/js/buttons/TextPushButton.js';
import Panel, { PanelOptions } from '../../sun/js/Panel.js';
import Tandem from '../../tandem/js/Tandem.js';
import GameTimer from './GameTimer.js';
import ScoreDisplayStars from './ScoreDisplayStars.js';
import vegas from './vegas.js';
import vegasStrings from './vegasStrings.js';

const DEFAULT_TITLE_FONT = new PhetFont( { size: 28, weight: 'bold' } );
const DEFAULT_INFO_FONT = new PhetFont( { size: 22, weight: 'bold' } );
const DEFAULT_BUTTON_FONT = new PhetFont( 26 );

type SelfOptions = {
  levelVisible?: boolean; // whether to display the level number
  ySpacing?: number;
  titleFont?: Font;
  infoFont?: Font;
  buttonFont?: Font;
  buttonFill?: IColor;
  starDiameter?: number;
  contentMaxWidth?: number | null; // applied as maxWidth to every subcomponent individually, not Panel's content
};

export type LevelCompletedNodeOptions = SelfOptions & PanelOptions;

export default class LevelCompletedNode extends Panel {

  private readonly disposeLevelCompletedNode: () => void;

  /**
   * @param level - the game level that has been completed
   * @param score
   * @param perfectScore
   * @param numberOfStars
   * @param timerEnabled
   * @param elapsedTime (in seconds)
   * @param bestTimeAtThisLevel (in seconds), null indicates no best time
   * @param isNewBestTime
   * @param continueFunction - function to call when the user presses the 'Continue' button
   * @param providedOptions
   */
  constructor( level: number, score: number, perfectScore: number, numberOfStars: number, timerEnabled: boolean,
               elapsedTime: number, bestTimeAtThisLevel: number | null, isNewBestTime: boolean,
               continueFunction: PushButtonListener, providedOptions?: LevelCompletedNodeOptions ) {

    const options = optionize<LevelCompletedNodeOptions, SelfOptions, PanelOptions, 'tandem'>( {

      // SelfOptions
      levelVisible: true,
      ySpacing: 30,
      titleFont: DEFAULT_TITLE_FONT,
      infoFont: DEFAULT_INFO_FONT,
      buttonFont: DEFAULT_BUTTON_FONT,
      buttonFill: 'rgb( 255, 255, 0 )',
      starDiameter: 62,
      contentMaxWidth: null,

      // PanelOptions
      fill: 'rgb( 180, 205, 255 )',
      stroke: 'black',
      lineWidth: 2,
      cornerRadius: 35,
      xMargin: 20,
      yMargin: 20,
      tandem: Tandem.REQUIRED
    }, providedOptions );

    // nodes to be added to the panel
    const children = [];

    // Title, which changes based on how the user did.
    const proportionCorrect = score / perfectScore;
    let titleText = vegasStrings.keepTrying;
    if ( proportionCorrect > 0.95 ) {
      titleText = vegasStrings.excellent;
    }
    else if ( proportionCorrect > 0.75 ) {
      titleText = vegasStrings.great;
    }
    else if ( proportionCorrect >= 0.5 ) {
      titleText = vegasStrings.good;
    }
    const title = new Text( titleText, {
      font: options.titleFont,
      maxWidth: options.contentMaxWidth
    } );
    children.push( title );

    // Progress indicator
    const scoreDisplayStars = new ScoreDisplayStars( new Property( score ), {
{'fraction_non_alphanumeric': 0.11612903225806452, 'fraction_numerical': 0.013172043010752688, 'mean_word_length': 3.2764367816091955, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 17, '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': '1426753', 'n_tokens_mistral': 2255, 'n_tokens_neox': 2121, 'n_words': 670}