<commit_before>// Error Handling
function report_error($window, err) {
    console.log(err);
    $window.swal('Error', err.data.message, 'error');
}

app.controller("HeaderController", ["$scope", "$window", "$state", "$stateParams",
    function ($scope, $window, $state, $stateParams) {
        $scope.openMenu = function(menu) {
            document.querySelector('.menu').classList.add('active');
            container = document.querySelector('.container-fluid').classList;
            container.add('active');
            container.add('pushed');
        }
        $window.closeMenu = $scope.closeMenu = function() {
            document.querySelector('.menu').classList.remove('active');
            container = document.querySelector('.container-fluid').classList;
            container.remove('active');
            container.remove('pushed');
        }
    }
])

function filter_rows(items) {
    rows = [];
    row = [];
    for (var i=0;i<items.length;i++) {
        item = items[i];
        if (i%3 == 0 && i != 0) {
            rows.push(row);
            row = [];
        }
        row.push(item);
    }
    if (row.length > 0) {
        rows.push(row);
    }
    return rows;
}

app.controller("CourseSelectorController", ["$scope", "$window", "$state", '$stateParams', 'Course',
    function ($scope, $window, $state, $stateParams, Course) {
      Course.get({
        'onlyenrolled': true
      },function(response) {
        if (response.results) {
            $scope.courses = response.results;
            $scope.rows = filter_rows(response.results);
        } else {
            $scope.courses = $scope.rows = []
        }
      }, function(err) {
           report_error($window, err);
       });
      if ($window.user.indexOf("berkeley.edu") == -1) {
        $window.swal({
            title: "Is this the right login?",
            text: "Logging you in with your \"" + $window.user + "\" account...",
            type: "info",
            showCancelButton: true,
            confirmButtonColor: "#DD6B55",
            confirmButtonText: "Yes - that's correct!",
            cancelButtonText: "No - log me out",
            closeOnConfirm: true,
            closeOnCancel: true
        }, function(isConfirm) {
            if (isConfirm) {
              // Do nothing, because the user might want to select a course.
            } else {
                $window.location.href = $window.reloginLink;
            }
        });
      } else {
         $window.location.hash = "";
      }

      $scope.loadAll = function() {
        Course.get(function(response) {
            if (response.results) {
                $scope.rows = filter_rows(response.results);
            } else {
                $scope.courses = $scope.rows = undefined;
            }
          }, function(err) {
            report_error($window, err);
        });
      }
    }
]);

// Assignment Controllers
app.controller("AssignmentOverviewController", ['$scope', "$window",'Assignment', 'User', '$timeout',
  function($scope, $window, Assignment, User, $timeout) {
    Assignment.query({
      fields: {
        id: true,
        display_name: true,
        id: true,
        due_date: true,
        points: true,
        created: true,
      }}, function(response) {
      $scope.assignments = response.results;
    }, function(err) {
         report_error($window, err);
     })}
]);

// Assignment Controllers
app.controller("GroupOverviewController", ['$scope', "$window",'Assignment', 'User', '$timeout',
  function($scope, $window, Assignment, User, $timeout) {
    Group.query(function(response) {
      $scope.assignments = response.results;
    }, function(err) {
         report_error($window, err);
     })}
]);

app.controller("SubmissionDetailCtrl", ['$scope', '$window', '$location', '$stateParams', '$sce', '$timeout', '$anchorScroll', 'Submission',
  function($scope, $window, $location, $stateParams, $sce, $timeout, $anchorScroll, Submission) {
      var converter = new Showdown.converter();

      $window.closeMenu();

      $scope.convertMarkdown = function(text) {
        if (text == "" || text === undefined) {
          return $sce.trustAsHtml("")
        }
        return $sce.trustAsHtml(converter.makeHtml(text));
      }

     Submission.get({
      id: $stateParams.submissionId
     }, function (response) {
        $scope.submission = response;
        $scope.courseId = $stateParams.courseId;
        if (response.messages && response.messages.file_contents && response.messages.file_contents['submit']) {
          delete $scope.submission.messages.file_contents['submit'];
          $scope.isSubmit = true;
        }
      }, function(err) {
           report_error($window, err);
       });
  }]);

// Main dashboard controller. Should be modularized later.
app.controller("AssignmentDashController", ['$scope', '$window', '$state',  '$stateParams', 'Assignment', 'User', 'Group', 'Submission', 'FinalSubmissionChange', '$timeout',
  function($scope, $window, $state,  $stateParams, Assignment, User, Group, Submission, FinalSubmissionChange, $timeout) {
      $scope.courseId = $stateParams.courseId

      $scope.reloadAssignments = function () {
          User.get({
            course: $stateParams.courseId,
          }, function (response) {
            $scope.closeDetails();
            $scope.initAssignments(response.assignments);
          }, function (error) {
            report_error($window, error);
            $state.transitionTo('courseLanding', null, { reload: true, inherit: true, notify: true })
          })
      }
      $scope.assignInit = function(assign) {
        if (assign.backups) {
            $scope.getBackups(assign, false);
        }
        if (assign.submissions) {
            $scope.getSubmissions(assign, false);
        }

        $scope.labelPartners(assign);
      }
      $scope.initAssignments = function(assignments) {
        $scope.assignments = assignments;
         $scope.rows = filter_rows(assignments);
          for (i = 0;i<assignments.length;i++) {
              $scope.assignInit(assignments[i]);
          }
      }

      $scope.labelPartners = function(assign) {
        info = assign.group.group_info;
        if (info !== null) {
            arr = info.member;
            for (var i = 0; i < arr.length; i++) {
                member = arr[i];
                member.i = i;
                member.letter = String.fromCharCode(65 + i);
            }
        }
      }

      $scope.initSortable = function(assign) {
        $('.sortable').disableSelection();
        $('.sortable').sortable({
            update: function(event, ui) {
                $scope.updatePartners(assign.group);
            }
        });
      }

        $scope.updatePartners = function(group) {
          info = group.group_info;
          if (info !== null && info !== undefined) {
              arr = info.member;
              order = {}
              i = 0;
              lis = document.querySelectorAll('.sidebar.active .sortable li');
              for (var i = 0;i<lis.length;i++) {
                  li = lis[i];
                  order[li.getAttribute('data-i')] = i
                  i += 1;
              }
              for (var i = 0; i< arr.length; i++) {
                member = arr[i];
                member.i = j = order[i];
                member.letter = letter = String.fromCharCode(65 + order[i]);
                document.querySelector('.sortable li[data-i="'+i+'"] .member-letter').innerHTML = letter;
              }
              return arr
          }
        }

      $scope.reorder = function(group) {
        arr = $scope.updatePartners(group);
        order = arr.concat()
        for (var i=0;i<arr.length;i++) {
            member = arr[i];
            order.splice(member.i, 1, member.email[0]);
        }

        Group.reorder({
            id: group.group_info.id,
            order: order
        },
        function (response) {
            $scope.closeDetails();
            $scope.reloadView();
            $window.swal({
                title: "Order saved",
                text: "The order you specified has been saved.",
                timer: 3500,
                type: "success"
            });
        }, function(err) {
            report_error($window, err);
        })
      }

      $scope.reloadAssignments();

      $scope.showComposition = function(score, backupId) {
        if (score) {
          $window.swal({title: 'Score: '+score.score+'/2',
              text: 'Message: ' + score.message,
              showCancelButton: false,
              icon: false,
              allowEscapeKey: true,
              allowOutsideClick: true,
              confirmButtonText: "View Comments",
              closeOnConfirm: true},
              function(isConfirm){
                if (isConfirm) {
                  $window.location.replace('#/'+$scope.courseId+'/submission/'+backupId.toString()+'/diff')
                } else {

                } });
        }
      }
      $scope.reloadView = function () {
        // oldToggle = $scope.currAssign.id
//          $scope.currAssign = null;

          User.force_get({
            course: $stateParams.courseId,
          }, function (response) {
            $scope.initAssignments(response.assignments);
            $scope.initSortable();
          }, function (error) {
            report_error($window, error);
            $state.transitionTo('courseLanding', null, { reload: true, inherit: true, notify: true })
          });

        // $state.transitionTo($state.current, angular.copy($stateParams), { reload: true, inherit: true, notify: true });
      };

      $scope.removeMember = function(currGroup, member) {
            Group.removeMember({
              id: currGroup.id,
              email: member.email[0]
            }, function (response) {
                $window.swal('Removed!', 'You may now invite additional members to your group.', 'success');
                $scope.closeDetails();
                $scope.reloadView();
            }, function(err) {
                  report_error($window, err);
              });
      };

      $scope.winRate = function (assign, backupId) {
        assign.winrate = {'progress': 1, 'message': "Loading"}
        Submission.winRate({
          id: backupId
        }, function (response){
          if (response.error.type) {
            assign.winrate = {'progress': 0, 'error': true, 'message': response.error.type+" Error"}
            $window.swal(response.error.type + " Error",'There was a ' + response.error.type + ' error in your code.','error')
          } else {
            $scope.winrate = response
            assign.winrate = {
              'progress': (response.winrate / .56) * 100,
              'percent': response.winrate * 100,
              'message': response.message
            }
          }
          // $window.swal(response.winrate*100 +"%",'Final Win Rate','info')
        }, function (err) {
          assign.winrate = {
            'message': response.message,
            'error': true
          }

          report_error($window, err);
        });
      }

      $scope.rejectInvite = function(currGroup) {
          Group.rejectInvitation({
            id: currGroup.id,
          }, function (response) {
            $scope.closeDetails();
            $window.swal({
              title: "Invitation rejected.",
              text: "You can now invite other members and/or be invited.",
              timer: 3500,
              type: "success"
            });
            $scope.reloadView();
          }, function (err) {
            report_error($window, err);
          });
      };

      $scope.acceptInvite = function(currGroup) {
          Group.acceptInvitation({
              id: currGroup.id,
          }, function (response) {
            $scope.closeDetails();
            $window.swal({
              title: "Group joined!",
              text: "You can now view submissions credited to this group.",
              timer: 3500,
              type: "success"
            });
            $scope.reloadView();
          }, function (err) {
            report_error($window, err);
          });
      };

      $scope.subm_quantity = 5;
      $scope.backup_quantity = 5;

      $scope.getSubmissions = function (assign,toIncrease) {
            if (toIncrease) {
              $scope.subm_quantity += 10;
            }
            User.getSubmissions({
              assignment: assign.assignment.id,
              quantity: $scope.subm_quantity
            }, function (response) {
              assign.submissions = response;
            }, function(err) {
                 report_error($window, err);
             });
      }

      $scope.getBackups = function (assign, toIncrease) {
            if (toIncrease) {
              $scope.backup_quantity += 10;
            }
            User.getBackups({
              assignment: assign.assignment.id,
              quantity: $scope.backup_quantity
            }, function (response) {
                assign.backups = response;
            }, function(err) {
                 report_error($window, err);
             });
      }

      $scope.changeSubmission = function (submId) {
        FinalSubmissionChange.change({
          submission: submId
        }, function (response) {
          $scope.reloadView();
          $window.swal({
              title: "Changed Submission",
              text: "We'll grade the submission you marked.",
              timer: 3500,
              type: "success"
            });
        }, function (error) {
            $window.swal("Oops...", "Please submit again, instead. This feature is not yet ready.", "error");
        })
      }

      $scope.addMember = function(assign, member) {
        if (member && member != '') {
          assignId = assign.assignment.id
          Assignment.invite({
            id: assignId,
            email: member
          }, function (response) {
                $scope.closeDetails();
                $window.swal({
                  title: "Invitation Sent!",
                  text: "Your partner will need to login to okpy.org and accept the invite.",
                  timer: 3500,
                  type: "success"
                });
                $scope.reloadView();
          }, function(err) {
               report_error($window, err);
           });
        }
      };

      $scope.randomColor = function randomColor(assignment) {
        themes = ['blue','gold','purple']
        if (!assignment.color) {
            var blob = document.querySelectorAll('.blob[id="'+assignment.id+'"]');
            assignment.color = blob.length > 0 ? blob[0].getAttribute('color') : themes[Math.ceil(Math.random()*themes.length)-1]
        }
        return assignment
      }

        $scope.openDetails = function openDetails(assign) {
            $scope.currGroup = assign.group
            $scope.currAssign = assign
            document.querySelector('.container-fluid').classList.add('active');
            document.querySelector('.sidebar[id="'+assign.assignment.id+'"]').classList.add('active');
            $scope.initSortable(assign);
        }

        $window.closeDetails = $scope.closeDetails = function closeDetails() {
            document.querySelector('.menu').classList.remove('active');
            document.querySelector('.container-fluid').classList.remove('active');
            sidebars = document.querySelectorAll('.sidebar');
            for (var i=0;i<sidebars.length;i++) {
                sidebar = sidebars[i];
                sidebar.classList.remove('active');
            }
        }
    }
]);<commit_msg>restored jQuery implmenetation of updatePartners<commit_after>// Error Handling
function report_error($window, err) {
    console.log(err);
    $window.swal('Error', err.data.message, 'error');
}

