<commit_before>require('app/styles/teachers/teacher-student-view.sass')
RootView = require 'views/core/RootView'
Campaigns = require 'collections/Campaigns'
Classroom = require 'models/Classroom'
Courses = require 'collections/Courses'
Levels = require 'collections/Levels'
LevelSession = require 'models/LevelSession'
LevelSessions = require 'collections/LevelSessions'
User = require 'models/User'
Users = require 'collections/Users'
CourseInstances = require 'collections/CourseInstances'
require 'd3/d3.js'
utils = require 'core/utils'
aceUtils = require 'core/aceUtils'

module.exports = class TeacherStudentView extends RootView
  id: 'teacher-student-view'
  template: require 'templates/teachers/teacher-student-view'

  events:
    'change #course-dropdown': 'onChangeCourseChart'
    'change .course-select': 'onChangeCourseSelect'
    'click .progress-dot a': 'onClickProgressDot'
    'click .level-progress-dot': 'onClickStudentProgressDot'

  getTitle: -> return @user?.broadName()

  initialize: (options, classroomID, @studentID) ->
    @classroom = new Classroom({_id: classroomID})
    @listenToOnce @classroom, 'sync', @onClassroomSync
    @supermodel.trackRequest(@classroom.fetch())

    @courses = new Courses()
    @supermodel.trackRequest(@courses.fetch({data: { project: 'name,i18n,slug' }}))

    @courseInstances = new CourseInstances()
    @supermodel.trackRequest @courseInstances.fetchForClassroom(classroomID)

    # TODO: fetch only necessary thang data (i.e. levels with student progress, via separate API instead of complicated data.project values)
    @levels = new Levels()
    @supermodel.trackRequest(@levels.fetchForClassroom(classroomID, {data: {project: 'name,original,i18n,thangs.id,thangs.components.config.programmableMethods.plan.solutions,thangs.components.config.programmableMethods.plan.context'}}))
    @urls = require('core/urls')

    @singleStudentLevelProgressDotTemplate = require 'templates/teachers/hovers/progress-dot-single-student-level'
    @levelProgressMap = {}

    super(options)

  onLoaded: ->
    @selectedCourseId = @courses.first().id if @courses.loaded and @courses.length > 0 and not @selectedCourseId
    if @students.loaded and not @destroyed
      @user = _.find(@students.models, (s)=> s.id is @studentID)
      @updateLastPlayedInfo()
      @updateLevelProgressMap()
      @updateLevelDataMap()
      @calculateStandardDev()
      @updateSolutions()
      @render()
      
      # Navigate to anchor after loading complete, update selectedCourseId for progress dropdown
      if window.location.hash
        levelSlug = window.location.hash.substring(1)
        @updateSelectedCourseProgress(levelSlug)
        window.location.href = window.location.href 

    super()

  afterRender: ->
    super(arguments...)
    @$('.progress-dot, .btn-view-project-level').each (i, el) ->
      dot = $(el)
      dot.tooltip({
        html: true
        container: dot
      }).delegate '.tooltip', 'mousemove', ->
        dot.tooltip('hide')

    @$('.glyphicon-question-sign').each (i, el) ->
      dot = $(el)
      dot.tooltip({
        html: true
        container: dot
      }).delegate '.tooltip', 'mousemove', ->
        dot.tooltip('hide')

    @drawBarGraph()
    @onChangeCourseChart()

    oldEditor.destroy() for oldEditor in @aceEditors ? []
    @aceEditors = []
    aceEditors = @aceEditors
    lang = @classroom.get('aceConfig')?.language or 'python'
    @$el.find('pre:has(code[class*="lang-"])').each ->
      aceEditor = aceUtils.initializeACE(@, lang)
      aceEditors.push aceEditor

  updateSolutions: ->
    return unless @classroom?.loaded and @sessions?.loaded and @levels?.loaded
    @levelSolutionMap = {}
    for level in @levels.models
      solution = level.getSolutions().find((s) => s.language is @classroom.get('aceConfig')?.language)
      solution = level.getSolutions().find((s) => s.language is 'html') unless solution
      @levelSolutionMap[level.get('original')] = solution.source if solution
    @levelStudentCodeMap = {}
    for session in @sessions.models when session.get('creator') is @studentID
      # Normal level
      @levelStudentCodeMap[session.get('level').original] = session.get('code')?['hero-placeholder']?['plan']
      # Arena level
      @levelStudentCodeMap[session.get('level').original] ?= session.get('code')?['hero-placeholder-1']?['plan']

  updateSelectedCourseProgress: (levelSlug) ->
    return unless levelSlug
    @selectedCourseId = @classroom.get('courses').find((c) => c.levels.find((l) => l.slug is levelSlug))?._id
    return unless @selectedCourseId
    @render?()

  onClickProgressDot: (e) ->
    @updateSelectedCourseProgress(@$(e.currentTarget).data('level-slug'))

  onChangeCourseChart: (e)->
    if (e)
      selected = ('#visualisation-'+((e.currentTarget).value))
      $("[id|='visualisation']").hide()
      $(selected).show()<commit_msg>Remove boilerplate html code from teacher code review<commit_after>require('app/styles/teachers/teacher-student-view.sass')
