<commit_before>import React from 'react';
import _ from 'lodash';
import Stack from '../components/Stack';
import BoxAndWhisker from '../components/BoxAndWhisker';
import DibelsBreakdownBar from '../components/DibelsBreakdownBar';
import {studentsInRoom} from './studentIdsByRoomFunctions';


// This component is written particularly for Somerville and it's likely this would require factoring out
// into `PerDistrict` to respect the way this data is stored across districts.
export default class ClassroomStats extends React.Component {
  constructor(props) {
    super(props);
    this.renderLabelFn = this.renderLabelFn.bind(this);
  }

  studentsInRoom(room) {
    const {students, studentIdsByRoom} = this.props;
    return studentsInRoom(students, studentIdsByRoom, room.roomKey);
  }

  render() {
    const {rooms, gradeLevelNextYear} = this.props;

    // Show different academic indicators by grade level.  STAR starts in 2nd grade.
    const showStar = (['1', '2'].indexOf(gradeLevelNextYear) === -1);
    const showDibels = !showStar;
    return (
      <div className="ClassroomStats" style={styles.root}>
        <table style={styles.table}>
          <thead>
            <tr>
              <th style={styles.cell}></th>
              <th style={styles.spacer}></th>
              <th style={{...styles.cell, ...styles.heading}}
                title="Students who have an IEP or 504 plan">IEP or 504</th>
              <th style={{...styles.cell, ...styles.heading}}
                title="Students receiving English Learning Services or who have in the past (FLEP)">Limited or FLEP</th>
              <th style={styles.spacer}></th>
              <th style={{...styles.cell, ...styles.heading}}
                title="Students who identify their gender as male and not female, nonbinary or transgendered.  One gender is chosen here to simplify the visual representation, not to imply a preference or hierarchy.">
                Gender, male</th>
              <th style={{...styles.cell, ...styles.heading}}
                title="Students whose are enrolled in the free or reduced lunch program">
                Low income
              </th>
              <th style={styles.spacer}></th>
              <th style={{...styles.cell, ...styles.heading}}
                title="Students who had three or more discipline incidents of any kind during this past school year.  Discipline incidents vary in severity; click on the student's name to see more in their profile.">
                Discipline, 3+
              </th>
              {showDibels &&
                <th style={{...styles.cell, ...styles.heading}}
                  title="Students' latest DIBELS scores, broken down into Core (green), Strategic (orange) and Itensive (red)">
                  Dibels CORE
                </th>}
              {showStar &&
                <th style={{...styles.cell, ...styles.heading}}
                  title="A boxplot showing the range of students' latest STAR Math percentile scores.  The number represents the median score.">
                  STAR Math
                </th>}
              {showStar &&
                <th style={{...styles.cell, ...styles.heading}}
                  title="A boxplot showing the range of students' latest STAR Reading percentile scores.  The number represents the median score.">
                  STAR Reading
                </th>}
            </tr>
          </thead>
          <tbody>
            {rooms.map(room => {  
              const studentsInRoom = this.studentsInRoom(room);
              return (
                <tr key={room.roomKey}>
                  <td style={styles.cell}>{room.roomName}</td>
                  <th style={styles.spacer}></th>
                  <td style={styles.cell}>{this.renderIepOr504(studentsInRoom)}</td>
                  <td style={styles.cell}>{this.renderEnglishLearners(studentsInRoom)}</td>
                  <td style={styles.spacer}></td>
                  <td style={styles.cell}>{this.renderGender(studentsInRoom)}</td>
                  <td style={styles.cell}>{this.renderLowIncome(studentsInRoom)}</td>
                  <td style={styles.spacer}></td>
                  <td style={styles.cell}>{this.renderDiscipline(studentsInRoom)}</td>
                  {showDibels && <td style={styles.cell}>{this.renderDibelsBreakdown(studentsInRoom)}</td>}
                  {showStar && <td style={styles.cell}>{this.renderMath(studentsInRoom)}</td>}
                  {showStar && <td style={styles.cell}>{this.renderReading(studentsInRoom)}</td>}
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    );
  }

  renderIepOr504(studentsInRoom) {
    const count = studentsInRoom.filter(student => {
      return (student.disability !== null || student.plan_504 !== 'Not 504');
    }).length;
    return this.renderStackSimple(count);
  }

  renderEnglishLearners(studentsInRoom) {
    const count = studentsInRoom.filter(student => {
      return ['Limited', 'FLEP'].indexOf(student.limited_english_proficiency !== -1);
    }).length;
    return this.renderStackSimple(count);
  }

  renderGender(studentsInRoom) {
    const count = studentsInRoom.filter(student => student.gender === 'M').length;
    return this.renderStackSimple(count);
  }

  renderLowIncome(studentsInRoom) {
    const count = studentsInRoom.filter(student => {
      return ['Free Lunch', 'Reduced Lunch'].indexOf(student.free_reduced_lunch) !== -1;
    }).length;
    return this.renderStackSimple(count);
  }

  renderDiscipline(studentsInRoom) {
    const count = studentsInRoom.filter(student => {
      return (student.most_recent_school_year_discipline_incidents_count >= 3);
    }).length;
    return this.renderStackSimple(count);
  }

  renderDibelsBreakdown(studentsInRoom) {
    const students = studentsInRoom;
    const dibelsCounts = {
      strategic: 0,
      intensive: 0,
      core: 0
    };
    students.forEach(student => {
      if (!student.latest_dibels) return;
      const level = dibelsLevel(student.latest_dibels);
      dibelsCounts[level] = dibelsCounts[level] + 1;
    });

    return (
      <DibelsBreakdownBar
        coreCount={dibelsCounts.core}
        intensiveCount={dibelsCounts.intensive}
        strategicCount={dibelsCounts.strategic}
        height={5}
        labelTop={5} />
    );
  }

  renderMath(studentsInRoom) {
    return this.renderStar(studentsInRoom, student => student.most_recent_star_math_percentile);
  }


  renderReading(studentsInRoom) {
    return this.renderStar(studentsInRoom, student => student.most_recent_star_reading_percentile);
  }

  renderStar(studentsInRoom, accessor) {
    const values = _.compact(studentsInRoom.map(accessor));
    return (
      <div>
        {(values.length === 0)
          ? null
          : <BoxAndWhisker values={values} style={{width: 100, marginLeft: 'auto', marginRight: 'auto'}} />}
      </div>
    );
  }
<commit_msg>Tweaking bars<commit_after>import React from 'react';
import _ from 'lodash';
import Stack from '../components/Stack';
import BoxAndWhisker from '../components/BoxAndWhisker';
import DibelsBreakdownBar from '../components/DibelsBreakdownBar';
import {studentsInRoom} from './studentIdsByRoomFunctions';


// This component is written particularly for Somerville and it's likely this would require factoring out
// into `PerDistrict` to respect the way this data is stored across districts.
export default class ClassroomStats extends React.Component {
  constructor(props) {
    super(props);
    this.renderLabelFn = this.renderLabelFn.bind(this);
  }

  studentsInRoom(room) {
    const {students, studentIdsByRoom} = this.props;
    return studentsInRoom(students, studentIdsByRoom, room.roomKey);
  }

  render() {
    const {rooms, gradeLevelNextYear} = this.props;

    // Show different academic indicators by grade level.  STAR starts in 2nd grade.
    const showStar = (['1', '2'].indexOf(gradeLevelNextYear) === -1);
    const showDibels = !showStar;
    return (
      <div className="ClassroomStats" style={styles.root}>
        <table style={styles.table}>
          <thead>
            <tr>
              <th style={styles.cell}></th>
              <th style={styles.spacer}></th>
              <th style={{...styles.cell, ...styles.heading}}
                title="Students who have an IEP or 504 plan">IEP or 504</th>
              <th style={{...styles.cell, ...styles.heading}}
                title="Students receiving English Learning Services or who have in the past (FLEP)">Limited or FLEP</th>
              <th style={styles.spacer}></th>
              <th style={{...styles.cell, ...styles.heading}}
                title="Students who identify their gender as male and not female, nonbinary or transgendered.  One gender is chosen here to simplify the visual representation, not to imply a preference or hierarchy.">
                Gender, male</th>
              <th style={{...styles.cell, ...styles.heading}}
                title="Students whose are enrolled in the free or reduced lunch program">
                Low income
              </th>
              <th style={styles.spacer}></th>
              <th style={{...styles.cell, ...styles.heading}}
                title="Students who had three or more discipline incidents of any kind during this past school year.  Discipline incidents vary in severity; click on the student's name to see more in their profile.">
                Discipline, 3+
              </th>
              {showDibels &&
                <th style={{...styles.cell, ...styles.heading}}
                  title="Students' latest DIBELS scores, broken down into Core (green), Strategic (orange) and Itensive (red)">
                  Dibels CORE
                </th>}
              {showStar &&
                <th style={{...styles.cell, ...styles.heading}}
                  title="A boxplot showing the range of students' latest STAR Math percentile scores.  The number represents the median score.">
                  STAR Math
                </th>}
              {showStar &&
                <th style={{...styles.cell, ...styles.heading}}
                  title="A boxplot showing the range of students' latest STAR Reading percentile scores.  The number represents the median score.">
                  STAR Reading
                </th>}
            </tr>
          </thead>
          <tbody>
            {rooms.map(room => {  
              const studentsInRoom = this.studentsInRoom(room);
              return (
                <tr key={room.roomKey}>
                  <td style={styles.cell}>{room.roomName}</td>
                  <th style={styles.spacer}></th>
                  <td style={styles.cell}>{this.renderIepOr504(studentsInRoom)}</td>
                  <td style={styles.cell}>{this.renderEnglishLearners(studentsInRoom)}</td>
                  <td style={styles.spacer}></td>
                  <td style={styles.cell}>{this.renderGender(studentsInRoom)}</td>
                  <td style={styles.cell}>{this.renderLowIncome(studentsInRoom)}</td>
                  <td style={styles.spacer}></td>
                  <td style={styles.cell}>{this.renderDiscipline(studentsInRoom)}</td>
                  {showDibels && <td style={styles.cell}>{this.renderDibelsBreakdown(studentsInRoom)}</td>}
                  {showStar && <td style={styles.cell}>{this.renderMath(studentsInRoom)}</td>}
                  {showStar && <td style={styles.cell}>{this.renderReading(studentsInRoom)}</td>}
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    );
  }

  renderIepOr504(studentsInRoom) {
    const count = studentsInRoom.filter(student => {
      return (student.disability !== null || student.plan_504 !== 'Not 504');
    }).length;
    return this.renderStackSimple(count);
  }

  renderEnglishLearners(studentsInRoom) {
    const count = studentsInRoom.filter(student => {
      return ['Limited', 'FLEP'].indexOf(student.limited_english_proficiency !== -1);
    }).length;
    return this.renderStackSimple(count);
  }

  renderGender(studentsInRoom) {
    const count = studentsInRoom.filter(student => student.gender === 'M').length;
    return this.renderStackSimple(count);
  }

  renderLowIncome(studentsInRoom) {
    const count = studentsInRoom.filter(student => {
      return ['Free Lunch', 'Reduced Lunch'].indexOf(student.free_reduced_lunch) !== -1;
    }).length;
    return this.renderStackSimple(count);
  }

  renderDiscipline(studentsInRoom) {
    const count = studentsInRoom.filter(student => {
      return (student.most_recent_school_year_discipline_incidents_count >= 3);
    }).length;
    return this.renderStackSimple(count);
  }

  renderDibelsBreakdown(studentsInRoom) {
    const students = studentsInRoom;
    const dibelsCounts = {
      strategic: 0,
      intensive: 0,
      core: 0
    };
    students.forEach(student => {
      if (!student.latest_dibels) return;
      const level = dibelsLevel(student.latest_dibels);
      dibelsCounts[level] = dibelsCounts[level] + 1;
    });

    return (
      <DibelsBreakdownBar
        coreCount={dibelsCounts.core}
        intensiveCount={dibelsCounts.intensive}
        strategicCount={dibelsCounts.strategic}
        style={{paddingTop: 2}}
        height={5}
        labelTop={5} />
    );
  }

  renderMath(studentsInRoom) {
    return this.renderStar(studentsInRoom, student => student.most_recent_star_math_percentile);
  }


  renderReading(studentsInRoom) {
    return this.renderStar(studentsInRoom, student => student.most_recent_star_reading_percentile);
  }

  renderStar(studentsInRoom, accessor) {
    const values = _.compact(studentsInRoom.map(accessor));
    return (
      <div>
        {(values.length === 0)
          ? null
          : <BoxAndWhisker values={values} style={{width: 100, marginLeft: 'auto', marginRight: 'auto'}} />}
      </div>
    );
  }

{'fraction_non_alphanumeric': 0.12627203669198797, 'fraction_numerical': 0.005231474845922316, 'mean_word_length': 2.3986848514369217, 'pattern_counts': {'":': 0, '<': 131, '<?xml version=': 0, '>': 151, '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': '5649521', 'n_tokens_mistral': 4102, 'n_tokens_neox': 3875, 'n_words': 913}