app.controller("HeaderController", ["$scope", "$window", "$state", "$stateParams",
    function ($scope, $window, $state, $stateParams) {
        $scope.openMenu = function(menu) {
            document.querySelector('.menu').classList.add('active');
            container = document.querySelector('.container-fluid').classList;
            container.add('active');
            container.add('pushed');
        }
        $window.closeMenu = $scope.closeMenu = function() {
            document.querySelector('.menu').classList.remove('active');
            container = document.querySelector('.container-fluid').classList;
            container.remove('active');
            container.remove('pushed');
        }
    }
])

function filter_rows(items) {
    rows = [];
    row = [];
    for (var i=0;i<items.length;i++) {
        item = items[i];
        if (i%3 == 0 && i != 0) {
            rows.push(row);
            row = [];
        }
        row.push(item);
    }
    if (row.length > 0) {
        rows.push(row);
    }
    return rows;
}

app.controller("CourseSelectorController", ["$scope", "$window", "$state", '$stateParams', 'Course',
    function ($scope, $window, $state, $stateParams, Course) {
      Course.get({
        'onlyenrolled': true
      },function(response) {
        if (response.results) {
            $scope.courses = response.results;
            $scope.rows = filter_rows(response.results);
        } else {
            $scope.courses = $scope.rows = []
        }
      }, function(err) {
           report_error($window, err);
       });
      if ($window.user.indexOf("berkeley.edu") == -1) {
        $window.swal({
            title: "Is this the right login?",
            text: "Logging you in with your \"" + $window.user + "\" account...",
            type: "info",
            showCancelButton: true,
            confirmButtonColor: "#DD6B55",
            confirmButtonText: "Yes - that's correct!",
            cancelButtonText: "No - log me out",
            closeOnConfirm: true,
            closeOnCancel: true
        }, function(isConfirm) {
            if (isConfirm) {
              // Do nothing, because the user might want to select a course.
            } else {
                $window.location.href = $window.reloginLink;
            }
        });
      } else {
         $window.location.hash = "";
      }

      $scope.loadAll = function() {
        Course.get(function(response) {
            if (response.results) {
                $scope.rows = filter_rows(response.results);
            } else {
                $scope.courses = $scope.rows = undefined;
            }
          }, function(err) {
            report_error($window, err);
        });
      }
    }
]);

// Assignment Controllers
app.controller("AssignmentOverviewController", ['$scope', "$window",'Assignment', 'User', '$timeout',
  function($scope, $window, Assignment, User, $timeout) {
    Assignment.query({
      fields: {
        id: true,
        display_name: true,
        id: true,
        due_date: true,
        points: true,
        created: true,
      }}, function(response) {
      $scope.assignments = response.results;
    }, function(err) {
         report_error($window, err);
     })}
]);

// Assignment Controllers
app.controller("GroupOverviewController", ['$scope', "$window",'Assignment', 'User', '$timeout',
  function($scope, $window, Assignment, User, $timeout) {
    Group.query(function(response) {
      $scope.assignments = response.results;
    }, function(err) {
         report_error($window, err);
     })}
]);

app.controller("SubmissionDetailCtrl", ['$scope', '$window', '$location', '$stateParams', '$sce', '$timeout', '$anchorScroll', 'Submission',
  function($scope, $window, $location, $stateParams, $sce, $timeout, $anchorScroll, Submission) {
      var converter = new Showdown.converter();

      $window.closeMenu();

      $scope.convertMarkdown = function(text) {
        if (text == "" || text === undefined) {
          return $sce.trustAsHtml("")
        }
        return $sce.trustAsHtml(converter.makeHtml(text));
      }

     Submission.get({
      id: $stateParams.submissionId
     }, function (response) {
        $scope.submission = response;
        $scope.courseId = $stateParams.courseId;
        if (response.messages && response.messages.file_contents && response.messages.file_contents['submit']) {
          delete $scope.submission.messages.file_contents['submit'];
          $scope.isSubmit = true;
        }
      }, function(err) {
           report_error($window, err);
       });
  }]);