RootView = require 'views/core/RootView'
Campaigns = require 'collections/Campaigns'
Classroom = require 'models/Classroom'
Courses = require 'collections/Courses'
Levels = require 'collections/Levels'
LevelSession = require 'models/LevelSession'
LevelSessions = require 'collections/LevelSessions'
User = require 'models/User'
Users = require 'collections/Users'
CourseInstances = require 'collections/CourseInstances'
require 'd3/d3.js'
utils = require 'core/utils'
aceUtils = require 'core/aceUtils'

module.exports = class TeacherStudentView extends RootView
  id: 'teacher-student-view'
  template: require 'templates/teachers/teacher-student-view'

  events:
    'change #course-dropdown': 'onChangeCourseChart'
    'change .course-select': 'onChangeCourseSelect'
    'click .progress-dot a': 'onClickProgressDot'
    'click .level-progress-dot': 'onClickStudentProgressDot'

  getTitle: -> return @user?.broadName()

  initialize: (options, classroomID, @studentID) ->
    @classroom = new Classroom({_id: classroomID})
    @listenToOnce @classroom, 'sync', @onClassroomSync
    @supermodel.trackRequest(@classroom.fetch())

    @courses = new Courses()
    @supermodel.trackRequest(@courses.fetch({data: { project: 'name,i18n,slug' }}))

    @courseInstances = new CourseInstances()
    @supermodel.trackRequest @courseInstances.fetchForClassroom(classroomID)

    # TODO: fetch only necessary thang data (i.e. levels with student progress, via separate API instead of complicated data.project values)
    @levels = new Levels()
    @supermodel.trackRequest(@levels.fetchForClassroom(classroomID, {data: {project: 'name,original,i18n,thangs.id,thangs.components.config.programmableMethods.plan.solutions,thangs.components.config.programmableMethods.plan.context'}}))
    @urls = require('core/urls')

    @singleStudentLevelProgressDotTemplate = require 'templates/teachers/hovers/progress-dot-single-student-level'
    @levelProgressMap = {}

    super(options)

  onLoaded: ->
    @selectedCourseId = @courses.first().id if @courses.loaded and @courses.length > 0 and not @selectedCourseId
    if @students.loaded and not @destroyed
      @user = _.find(@students.models, (s)=> s.id is @studentID)
      @updateLastPlayedInfo()
      @updateLevelProgressMap()
      @updateLevelDataMap()
      @calculateStandardDev()
      @updateSolutions()
      @render()
      
      # Navigate to anchor after loading complete, update selectedCourseId for progress dropdown
      if window.location.hash
        levelSlug = window.location.hash.substring(1)
        @updateSelectedCourseProgress(levelSlug)
        window.location.href = window.location.href 

    super()

  afterRender: ->
    super(arguments...)
    @$('.progress-dot, .btn-view-project-level').each (i, el) ->
      dot = $(el)
      dot.tooltip({
        html: true
        container: dot
      }).delegate '.tooltip', 'mousemove', ->
        dot.tooltip('hide')

    @$('.glyphicon-question-sign').each (i, el) ->
      dot = $(el)
      dot.tooltip({
        html: true
        container: dot
      }).delegate '.tooltip', 'mousemove', ->
        dot.tooltip('hide')

    @drawBarGraph()
    @onChangeCourseChart()

    oldEditor.destroy() for oldEditor in @aceEditors ? []
    @aceEditors = []
    aceEditors = @aceEditors
    lang = @classroom.get('aceConfig')?.language or 'python'
    @$el.find('pre:has(code[class*="lang-"])').each ->
      aceEditor = aceUtils.initializeACE(@, lang)
      aceEditors.push aceEditor

  updateSolutions: ->
    return unless @classroom?.loaded and @sessions?.loaded and @levels?.loaded
    @levelSolutionMap = {}
    for level in @levels.models
      solution = level.getSolutions().find((s) => s.language is @classroom.get('aceConfig')?.language)?.source
      solution ?= utils.extractPlayerCodeTag(level.getSolutions().find((s) => s.language is 'html')?.source or '')
      @levelSolutionMap[level.get('original')] = solution
    @levelStudentCodeMap = {}
    for session in @sessions.models when session.get('creator') is @studentID
      # Normal level
      @levelStudentCodeMap[session.get('level').original] = session.get('code')?['hero-placeholder']?['plan']
      # Arena level
      @levelStudentCodeMap[session.get('level').original] ?= session.get('code')?['hero-placeholder-1']?['plan']

  updateSelectedCourseProgress: (levelSlug) ->
    return unless levelSlug
    @selectedCourseId = @classroom.get('courses').find((c) => c.levels.find((l) => l.slug is levelSlug))?._id
    return unless @selectedCourseId
    @render?()

  onClickProgressDot: (e) ->
    @updateSelectedCourseProgress(@$(e.currentTarget).data('level-slug'))

  onChangeCourseChart: (e)->
    if (e)
      selected = ('#visualisation-'+((e.currentTarget).value))
      $("[id|='visualisation']").hide()
      $(selected).show()
{'fraction_non_alphanumeric': 0.14266829367500508, 'fraction_numerical': 0.0018303843807199512, 'mean_word_length': 4.012742099898063, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 41, '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': '403550', 'n_tokens_mistral': 3019, 'n_tokens_neox': 2925, 'n_words': 589}