// Main dashboard controller. Should be modularized later.
app.controller("AssignmentDashController", ['$scope', '$window', '$state',  '$stateParams', 'Assignment', 'User', 'Group', 'Submission', 'FinalSubmissionChange', '$timeout',
  function($scope, $window, $state,  $stateParams, Assignment, User, Group, Submission, FinalSubmissionChange, $timeout) {
      $scope.courseId = $stateParams.courseId

      $scope.reloadAssignments = function () {
          User.get({
            course: $stateParams.courseId,
          }, function (response) {
            $scope.closeDetails();
            $scope.initAssignments(response.assignments);
          }, function (error) {
            report_error($window, error);
            $state.transitionTo('courseLanding', null, { reload: true, inherit: true, notify: true })
          })
      }
      $scope.assignInit = function(assign) {
        if (assign.backups) {
            $scope.getBackups(assign, false);
        }
        if (assign.submissions) {
            $scope.getSubmissions(assign, false);
        }

        $scope.labelPartners(assign);
      }
      $scope.initAssignments = function(assignments) {
        $scope.assignments = assignments;
         $scope.rows = filter_rows(assignments);
          for (i = 0;i<assignments.length;i++) {
              $scope.assignInit(assignments[i]);
          }
      }

      $scope.labelPartners = function(assign) {
        info = assign.group.group_info;
        if (info !== null) {
            arr = info.member;
            for (var i = 0; i < arr.length; i++) {
                member = arr[i];
                member.i = i;
                member.letter = String.fromCharCode(65 + i);
            }
        }
      }

      $scope.initSortable = function(assign) {
        $('.sortable').disableSelection();
        $('.sortable').sortable({
            update: function(event, ui) {
                $scope.updatePartners(assign.group);
            }
        });
      }

        $scope.updatePartners = function(group) {
          info = group.group_info;
          if (info !== null && info !== undefined) {
              arr = info.member;
              order = {}
              i = 0;
              $('.sidebar.active .sortable li').each(function() {
                  order[$(this).data('i')] = i
                  i += 1;
              });
              for (var i = 0; i< arr.length; i++) {
                member = arr[i];
                member.i = j = order[i];
                member.letter = letter = String.fromCharCode(65 + order[i]);
                $('.sortable li[data-i="'+i+'"]').find('.member-letter').html(letter);
              }
              return arr
          }
        }

      $scope.reorder = function(group) {
        arr = $scope.updatePartners(group);
        order = arr.concat()
        for (var i=0;i<arr.length;i++) {
            member = arr[i];
            order.splice(member.i, 1, member.email[0]);
        }

        Group.reorder({
            id: group.group_info.id,
            order: order
        },
        function (response) {
            $scope.closeDetails();
            $scope.reloadView();
            $window.swal({
                title: "Order saved",
                text: "The order you specified has been saved.",
                timer: 3500,
                type: "success"
            });
        }, function(err) {
            report_error($window, err);
        })
      }

      $scope.reloadAssignments();

      $scope.showComposition = function(score, backupId) {
        if (score) {
          $window.swal({title: 'Score: '+score.score+'/2',
              text: 'Message: ' + score.message,
              showCancelButton: false,
              icon: false,
              allowEscapeKey: true,
              allowOutsideClick: true,
              confirmButtonText: "View Comments",
              closeOnConfirm: true},
              function(isConfirm){
                if (isConfirm) {
                  $window.location.replace('#/'+$scope.courseId+'/submission/'+backupId.toString()+'/diff')
                } else {

                } });
        }
      }
      $scope.reloadView = function () {
        // oldToggle = $scope.currAssign.id
//          $scope.currAssign = null;

          User.force_get({
            course: $stateParams.courseId,
          }, function (response) {
            $scope.initAssignments(response.assignments);
            $scope.initSortable();
          }, function (error) {
            report_error($window, error);
            $state.transitionTo('courseLanding', null, { reload: true, inherit: true, notify: true })
          });

        // $state.transitionTo($state.current, angular.copy($stateParams), { reload: true, inherit: true, notify: true });
      };

      $scope.removeMember = function(currGroup, member) {
            Group.removeMember({
              id: currGroup.id,
              email: member.email[0]
            }, function (response) {
                $window.swal('Removed!', 'You may now invite additional members to your group.', 'success');
                $scope.closeDetails();
                $scope.reloadView();
            }, function(err) {
                  report_error($window, err);
              });
      };

      $scope.winRate = function (assign, backupId) {
        assign.winrate = {'progress': 1, 'message': "Loading"}
        Submission.winRate({
          id: backupId
        }, function (response){
          if (response.error.type) {
            assign.winrate = {'progress': 0, 'error': true, 'message': response.error.type+" Error"}
            $window.swal(response.error.type + " Error",'There was a ' + response.error.type + ' error in your code.','error')
          } else {
            $scope.winrate = response
            assign.winrate = {
              'progress': (response.winrate / .56) * 100,
              'percent': response.winrate * 100,
              'message': response.message
            }
          }
          // $window.swal(response.winrate*100 +"%",'Final Win Rate','info')
        }, function (err) {
          assign.winrate = {
            'message': response.message,
            'error': true
          }

          report_error($window, err);
        });
      }

      $scope.rejectInvite = function(currGroup) {
          Group.rejectInvitation({
            id: currGroup.id,
          }, function (response) {
            $scope.closeDetails();
            $window.swal({
              title: "Invitation rejected.",
              text: "You can now invite other members and/or be invited.",
              timer: 3500,
              type: "success"
            });
            $scope.reloadView();
          }, function (err) {
            report_error($window, err);
          });
      };

      $scope.acceptInvite = function(currGroup) {
          Group.acceptInvitation({
              id: currGroup.id,
          }, function (response) {
            $scope.closeDetails();
            $window.swal({
              title: "Group joined!",
              text: "You can now view submissions credited to this group.",
              timer: 3500,
              type: "success"
            });
            $scope.reloadView();
          }, function (err) {
            report_error($window, err);
          });
      };

      $scope.subm_quantity = 5;
      $scope.backup_quantity = 5;

      $scope.getSubmissions = function (assign,toIncrease) {
            if (toIncrease) {
              $scope.subm_quantity += 10;
            }
            User.getSubmissions({
              assignment: assign.assignment.id,
              quantity: $scope.subm_quantity
            }, function (response) {
              assign.submissions = response;
            }, function(err) {
                 report_error($window, err);
             });
      }

      $scope.getBackups = function (assign, toIncrease) {
            if (toIncrease) {
              $scope.backup_quantity += 10;
            }
            User.getBackups({
              assignment: assign.assignment.id,
              quantity: $scope.backup_quantity
            }, function (response) {
                assign.backups = response;
            }, function(err) {
                 report_error($window, err);
             });
      }

      $scope.changeSubmission = function (submId) {
        FinalSubmissionChange.change({
          submission: submId
        }, function (response) {
          $scope.reloadView();
          $window.swal({
              title: "Changed Submission",
              text: "We'll grade the submission you marked.",
              timer: 3500,
              type: "success"
            });
        }, function (error) {
            $window.swal("Oops...", "Please submit again, instead. This feature is not yet ready.", "error");
        })
      }

      $scope.addMember = function(assign, member) {
        if (member && member != '') {
          assignId = assign.assignment.id
          Assignment.invite({
            id: assignId,
            email: member
          }, function (response) {
                $scope.closeDetails();
                $window.swal({
                  title: "Invitation Sent!",
                  text: "Your partner will need to login to okpy.org and accept the invite.",
                  timer: 3500,
                  type: "success"
                });
                $scope.reloadView();
          }, function(err) {
               report_error($window, err);
           });
        }
      };

      $scope.randomColor = function randomColor(assignment) {
        themes = ['blue','gold','purple']
        if (!assignment.color) {
            var blob = document.querySelectorAll('.blob[id="'+assignment.id+'"]');
            assignment.color = blob.length > 0 ? blob[0].getAttribute('color') : themes[Math.ceil(Math.random()*themes.length)-1]
        }
        return assignment
      }

        $scope.openDetails = function openDetails(assign) {
            $scope.currGroup = assign.group
            $scope.currAssign = assign
            document.querySelector('.container-fluid').classList.add('active');
            document.querySelector('.sidebar[id="'+assign.assignment.id+'"]').classList.add('active');
            $scope.initSortable(assign);
        }

        $window.closeDetails = $scope.closeDetails = function closeDetails() {
            document.querySelector('.menu').classList.remove('active');
            document.querySelector('.container-fluid').classList.remove('active');
            sidebars = document.querySelectorAll('.sidebar');
            for (var i=0;i<sidebars.length;i++) {
                sidebar = sidebars[i];
                sidebar.classList.remove('active');
            }
        }
    }
]);<|endoftext|>


<commit_before>
app.controller("CourseSelectorController", ["$scope", "$window", "$state", '$stateParams', 'Course',
    function ($scope, $window, $state, $stateParams, Course) {
      Course.get(function(response) {
        $scope.courses = response.results
        // TODO : Remove
        console.log($scope.courses)
      });
      if ($window.user.indexOf("berkeley.edu") == -1) {
        $window.swal({
            title: "Is this the right login?",
            text: "Logging you in with your \"" + $window.user + "\" account...",
            type: "info",
            showCancelButton: true,
            confirmButtonColor: "#DD6B55",
            confirmButtonText: "Yes - that's correct!",
            cancelButtonText: "No - log me out",
            closeOnConfirm: true,
            closeOnCancel: true
        }, function(isConfirm) {
            if (isConfirm) {
              // Do nothing, because the user might want to select a course.
            } else {
                $window.location.href = $window.reloginLink;
            }
        });
      } else {
         $window.location.hash = "";
      }
    }
]);

// Assignment Controllers
app.controller("AssignmentOverviewController", ['$scope', 'Assignment', 'User', '$timeout',
  function($scope, Assignment, User, $timeout) {
    Assignment.query(function(response) {
      $scope.assignments = response.results;
    })}
]);

// Assignment Controllers
app.controller("GroupOverviewController", ['$scope', 'Assignment', 'User', '$timeout',
  function($scope, Assignment, User, $timeout) {
    Group.query(function(response) {
      $scope.assignments = response.results;
    })}
]);

// Eeek.
app.controller("AssignmentDashController", ['$scope', 'Assignment', 'User', 'Group', '$timeout',
  function($scope, Assignment, User, Group, $timeout) {
      $scope.courseId = 5699868278390784;

      $scope.toggleAssign = function (assign) {
        if ($scope.currAssign == assign) {
          $scope.currAssign = null
        } else {
          $scope.currAssign = assign;
        }
      }

      $scope.reloadAssignments = function () {
          User.get({
            course: 5699868278390784,
          }, function (response) {
            console.log(response.assignments)
            $scope.assignments = response.assignments
          })
      }

      $scope.reloadAssignments()

      $scope.removeMember = function(currGroup, member) {
            Group.removeMember({
              member: member.key,
              id: currGroup.id
            }, function (err) {
              $scope.currGroup = null;
              $scope.hideGroup();
              $scope.currAssign.group = null
            });
      };

      $scope.getSubmissions = function (assignId) {
            User.getSubmissions({
              assignment: assignId
            }, function (response) {
              $scope.currAssign.submissions = response;
              $scope.showSubms();
            });
      }

      $scope.getBackups = function (assignId) {
            User.getBackups({
              assignment: assignId
            }, function (response) {
              $scope.currAssign.backups = response;
              $scope.showBackups();
            });
      }

        $scope.addMember = function(assignmentId, member) {
          if (member != '') {
            Assignment.invite({
              id: assignmentId,
              email: member
            }, function (response) {
              // TODO  Check for error.
              console.log(response)
            });
          }
        };

        $scope.showGroup = function showGroup(group) {
            $('.popups').addClass('active');
            $('.popup').removeClass('active');
            $('.popup.group').addClass('active').removeClass('hide');
            $scope.currGroup = group
        }

        $scope.hideGroup = function hideGroup() {
            $('.popups').removeClass('active');
            $('.popup').removeClass('active');
            $('.popup.group').addClass('active').addClass('hide');
        }

        $scope.showBackups = function showGroup(id) {
            $('.popups').addClass('active');
            $('.popup').removeClass('active');
            $('.popup.backups').addClass('active').removeClass('hide');
        }

        $scope.showSubms = function showGroup(id) {
            $('.popups').addClass('active');
            $('.popup').removeClass('active');
            $('.popup.submissions').addClass('active').removeClass('hide');
        }

        $scope.hidePopups =  function hidePopups() {
            $('.assign').removeClass('s');
            $('.popups').removeClass('active');
            $('.popup').removeClass('active');
            setTimeout(function() {
              $('.popup').addClass('hide');
            },400);
          }

        $scope.showLoader = function showLoader() {
          $('.loader').removeClass('hide');
        }

        $scope.hideLoader = function hideLoader() {
          $('.loader').addClass('done hide');
          setTimeout(function() {
            $('.loader').removeClass('done')
          },800)
        }

      }
]);

// Group Controllers
app.controller("GroupController", ["$scope", "$stateParams", "$window", "$timeout", "Group",
    function ($scope, $stateParams, $window, $timeout, Group) {
      $scope.loadGroup = function() {
        Group.query({
            assignment: $stateParams.assignmentId,
            members: $window.user
          }, function(groups) {
            if (groups.length == 1) {
              $scope.group = groups[0];
              $scope.inGroup = true;
            } else {
              $scope.group = undefined;
              $scope.inGroup = false;
            }
          }
        );
      }
      $scope.refreshGroup = function() {
          $timeout(function() {
            $scope.loadGroup();
          }, 300);
      }
      $scope.loadGroup();
      $scope.createGroup = function() {
        Group.save({
          assignment: $stateParams.assignmentId,
          members: $window.user
        }, $scope.refreshGroup);
      }
    }
  ]);

app.controller("MemberController", ["$scope", "$modal", "Group",
    function ($scope, $modal, Group) {
      $scope.remove = function() {
          Group.removeMember({
            member: $scope.member.email,
            id: $scope.group.id
          }, $scope.refreshGroup);
        }
    }
]);

app.controller("AddMemberController", ["$scope", "$stateParams", "$window", "$timeout", "Group",
    function ($scope, $stateParams, $window, $timeout, Group) {
      $scope.add = function() {
        if ($scope.newMember != "") {
          Group.addMember({
            member: $scope.newMember,
            id: $scope.group.id
          }, $scope.refreshGroup);
        }
      }
    }
  ]);

app.controller("InvitationsController", ["$scope", "$stateParams", "$window", "$timeout", "User", "Group",
    function ($scope, $stateParams, $window, $timeout, User, Group) {
      $scope.invitations = User.invitations({
        assignment: $stateParams.assignmentId
      });

      $scope.refreshInvitations = function() {
          $timeout(function() {
            $scope.invitations = User.invitations({
              assignment: $stateParams.assignmentId
            });
          }, 300);
      }

      $scope.accept = function(invitation, $event) {
        $event.stopPropagation();
        if ($scope.inGroup === false) {
          Group.acceptInvitation({
            id: invitation.id
          }, function() {
            $scope.refreshInvitations();
            $scope.refreshGroup();
          });
        } else {
        }
      }

      $scope.reject = function(invitation, $event) {
        $event.stopPropagation();
        Group.rejectInvitation({
          id: invitation.id
        }, $scope.refreshInvitations);
      }
    }
  ]);

<commit_msg>hardcode server course key in frontend :(<commit_after>
app.controller("CourseSelectorController", ["$scope", "$window", "$state", '$stateParams', 'Course',
    function ($scope, $window, $state, $stateParams, Course) {
      Course.get(function(response) {
        $scope.courses = response.results
        // TODO : Remove
        console.log($scope.courses)
      });
      if ($window.user.indexOf("berkeley.edu") == -1) {
        $window.swal({
            title: "Is this the right login?",
            text: "Logging you in with your \"" + $window.user + "\" account...",
            type: "info",
            showCancelButton: true,
            confirmButtonColor: "#DD6B55",
            confirmButtonText: "Yes - that's correct!",
            cancelButtonText: "No - log me out",
            closeOnConfirm: true,
            closeOnCancel: true
        }, function(isConfirm) {
            if (isConfirm) {
              // Do nothing, because the user might want to select a course.
            } else {
                $window.location.href = $window.reloginLink;
            }
        });
      } else {
         $window.location.hash = "";
      }
    }
]);

// Assignment Controllers
app.controller("AssignmentOverviewController", ['$scope', 'Assignment', 'User', '$timeout',
  function($scope, Assignment, User, $timeout) {
    Assignment.query(function(response) {
      $scope.assignments = response.results;
    })}
]);

// Assignment Controllers
app.controller("GroupOverviewController", ['$scope', 'Assignment', 'User', '$timeout',
  function($scope, Assignment, User, $timeout) {
    Group.query(function(response) {
      $scope.assignments = response.results;
    })}
]);

// Eeek.
app.controller("AssignmentDashController", ['$scope', 'Assignment', 'User', 'Group', '$timeout',
  function($scope, Assignment, User, Group, $timeout) {
      $scope.courseId = 5165212546105344;

      $scope.toggleAssign = function (assign) {
        if ($scope.currAssign == assign) {
          $scope.currAssign = null
        } else {
          $scope.currAssign = assign;
        }
      }

      $scope.reloadAssignments = function () {
          User.get({
            course: $scope.courseId,
          }, function (response) {
            console.log(response.assignments)
            $scope.assignments = response.assignments
          })
      }

      $scope.reloadAssignments()

      $scope.removeMember = function(currGroup, member) {
            Group.removeMember({
              member: member.key,
              id: currGroup.id
            }, function (err) {
              $scope.currGroup = null;
              $scope.hideGroup();
              $scope.currAssign.group = null
            });
      };

      $scope.getSubmissions = function (assignId) {
            User.getSubmissions({
              assignment: assignId
            }, function (response) {
              $scope.currAssign.submissions = response;
              $scope.showSubms();
            });
      }

      $scope.getBackups = function (assignId) {
            User.getBackups({
              assignment: assignId
            }, function (response) {
              $scope.currAssign.backups = response;
              $scope.showBackups();
            });
      }

        $scope.addMember = function(assignmentId, member) {
          if (member != '') {
            Assignment.invite({
              id: assignmentId,
              email: member
            }, function (response) {
              // TODO  Check for error.
              console.log(response)
            });
          }
        };

        $scope.showGroup = function showGroup(group) {
            $('.popups').addClass('active');
            $('.popup').removeClass('active');
            $('.popup.group').addClass('active').removeClass('hide');
            $scope.currGroup = group
        }

        $scope.hideGroup = function hideGroup() {
            $('.popups').removeClass('active');
            $('.popup').removeClass('active');
            $('.popup.group').addClass('active').addClass('hide');
        }

        $scope.showBackups = function showGroup(id) {
            $('.popups').addClass('active');
            $('.popup').removeClass('active');
            $('.popup.backups').addClass('active').removeClass('hide');
        }

        $scope.showSubms = function showGroup(id) {
            $('.popups').addClass('active');
            $('.popup').removeClass('active');
            $('.popup.submissions').addClass('active').removeClass('hide');
        }

        $scope.hidePopups =  function hidePopups() {
            $('.assign').removeClass('s');
            $('.popups').removeClass('active');
            $('.popup').removeClass('active');
            setTimeout(function() {
              $('.popup').addClass('hide');
            },400);
          }

        $scope.showLoader = function showLoader() {
          $('.loader').removeClass('hide');
        }

        $scope.hideLoader = function hideLoader() {
          $('.loader').addClass('done hide');
          setTimeout(function() {
            $('.loader').removeClass('done')
          },800)
        }

      }
]);

// Group Controllers
app.controller("GroupController", ["$scope", "$stateParams", "$window", "$timeout", "Group",
    function ($scope, $stateParams, $window, $timeout, Group) {
      $scope.loadGroup = function() {
        Group.query({
            assignment: $stateParams.assignmentId,
            members: $window.user
          }, function(groups) {
            if (groups.length == 1) {
              $scope.group = groups[0];
              $scope.inGroup = true;
            } else {
              $scope.group = undefined;
              $scope.inGroup = false;
            }
          }
        );
      }
      $scope.refreshGroup = function() {
          $timeout(function() {
            $scope.loadGroup();
          }, 300);
      }
      $scope.loadGroup();
      $scope.createGroup = function() {
        Group.save({
          assignment: $stateParams.assignmentId,
          members: $window.user
        }, $scope.refreshGroup);
      }
    }
  ]);

app.controller("MemberController", ["$scope", "$modal", "Group",
    function ($scope, $modal, Group) {
      $scope.remove = function() {
          Group.removeMember({
            member: $scope.member.email,
            id: $scope.group.id
          }, $scope.refreshGroup);
        }
    }
]);

app.controller("AddMemberController", ["$scope", "$stateParams", "$window", "$timeout", "Group",
    function ($scope, $stateParams, $window, $timeout, Group) {
      $scope.add = function() {
        if ($scope.newMember != "") {
          Group.addMember({
            member: $scope.newMember,
            id: $scope.group.id
          }, $scope.refreshGroup);
        }
      }
    }
  ]);

app.controller("InvitationsController", ["$scope", "$stateParams", "$window", "$timeout", "User", "Group",
    function ($scope, $stateParams, $window, $timeout, User, Group) {
      $scope.invitations = User.invitations({
        assignment: $stateParams.assignmentId
      });

      $scope.refreshInvitations = function() {
          $timeout(function() {
            $scope.invitations = User.invitations({
              assignment: $stateParams.assignmentId
            });
          }, 300);
      }

      $scope.accept = function(invitation, $event) {
        $event.stopPropagation();
        if ($scope.inGroup === false) {
          Group.acceptInvitation({
            id: invitation.id
          }, function() {
            $scope.refreshInvitations();
            $scope.refreshGroup();
          });
        } else {
        }
      }

      $scope.reject = function(invitation, $event) {
        $event.stopPropagation();
        Group.rejectInvitation({
          id: invitation.id
        }, $scope.refreshInvitations);
      }
    }
  ]);

<|endoftext|>


<commit_before>'use strict';

var Dota2 = require("../index");

var cacheTypeIDs = {
    // Legacy values
    LOBBY: 2004,
    PARTY: 2003,
    PARTY_INVITE: 2006,
    LOBBY_INVITE: 2011,
    // Actual values
    CSOEconItem : 1,
    CSOItemRecipe : 5,
    CSOEconGameAccountClient : 7,
    CSOSelectedItemPreset : 35,      // no longer exists in game files
    CSOEconItemPresetInstance : 36,  // no longer exists in game files
    CSOEconItemDropRateBonus : 38,
    CSOEconItemLeagueViewPass : 39,
    CSOEconItemEventTicket : 40,
    CSOEconItemTournamentPassport : 42,
    CSODOTAGameAccountClient : 2002,
    CSODOTAParty : 2003,
    CSODOTALobby : 2004,
    CSODOTAPartyInvite : 2006,
    CSODOTAGameHeroFavorites : 2007,
    CSODOTAMapLocationState : 2008,
    CMsgDOTATournament : 2009,
    CSODOTAPlayerChallenge : 2010,
    CSODOTALobbyInvite : 2011
};

// Handlers
function handleCreateType(obj_type, object_data) {
    switch(obj_type) {
        case cacheTypeIDs.CSOEconItem:
            this.Logger.debug("Received trade request");
            var item = Dota2.schema.lookupType("CSOEconItem").decode(object_data);
            this.emit("gotItem", item);
            this.Inventory.push(item);
            break;
    }
}

function handleSubscribedType(obj_type, object_data, isDelete) {
    switch (obj_type) {
        // Inventory item
        case cacheTypeIDs.CSOEconItem:
            this.Logger.debug("Received inventory snapshot");
            // Parse items
            var items = object_data.map(obj => Dota2.schema.lookupType("CSOEconItem").decode(obj));
            // Remove updated items from inventory
            var inv = this.Inventory.filter(item => items.reduce((acc, val) => acc && item.id.notEquals(val.id)), true);
            if (!isDelete) {
                // Put them back if it's not a delete
                inv = inv.concat(items);
            }
            this.emit("inventoryUpdate", inv);
            this.Inventory = inv;
            break;
        // Lobby snapshot.
        case cacheTypeIDs.CSODOTALobby:
            // object_data is an array when called from onCacheSubscribed
            // but an object when called from onUpdateMultiple
            var lobby = Dota2.schema.lookupType("CSODOTALobby").decode([].concat(object_data)[0]);
            this.Logger.debug("Received lobby snapshot for lobby ID " + lobby.lobby_id);
            this.emit("practiceLobbyUpdate", lobby);
            this.Lobby = lobby;
            break;
        // Lobby invite snapshot.
        case cacheTypeIDs.CSODOTALobbyInvite:
            var lobbyInvite = Dota2.schema.lookupType("CSODOTALobbyInvite").decode(object_data[0]);
            this.Logger.debug("Received lobby invite snapshot for group ID " + lobbyInvite.group_id);
            this.emit("lobbyInviteUpdate", lobbyInvite);
            this.LobbyInvite = lobbyInvite;
            break;
        // Party snapshot.
        case cacheTypeIDs.CSODOTAParty:
            var party = Dota2.schema.lookupType("CSODOTAParty").decode([].concat(object_data)[0]);
            this.Logger.debug("Received party snapshot for party ID " + party.party_id);
            this.emit("partyUpdate", party);
            this.Party = party;
            break;
        // Party invite snapshot.
        case cacheTypeIDs.CSODOTAPartyInvite:
            var party = Dota2.schema.lookupType("CSODOTAPartyInvite").decode(object_data[0]);
            this.Logger.debug("Received party invite snapshot for group ID " + party.group_id);
            this.emit("partyInviteUpdate", party);
            this.PartyInvite = party;
            break;
        default:
            this.Logger.warn("Unhandled cache ID: " + obj_type);
            break;
    }
};

Dota2.Dota2Client.prototype._handleWelcomeCaches = function handleWelcomeCaches(message) {
    var welcome = Dota2.schema.lookupType("CMsgClientWelcome").decode(message);
    var _self = this;

    if (welcome.outofdate_subscribed_caches)
        welcome.outofdate_subscribed_caches.forEach(function(cache) {
            cache.objects.forEach(function(obj) {
                handleSubscribedType.call(_self, obj.type_id, obj.object_data[0]);
            });
        });
};

// Events
/**
 * Emitted when the GC sends an inventory snapshot. The GC is incredibly
 * inefficient and will send the entire object even if it's a minor update.
 * You can use this to detect when a change was made to your inventory (e.g. drop)
 * Note that the {@link module:Dota2.Dota2Client#Inventory|Inventory} property will be the old value until after this event
 * completes to allow comparison between the two.
 * @event module:Dota2.Dota2Client#inventoryUpdate
 * @param {CSOEconItem[]} inventory - A list of `CSOEconItem` objects
 */
 /**
 * Emitted when the GC sends a lobby snapshot. The GC is incredibly
 * inefficient and will send the entire object even if it's a minor update.
 * You can use this to detect when a lobby has been entered / created
 * successfully as well. Note that the {@link module:Dota2.Dota2Client#Lobby|Lobby} property will be the old
 * value until after this event completes to allow comparison between the
 * two.
 * @event module:Dota2.Dota2Client#practiceLobbyUpdate
 * @param {CSODOTALobby} lobby - The new state of the lobby.
 */
 /**
 * Emitted when leaving a lobby (aka, the lobby is cleared). This can
 * happen when kicked, upon leaving a lobby, etc. There are other events
 * to tell when the bot has been kicked.
 * @event module:Dota2.Dota2Client#practiceLobbyCleared
 */
 /**
 * Emitted when the bot received an invite to a lobby
 * @event module:Dota2.Dota2Client#lobbyInviteUpdate
 * @param {CSODOTALobbyInvite} lobbyInvite - The invitation to a lobby.
 */
 /**
 * Emitted when the Lobby Invite is cleared, for example when
 * accepting/rejecting it or when the lobby is closed.
 * @event module:Dota2.Dota2Client#lobbyInviteCleared
 */
 /**
 * Emitted when the GC sends a party snapshot. The GC is incredibly
 * inefficient and will send the entire object even if it's a minor update.
 * You can use this to detect when a party has been entered / created
 * successfully as well. Note that the {@link module:Dota2.Dota2Client#Party|Party} property will be the old
 * value until after this event completes to allow comparison between the
 * two.
 * @event module:Dota2.Dota2Client#partyUpdate
 * @param {CSODOTAParty} party - The new state of the party.
 */
 /**
 * Emitted when leaving a party (aka, the party is cleared). This can
 * happen when kicked, upon leaving a party, etc. There are other callbacks
 * to tell when the bot has been kicked.
 * @event module:Dota2.Dota2Client#partyCleared
 */
 /**
 * Emitted when the GC sends a party invite snapshot. The GC is incredibly
 * inefficient and will send the entire object even if it's a minor update.
 * You can use this to detect when an incoming party invite has been sent.
 * Note that the {@link module:Dota2.Dota2Client#PartyInvite|PartyInvite} property will be the old
 * value until after this event completes to allow comparison between the two.
 * @event module:Dota2.Dota2Client#partyInviteUpdate
 * @param {CSODOTAPartyInvite} partyInvite - The invitation to a party.
 */
 /**
 * Emitted when the Party Invite is cleared, for example when
 * accepting/rejecting it or when the party is closed
 * @event module:Dota2.Dota2Client#partyInviteCleared
 */

var handlers = Dota2.Dota2Client.prototype._handlers;

var onCacheSubscribed = function onCacheSubscribed(message) {
    var subscribe = Dota2.schema.lookupType("CMsgSOCacheSubscribed").decode(message);
    var _self = this;

    this.Logger.debug("Cache(s) subscribed, type(s): " + subscribe.objects.map(obj=>obj.type_id).toString());

    subscribe.objects.forEach(function(obj) {
        handleSubscribedType.call(_self, obj.type_id, obj.object_data);
    });
};
handlers[Dota2.schema.lookupEnum("ESOMsg").values.k_ESOMsg_CacheSubscribed] = onCacheSubscribed;

var onUpdateMultiple = function onUpdateMultiple(message) {
    var multi = Dota2.schema.lookup("CMsgSOMultipleObjects").decode(message);
    var _self = this;

    let multi_types = ["objects_modified", "objects_added", "objects_removed"];
    multi_types.map((type, i) => {
        if (multi[type]) {
            let updates = {};
            multi[type].forEach(obj => {
                if (updates[obj.type_id]) updates[obj.type_id] = updates[obj.type_id].concat(obj.object_data);
                else updates[obj.type_id] = [obj.object_data];
            });
            for (let type in updates)
                handleSubscribedType.call(_self, parseInt(type), updates[type], i==2);
        }
    });

};
handlers[Dota2.schema.lookupEnum("ESOMsg").values.k_ESOMsg_UpdateMultiple] = onUpdateMultiple;

var onCreate = function onCreate(message) {
    var single = Dota2.schema.lookup("CMsgSOSingleObject").decode(message);
    var _self = this;

    this.Logger.debug("Create, type " + single.type_id);

    handleCreateType.call(_self, single.type_id, single.object_data);
}
handlers[Dota2.schema.lookupEnum("ESOMsg").values.k_ESOMsg_Create] = onCreate;

var onCacheUnsubscribed = function onCacheUnsubscribed(message) {
    var unsubscribe = Dota2.schema.lookup("CMsgSOCacheUnsubscribed").decode(message);
    var _self = this;

    this.Logger.debug("Cache unsubscribed, " + unsubscribe.owner_soid.id);

    if (this.Lobby && unsubscribe.owner_soid.id.eq(this.Lobby.lobby_id)) {
        this.Lobby = null;
        this.emit("practiceLobbyCleared");
    } else if (this.LobbyInvite && unsubscribe.owner_soid.id.eq(this.LobbyInvite.group_id)) {
        this.LobbyInvite = null;
        this.emit("lobbyInviteCleared");
    } else if (this.Party && unsubscribe.owner_soid.id.eq(this.Party.party_id)) {
        this.Party = null;
        this.emit("partyCleared");
    } else if (this.PartyInvite && unsubscribe.owner_soid.id.eq(this.PartyInvite.group_id)) {
        this.PartyInvite = null;
        this.emit("partyInviteCleared");
    }
};
handlers[Dota2.schema.lookupEnum("ESOMsg").values.k_ESOMsg_CacheUnsubscribed] = onCacheUnsubscribed;

var onCacheDestroy = function onCacheDestroy(message) {
    var destroy = Dota2.schema.lookup("CMsgSOSingleObject").decode(message);

    this.Logger.debug("Cache destroy, " + destroy.type_id);

    if (destroy.type_id === cacheTypeIDs.CSODOTAPartyInvite) {
        this.PartyInvite = null;
        this.emit("partyInviteCleared");
    }
    if (destroy.type_id === cacheTypeIDs.CSODOTALobbyInvite) {
        this.LobbyInvite = null;
        this.emit("lobbyInviteCleared");
    }
    if (destroy.type_id === cacheTypeIDs.CSOEconItem) {
        var item = Dota2.schema.lookupType("CSOEconItem").decode(destroy.object_data);
        this.Inventory = this.Inventory.filter(i => item.id.equals(i.id));
        this.emit("gaveItem", item);
    }
};
handlers[Dota2.schema.lookupEnum("ESOMsg").values.k_ESOMsg_Destroy] = onCacheDestroy;
<commit_msg>Update doc + move destroy handling to proper function<commit_after>'use strict';

var Dota2 = require("../index");

var cacheTypeIDs = {
    // Legacy values
    LOBBY: 2004,
    PARTY: 2003,
    PARTY_INVITE: 2006,
    LOBBY_INVITE: 2011,
    // Actual values
    CSOEconItem : 1,
    CSOItemRecipe : 5,
    CSOEconGameAccountClient : 7,
    CSOSelectedItemPreset : 35,      // no longer exists in game files
    CSOEconItemPresetInstance : 36,  // no longer exists in game files
    CSOEconItemDropRateBonus : 38,
    CSOEconItemLeagueViewPass : 39,
    CSOEconItemEventTicket : 40,
    CSOEconItemTournamentPassport : 42,
    CSODOTAGameAccountClient : 2002,
    CSODOTAParty : 2003,
    CSODOTALobby : 2004,
    CSODOTAPartyInvite : 2006,
    CSODOTAGameHeroFavorites : 2007,
    CSODOTAMapLocationState : 2008,
    CMsgDOTATournament : 2009,
    CSODOTAPlayerChallenge : 2010,
    CSODOTALobbyInvite : 2011
};

// Handlers
function handleCreateType(obj_type, object_data) {
    switch(obj_type) {
        case cacheTypeIDs.CSOEconItem:
            this.Logger.debug("Got an item traded");
            var item = Dota2.schema.lookupType("CSOEconItem").decode(object_data);
            this.emit("gotItem", item);
            this.Inventory.push(item);
            break;
    }
}

function handleDestroyType(obj_type, object_data) {
    switch(obj_type) {
        case cacheTypeIDs.CSODOTAPartyInvite:
            this.Logger.debug("Party invite cleared");
            this.PartyInvite = null;
            this.emit("partyInviteCleared");
            break;
        case cacheTypeIDs.CSODOTALobbyInvite:
            this.Logger.debug("Lobby invite cleared");
            this.LobbyInvite = null;
            this.emit("lobbyInviteCleared");
            break;
        case cacheTypeIDs.CSOEconItem:
            this.Logger.debug("Traded item away");
            var item = Dota2.schema.lookupType("CSOEconItem").decode(object_data);
            this.Inventory = this.Inventory.filter(i => item.id.equals(i.id));
            this.emit("gaveItem", item);
            break;
    }
}

function handleSubscribedType(obj_type, object_data, isDelete) {
    switch (obj_type) {
        // Inventory item
        case cacheTypeIDs.CSOEconItem:
            this.Logger.debug("Received inventory snapshot");
            // Parse items
            var items = object_data.map(obj => Dota2.schema.lookupType("CSOEconItem").decode(obj));
            // Remove updated items from inventory
            var inv = this.Inventory.filter(item => items.reduce((acc, val) => acc && item.id.notEquals(val.id)), true);
            if (!isDelete) {
                // Put them back if it's not a delete
                inv = inv.concat(items);
            }
            this.emit("inventoryUpdate", inv);
            this.Inventory = inv;
            break;
        // Lobby snapshot.
        case cacheTypeIDs.CSODOTALobby:
            // object_data is an array when called from onCacheSubscribed
            // but an object when called from onUpdateMultiple
            var lobby = Dota2.schema.lookupType("CSODOTALobby").decode([].concat(object_data)[0]);
            this.Logger.debug("Received lobby snapshot for lobby ID " + lobby.lobby_id);
            this.emit("practiceLobbyUpdate", lobby);
            this.Lobby = lobby;
            break;
        // Lobby invite snapshot.
        case cacheTypeIDs.CSODOTALobbyInvite:
            var lobbyInvite = Dota2.schema.lookupType("CSODOTALobbyInvite").decode(object_data[0]);
            this.Logger.debug("Received lobby invite snapshot for group ID " + lobbyInvite.group_id);
            this.emit("lobbyInviteUpdate", lobbyInvite);
            this.LobbyInvite = lobbyInvite;
            break;
        // Party snapshot.
        case cacheTypeIDs.CSODOTAParty:
            var party = Dota2.schema.lookupType("CSODOTAParty").decode([].concat(object_data)[0]);
            this.Logger.debug("Received party snapshot for party ID " + party.party_id);
            this.emit("partyUpdate", party);
            this.Party = party;
            break;
        // Party invite snapshot.
        case cacheTypeIDs.CSODOTAPartyInvite:
            var party = Dota2.schema.lookupType("CSODOTAPartyInvite").decode(object_data[0]);
            this.Logger.debug("Received party invite snapshot for group ID " + party.group_id);
            this.emit("partyInviteUpdate", party);
            this.PartyInvite = party;
            break;
        default:
            this.Logger.warn("Unhandled cache ID: " + obj_type);
            break;
    }
};

Dota2.Dota2Client.prototype._handleWelcomeCaches = function handleWelcomeCaches(message) {
    var welcome = Dota2.schema.lookupType("CMsgClientWelcome").decode(message);
    var _self = this;

    if (welcome.outofdate_subscribed_caches)
        welcome.outofdate_subscribed_caches.forEach(function(cache) {
            cache.objects.forEach(function(obj) {
                handleSubscribedType.call(_self, obj.type_id, obj.object_data[0]);
            });
        });
};

// Events
/**
 * Emitted when the GC sends an inventory snapshot. The GC is incredibly
 * inefficient and will send the entire object even if it's a minor update.
 * You can use this to detect when a change was made to your inventory (e.g. drop)
 * Note that the {@link module:Dota2.Dota2Client#Inventory|Inventory} property will be the old value until after this event
 * completes to allow comparison between the two.
 * @event module:Dota2.Dota2Client#inventoryUpdate
 * @param {CSOEconItem[]} inventory - A list of `CSOEconItem` objects
 */
/**
 * Emitted when you receive an item through a trade.
 * Note that the {@link module:Dota2.Dota2Client#Inventory|Inventory} property will be the old value until after this event
 * completes to allow comparison between the two.
 * @event module:Dota2.Dota2Client#gotItem
 * @param {CSOEconItem} item - `CSOEconItem` object describing the received item
 **/
/**
 * Emitted when you trade away an item.
 * Note that the {@link module:Dota2.Dota2Client#Inventory|Inventory} property will be the old value until after this event
 * completes to allow comparison between the two.
 * @event module:Dota2.Dota2Client#gaveItem
 * @param {CSOEconItem} item - `CSOEconItem` object describing the traded item
 **/
 /**
 * Emitted when the GC sends a lobby snapshot. The GC is incredibly
 * inefficient and will send the entire object even if it's a minor update.
 * You can use this to detect when a lobby has been entered / created
 * successfully as well. Note that the {@link module:Dota2.Dota2Client#Lobby|Lobby} property will be the old
 * value until after this event completes to allow comparison between the
 * two.
 * @event module:Dota2.Dota2Client#practiceLobbyUpdate
 * @param {CSODOTALobby} lobby - The new state of the lobby.
 */
 /**
 * Emitted when leaving a lobby (aka, the lobby is cleared). This can
 * happen when kicked, upon leaving a lobby, etc. There are other events
 * to tell when the bot has been kicked.
 * @event module:Dota2.Dota2Client#practiceLobbyCleared
 */
 /**
 * Emitted when the bot received an invite to a lobby
 * @event module:Dota2.Dota2Client#lobbyInviteUpdate
 * @param {CSODOTALobbyInvite} lobbyInvite - The invitation to a lobby.
 */
 /**
 * Emitted when the Lobby Invite is cleared, for example when
 * accepting/rejecting it or when the lobby is closed.
 * @event module:Dota2.Dota2Client#lobbyInviteCleared
 */
 /**
 * Emitted when the GC sends a party snapshot. The GC is incredibly
 * inefficient and will send the entire object even if it's a minor update.
 * You can use this to detect when a party has been entered / created
 * successfully as well. Note that the {@link module:Dota2.Dota2Client#Party|Party} property will be the old
 * value until after this event completes to allow comparison between the
 * two.
 * @event module:Dota2.Dota2Client#partyUpdate
 * @param {CSODOTAParty} party - The new state of the party.
 */
 /**
 * Emitted when leaving a party (aka, the party is cleared). This can
 * happen when kicked, upon leaving a party, etc. There are other callbacks
 * to tell when the bot has been kicked.
 * @event module:Dota2.Dota2Client#partyCleared
 */
 /**
 * Emitted when the GC sends a party invite snapshot. The GC is incredibly
 * inefficient and will send the entire object even if it's a minor update.
 * You can use this to detect when an incoming party invite has been sent.
 * Note that the {@link module:Dota2.Dota2Client#PartyInvite|PartyInvite} property will be the old
 * value until after this event completes to allow comparison between the two.
 * @event module:Dota2.Dota2Client#partyInviteUpdate
 * @param {CSODOTAPartyInvite} partyInvite - The invitation to a party.
 */
 /**
 * Emitted when the Party Invite is cleared, for example when
 * accepting/rejecting it or when the party is closed
 * @event module:Dota2.Dota2Client#partyInviteCleared
 */

var handlers = Dota2.Dota2Client.prototype._handlers;

var onCacheSubscribed = function onCacheSubscribed(message) {
    var subscribe = Dota2.schema.lookupType("CMsgSOCacheSubscribed").decode(message);
    var _self = this;

    this.Logger.debug("Cache(s) subscribed, type(s): " + subscribe.objects.map(obj=>obj.type_id).toString());

    subscribe.objects.forEach(function(obj) {
        handleSubscribedType.call(_self, obj.type_id, obj.object_data);
    });
};
handlers[Dota2.schema.lookupEnum("ESOMsg").values.k_ESOMsg_CacheSubscribed] = onCacheSubscribed;

var onUpdateMultiple = function onUpdateMultiple(message) {
    var multi = Dota2.schema.lookup("CMsgSOMultipleObjects").decode(message);
    var _self = this;

    let multi_types = ["objects_modified", "objects_added", "objects_removed"];
    multi_types.map((type, i) => {
        if (multi[type]) {
            let updates = {};
            multi[type].forEach(obj => {
                if (updates[obj.type_id]) updates[obj.type_id] = updates[obj.type_id].concat(obj.object_data);
                else updates[obj.type_id] = [obj.object_data];
            });
            for (let type in updates)
                handleSubscribedType.call(_self, parseInt(type), updates[type], i==2);
        }
    });

};
handlers[Dota2.schema.lookupEnum("ESOMsg").values.k_ESOMsg_UpdateMultiple] = onUpdateMultiple;

var onCreate = function onCreate(message) {
    var single = Dota2.schema.lookup("CMsgSOSingleObject").decode(message);
    var _self = this;

    this.Logger.debug("Create, type " + single.type_id);

    handleCreateType.call(_self, single.type_id, single.object_data);
}
handlers[Dota2.schema.lookupEnum("ESOMsg").values.k_ESOMsg_Create] = onCreate;

var onCacheUnsubscribed = function onCacheUnsubscribed(message) {
    var unsubscribe = Dota2.schema.lookup("CMsgSOCacheUnsubscribed").decode(message);
    var _self = this;

    this.Logger.debug("Cache unsubscribed, " + unsubscribe.owner_soid.id);

    if (this.Lobby && unsubscribe.owner_soid.id.eq(this.Lobby.lobby_id)) {
        this.Lobby = null;
        this.emit("practiceLobbyCleared");
    } else if (this.LobbyInvite && unsubscribe.owner_soid.id.eq(this.LobbyInvite.group_id)) {
        this.LobbyInvite = null;
        this.emit("lobbyInviteCleared");
    } else if (this.Party && unsubscribe.owner_soid.id.eq(this.Party.party_id)) {
        this.Party = null;
        this.emit("partyCleared");
    } else if (this.PartyInvite && unsubscribe.owner_soid.id.eq(this.PartyInvite.group_id)) {
        this.PartyInvite = null;
        this.emit("partyInviteCleared");
    }
};
handlers[Dota2.schema.lookupEnum("ESOMsg").values.k_ESOMsg_CacheUnsubscribed] = onCacheUnsubscribed;

var onCacheDestroy = function onCacheDestroy(message) {
    var single = Dota2.schema.lookup("CMsgSOSingleObject").decode(message);

    this.Logger.debug("Cache destroy, " + single.type_id);

    handleDestroyType.call(_self, single.type_id, single.object_data);
};
handlers[Dota2.schema.lookupEnum("ESOMsg").values.k_ESOMsg_Destroy] = onCacheDestroy;
<|endoftext|>


<commit_before>"use strict"

var SpansObject;

var docgeoApplier;
var docgeoUnapplier;
var docgeoApplier_geo;

var docgeoClass = "docgeo"
var annotationClasses = [docgeoClass]

function addDocGeo() {
    addAnnotation(docgeoClass, docgeoApplier)
}

function init() {
    commonMapInit()

    SpansObject = Parse.Object.extend("DocGeoSpans");

    docgeoApplier = rangy.createClassApplier(docgeoClass, {
        elementAttributes: {onclick:"spanClick(this)"},
        normalize: false
    });
    docgeoUnapplier = rangy.createClassApplier(docgeoClass, {
        elementAttributes: {onclick:"spanClick(this)"},
        normalize: true
    });

    docgeoApplier_geo = rangy.createClassApplier(docgeoClass, {
        elementAttributes: {onclick:"spanClick(this)"}, geo:"1",
        normalize: false
    });

    annotationClassesAndAppliers = [
        {clazz: docgeoClass, applier: docgeoApplier, geoapplier: docgeoApplier_geo, unapplier: docgeoUnapplier}
    ]

    keyCodeActions = [
        {code: 65, action: addDocGeo},
        {code: 82, action: removeAnnotation}
    ]

    isDocGeo = true
}

// Set 4-space indentation for vi
// vi:sw=4
<commit_msg>fixed coloring in docgeo applier<commit_after>"use strict"

var SpansObject;

var docgeoApplier;
var docgeoUnapplier;
var docgeoApplier_geo;

var docgeoClass = "docgeo"
var annotationClasses = [docgeoClass]

function addDocGeo() {
    addAnnotation(docgeoClass, docgeoApplier)
}

function init() {
    commonMapInit()

    SpansObject = Parse.Object.extend("DocGeoSpans");

    docgeoApplier = rangy.createClassApplier(docgeoClass, {
        elementAttributes: {onclick:"spanClick(this)"},
        normalize: false
    });
    docgeoUnapplier = rangy.createClassApplier(docgeoClass, {
        elementAttributes: {onclick:"spanClick(this)"},
        normalize: true
    });

    docgeoApplier_geo = rangy.createClassApplier(docgeoClass, {
        elementAttributes: {onclick:"spanClick(this)", geo:"1"},
        normalize: false
    });

    annotationClassesAndAppliers = [
        {clazz: docgeoClass, applier: docgeoApplier, geoapplier: docgeoApplier_geo, unapplier: docgeoUnapplier}
    ]

    keyCodeActions = [
        {code: 65, action: addDocGeo},
        {code: 82, action: removeAnnotation}
    ]

    isDocGeo = true
}

// Set 4-space indentation for vi
// vi:sw=4
<|endoftext|>


<commit_before>var CSGO = require("../index"),
    util = require("util"),
    protos = require("../protos");

CSGO.CSGOClient.prototype.matchmakingStatsRequest = function() {
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready, please listen for the 'ready' event.");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending matchmaking stats request");
  }

  var payload = new protos.CMsgGCCStrike15_v2_MatchmakingClient2GCHello({});
  this._gc.send({msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchmakingClient2GCHello, proto: {}},
      payload.toBuffer());
};

CSGO.CSGOClient.prototype.playerProfileRequest = function(accountId, req_level, callback) {
  callback = callback || null;
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending player profile request");
  }

  var payload = new protos.CMsgGCCStrike15_v2_ClientRequestPlayersProfile({
    account_id: accountId,
    request_level: req_level || 32
  });
  this._gc.send({msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_ClientRequestPlayersProfile, proto: {}},
      payload.toBuffer(), callback);
};
CSGO.CSGOClient.prototype.requestCurrentLiveGames = function(callback) {
  callback = callback || null;
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending live matches");
  }

  var payload = new protos.CMsgGCCStrike15_v2_MatchListRequestCurrentLiveGames();
  this._gc.send({msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchListRequestCurrentLiveGames , proto: {}},
      payload.toBuffer(), callback);
};
CSGO.CSGOClient.prototype.requestLiveGameForUser = function(accountid, callback) {
  callback = callback || null;
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending live matches");
  }

  var payload = new protos.CMsgGCCStrike15_v2_MatchListRequestLiveGameForUser({
    accountid: accountid
  });
  this._gc.send({msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchListRequestLiveGameForUser , proto: {}},
      payload.toBuffer(), callback);
};

CSGO.CSGOClient.prototype.requestWatchInfoFriends = function(request, callback) {
  callback = callback || null;
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending watch info request");
  }

  var payload = new protos.CMsgGCCStrike15_v2_ClientRequestWatchInfoFriends(request);
  this._gc.send({msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_ClientRequestWatchInfoFriends2, proto: {}},
      payload.toBuffer(), callback);
};

CSGO.CSGOClient.prototype.requestGame = function(matchid, outcome, token, callback) {
  callback = callback || null;
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending info match request with ID of " + matchid);
  }

  var payload = new protos.CMsgGCCStrike15_v2_MatchListRequestFullGameInfo({

  });
  if(matchid){
    payload.matchid = matchid;
  }
  if(outcome){
    payload.outcomeid = outcome;
  }
  if(token){
    payload.token = token;
  }
  this._gc.send({msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchListRequestFullGameInfo, proto: {}},
      payload.toBuffer(), callback);
};

CSGO.CSGOClient.prototype.requestRecentGames = function(accid, callback) {
  callback = callback || null;
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending recent match request with ID of " + accid);
  }

  var payload = new protos.CMsgGCCStrike15_v2_MatchListRequestRecentUserGames({
    accountid: accid
  });
  this._gc.send(
      {
        msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchListRequestRecentUserGames,
        proto: {

        }
      },
      payload.toBuffer(), callback);
};
CSGO.CSGOClient.prototype.richPresenceRequest = function(steamids, callback){
  this._gc._client.send({
        msg: CSGO.EMsg.ClientRichPresenceRequest,
        proto: {
          routing_appid: 730
        }
      },
      new protos.schema.CMsgClientRichPresenceRequest({
        steamid_request: steamids
      }).toBuffer(), callback);
};
CSGO.CSGOClient.prototype.richPresenceUpload = function(rp, steamids, callback){
  var payload = new protos.schema.CMsgClientRichPresenceUpload();
  payload.rich_presence_kv = require("../VDF").encode(rp);
  if(this.debug){
      console.log(payload.rich_presence_kv);
  }
  if(steamids){
    payload.steamid_broadcast = steamids;
  }
  this._gc._client.send({
        msg: CSGO.EMsg.ClientRichPresenceUpload,
        proto: {
          routing_appid: 730
        }
      },
      payload.toBuffer(), callback);
};

var handlers = CSGO.CSGOClient.prototype._handlers;

handlers[CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchmakingGC2ClientHello] = function onMatchmakingStatsResponse(message) {
  var matchmakingStatsResponse = protos.CMsgGCCStrike15_v2_MatchmakingGC2ClientHello.decode(message);

  if (this.debug) {
    util.log("Received matchmaking stats");
  }
  this.emit("matchmakingStatsData", matchmakingStatsResponse);
};

handlers[CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_PlayersProfile] = function onPlayerProfileResponse(message) {
  var playerProfileResponse = protos.CMsgGCCStrike15_v2_PlayersProfile.decode(message);

  if (this.debug) {
    util.log("Received player profile");
  }
  this.emit("playerProfile", playerProfileResponse);
};

handlers[CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchList] = function(message) {
  var matchListResponse = protos.CMsgGCCStrike15_v2_MatchList.decode(message);

  if (this.debug) {
    util.log("Received match list");
  }
  this.emit("matchList", matchListResponse);
};
handlers[CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_WatchInfoUsers] = function(message){
  var response = protos.CMsgGCCStrike15_v2_WatchInfoUsers.decode(message);
  if(this.debug){
    util.log('Recieved watch info');
  }
  this.emit('watchList', response);
}
handlers[CSGO.EMsg.ClientRichPresenceInfo] = function(data) {
  var vdf = require('../VDF');
  var response_kv = protos.schema.CMsgClientRichPresenceInfo.decode(data);
  var output = {};
  for(var index in response_kv.rich_presence){
    if(response_kv.rich_presence.hasOwnProperty(index)){
      var rp = vdf.decode(response_kv.rich_presence[index].rich_presence_kv.toBuffer());
      if(rp.hasOwnProperty('RP')) {
        rp = rp.RP;
      }
      output[response_kv.rich_presence[index].steamid_user] = rp;
    }
  }
  this.emit('richPresenceInfo', output);
};
<commit_msg>Formatted rich presence debug message<commit_after>var CSGO = require("../index"),
    util = require("util"),
    protos = require("../protos");

CSGO.CSGOClient.prototype.matchmakingStatsRequest = function() {
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready, please listen for the 'ready' event.");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending matchmaking stats request");
  }

  var payload = new protos.CMsgGCCStrike15_v2_MatchmakingClient2GCHello({});
  this._gc.send({msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchmakingClient2GCHello, proto: {}},
      payload.toBuffer());
};

CSGO.CSGOClient.prototype.playerProfileRequest = function(accountId, req_level, callback) {
  callback = callback || null;
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending player profile request");
  }

  var payload = new protos.CMsgGCCStrike15_v2_ClientRequestPlayersProfile({
    account_id: accountId,
    request_level: req_level || 32
  });
  this._gc.send({msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_ClientRequestPlayersProfile, proto: {}},
      payload.toBuffer(), callback);
};
CSGO.CSGOClient.prototype.requestCurrentLiveGames = function(callback) {
  callback = callback || null;
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending live matches");
  }

  var payload = new protos.CMsgGCCStrike15_v2_MatchListRequestCurrentLiveGames();
  this._gc.send({msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchListRequestCurrentLiveGames , proto: {}},
      payload.toBuffer(), callback);
};
CSGO.CSGOClient.prototype.requestLiveGameForUser = function(accountid, callback) {
  callback = callback || null;
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending live matches");
  }

  var payload = new protos.CMsgGCCStrike15_v2_MatchListRequestLiveGameForUser({
    accountid: accountid
  });
  this._gc.send({msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchListRequestLiveGameForUser , proto: {}},
      payload.toBuffer(), callback);
};

CSGO.CSGOClient.prototype.requestWatchInfoFriends = function(request, callback) {
  callback = callback || null;
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending watch info request");
  }

  var payload = new protos.CMsgGCCStrike15_v2_ClientRequestWatchInfoFriends(request);
  this._gc.send({msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_ClientRequestWatchInfoFriends2, proto: {}},
      payload.toBuffer(), callback);
};

CSGO.CSGOClient.prototype.requestGame = function(matchid, outcome, token, callback) {
  callback = callback || null;
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending info match request with ID of " + matchid);
  }

  var payload = new protos.CMsgGCCStrike15_v2_MatchListRequestFullGameInfo({

  });
  if(matchid){
    payload.matchid = matchid;
  }
  if(outcome){
    payload.outcomeid = outcome;
  }
  if(token){
    payload.token = token;
  }
  this._gc.send({msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchListRequestFullGameInfo, proto: {}},
      payload.toBuffer(), callback);
};

CSGO.CSGOClient.prototype.requestRecentGames = function(accid, callback) {
  callback = callback || null;
  if (!this._gcReady) {
    if (this.debug) {
      util.log("GC not ready");
    }
    return null;
  }

  if (this.debug) {
    util.log("Sending recent match request with ID of " + accid);
  }

  var payload = new protos.CMsgGCCStrike15_v2_MatchListRequestRecentUserGames({
    accountid: accid
  });
  this._gc.send(
      {
        msg:CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchListRequestRecentUserGames,
        proto: {

        }
      },
      payload.toBuffer(), callback);
};
CSGO.CSGOClient.prototype.richPresenceRequest = function(steamids, callback){
  this._gc._client.send({
        msg: CSGO.EMsg.ClientRichPresenceRequest,
        proto: {
          routing_appid: 730
        }
      },
      new protos.schema.CMsgClientRichPresenceRequest({
        steamid_request: steamids
      }).toBuffer(), callback);
};
CSGO.CSGOClient.prototype.richPresenceUpload = function(rp, steamids, callback){
  var payload = new protos.schema.CMsgClientRichPresenceUpload();
  payload.rich_presence_kv = require("../VDF").encode(rp);
  if(this.debug){
      util.log("Rich presence Payload:")
      console.log(payload.rich_presence_kv);
  }
  if(steamids){
    payload.steamid_broadcast = steamids;
  }
  this._gc._client.send({
        msg: CSGO.EMsg.ClientRichPresenceUpload,
        proto: {
          routing_appid: 730
        }
      },
      payload.toBuffer(), callback);
};

var handlers = CSGO.CSGOClient.prototype._handlers;

handlers[CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchmakingGC2ClientHello] = function onMatchmakingStatsResponse(message) {
  var matchmakingStatsResponse = protos.CMsgGCCStrike15_v2_MatchmakingGC2ClientHello.decode(message);

  if (this.debug) {
    util.log("Received matchmaking stats");
  }
  this.emit("matchmakingStatsData", matchmakingStatsResponse);
};

handlers[CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_PlayersProfile] = function onPlayerProfileResponse(message) {
  var playerProfileResponse = protos.CMsgGCCStrike15_v2_PlayersProfile.decode(message);

  if (this.debug) {
    util.log("Received player profile");
  }
  this.emit("playerProfile", playerProfileResponse);
};

handlers[CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_MatchList] = function(message) {
  var matchListResponse = protos.CMsgGCCStrike15_v2_MatchList.decode(message);

  if (this.debug) {
    util.log("Received match list");
  }
  this.emit("matchList", matchListResponse);
};
handlers[CSGO.ECSGOCMsg.k_EMsgGCCStrike15_v2_WatchInfoUsers] = function(message){
  var response = protos.CMsgGCCStrike15_v2_WatchInfoUsers.decode(message);
  if(this.debug){
    util.log('Recieved watch info');
  }
  this.emit('watchList', response);
}
handlers[CSGO.EMsg.ClientRichPresenceInfo] = function(data) {
  var vdf = require('../VDF');
  var response_kv = protos.schema.CMsgClientRichPresenceInfo.decode(data);
  var output = {};
  for(var index in response_kv.rich_presence){
    if(response_kv.rich_presence.hasOwnProperty(index)){
      var rp = vdf.decode(response_kv.rich_presence[index].rich_presence_kv.toBuffer());
      if(rp.hasOwnProperty('RP')) {
        rp = rp.RP;
      }
      output[response_kv.rich_presence[index].steamid_user] = rp;
    }
  }
  this.emit('richPresenceInfo', output);
};
<|endoftext|>


<commit_before>"use strict";

require([__dirname + "/../low.js", __dirname + "/tools.js"], function (low, tools)
{

    exports.ListView = function ()
    {
        tools.defineProperties(this, {
            size: { get: size }
        });

        var that = this;
        var m_items = [];

        var m_listView = $(
            low.tag("ul").class("sh-listview")
            .html()
        );

        function size()
        {
            return m_items.length;
        }

        this.get = function ()
        {
            return m_listView;
        };

        this.add = function (item)
        {
            m_items.push(item);
            m_listView.append(item.get());
            that.sizeChanged();
        };

        this.insert = function (at, item)
        {
            if (at === m_items.length)
            {
                that.add(item);
            }
            else if (at >= 0 && at < m_items.length)
            {
                m_items = m_items.slice(0, at).concat([item]).concat(m_items.slice(at));
                item.get().insertBefore(m_listView.find("> *")[at]);
                that.sizeChanged();
            }
        };

        this.remove = function (at)
        {
            if (at >= 0 && at < m_items.length)
            {
                m_items.splice(at, 1);
                m_listView.find("> *")[at].remove();
                that.sizeChanged();
            }
        };

        this.item = function (n)
        {
            return m_items[n];
        };

        this.indexOf = function (item)
        {
            for (var i = 0; i < m_items.length; ++i)
            {
                if (m_items[i] === item)
                {
                    return i;
                }
            }
            return -1;
        };

        this.clear = function ()
        {
            m_listView.html("");
            m_items = [];
            that.sizeChanged();
        };

        tools.initAs(this, tools.VISUAL);
    };

});
<commit_msg>added ListView.scrollTo<commit_after>"use strict";

require([__dirname + "/../low.js", __dirname + "/tools.js"], function (low, tools)
{

    exports.ListView = function ()
    {
        tools.defineProperties(this, {
            size: { get: size }
        });

        var that = this;
        var m_items = [];

        var m_listView = $(
            low.tag("ul").class("sh-listview")
            .html()
        );

        function size()
        {
            return m_items.length;
        }

        this.get = function ()
        {
            return m_listView;
        };

        this.add = function (item)
        {
            m_items.push(item);
            m_listView.append(item.get());
            that.sizeChanged();
        };

        this.insert = function (at, item)
        {
            if (at === m_items.length)
            {
                that.add(item);
            }
            else if (at >= 0 && at < m_items.length)
            {
                m_items = m_items.slice(0, at).concat([item]).concat(m_items.slice(at));
                item.get().insertBefore(m_listView.find("> *")[at]);
                that.sizeChanged();
            }
        };

        this.remove = function (at)
        {
            if (at >= 0 && at < m_items.length)
            {
                m_items.splice(at, 1);
                m_listView.find("> *")[at].remove();
                that.sizeChanged();
            }
        };

        this.item = function (n)
        {
            return m_items[n];
        };

        this.indexOf = function (item)
        {
            for (var i = 0; i < m_items.length; ++i)
            {
                if (m_items[i] === item)
                {
                    return i;
                }
            }
            return -1;
        };

        this.scrollTo = function (item)
        {
            for (var i = 0; i < m_items.length; ++i)
            {
                if (m_items[i] === item)
                {
                    $(document).scrollTop(item.get().offset().top - $(window).height() / 2);
                }
            }
        };

        this.clear = function ()
        {
            m_listView.html("");
            m_items = [];
            that.sizeChanged();
        };

        tools.initAs(this, tools.VISUAL);
    };

});
<|endoftext|>


<commit_before>var _ = require('lodash'),
    qs = require('../parsers/qs');

module.exports = function (model) {
    var middlewares = [];

    middlewares.push(function (req, res, next) {
        var options = {},
            keys = {};

        model = req.model || model;

        keys.model = _.keys(model.rawAttributes);
        keys.query = _.keys(req.query);
        keys.filters = _.intersection(keys.model, keys.query);

        options.attributes = qs.fields(req.query.fields);
        options.limit = qs.limit(req.query.limit) || 50;
        options.offset = qs.offset(req.query.offset);
        options.order = qs.sort(req.query.sort);
        options.where = qs.filters(_.pick(req.query, keys.filters));

        options = _.omit(options, _.isNull);

        req.options = _.merge({}, options, req.options);

        next();
    });

    middlewares.push(function (req, res, next) {
        var options = req.options;

        model
            .findAndCountAll(options)
            .then(respond)
            .catch(next);

        function respond(result) {
            var count = result.count,
                start = options.offset,
                end = options.offset + options.limit;

            if (end >= count) {
                end = count;
                res.status(200);
            } else {
                res.status(206);
            }

            res.set('Content-Range', start + '-' + end + '/' + count);
            res.send(result.rows);
        }
    });

    return middlewares;
};<commit_msg>Fixed a lodash call.<commit_after>var _ = require('lodash'),
    qs = require('../parsers/qs');

module.exports = function (model) {
    var middlewares = [];

    middlewares.push(function (req, res, next) {
        var options = {},
            keys = {};

        model = req.model || model;

        keys.model = _.keys(model.rawAttributes);
        keys.query = _.keys(req.query);
        keys.filters = _.intersection(keys.model, keys.query);

        options.attributes = qs.fields(req.query.fields);
        options.limit = qs.limit(req.query.limit) || 50;
        options.offset = qs.offset(req.query.offset);
        options.order = qs.sort(req.query.sort);
        options.where = qs.filters(_.pick(req.query, keys.filters));

        options = _.omitBy(options, _.isNull);

        req.options = _.merge({}, options, req.options);

        next();
    });

    middlewares.push(function (req, res, next) {
        var options = req.options;

        model
            .findAndCountAll(options)
            .then(respond)
            .catch(next);

        function respond(result) {
            var count = result.count,
                start = options.offset,
                end = options.offset + options.limit;

            if (end >= count) {
                end = count;
                res.status(200);
            } else {
                res.status(206);
            }

            res.set('Content-Range', start + '-' + end + '/' + count);
            res.send(result.rows);
        }
    });

    return middlewares;
};<|endoftext|>