首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >存储学生考试成绩的系统的角分量

存储学生考试成绩的系统的角分量
EN

Code Review用户
提问于 2017-03-16 16:03:50
回答 1查看 168关注 0票数 6

我正在设计一个系统,其中有一个视图,教师可以看到学生的测试数据摘要。以下是它的组成部分:

代码语言:javascript
复制
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';

import { Student } from '../../models/student'
import { StudentsService } from '../../services/students.service';
import { Test } from '../../models/test'
import { TestsService } from '../../services/tests.service';

@Component({
  selector: 'app-teacher',
  providers: [ StudentsService, TestsService ],
  templateUrl: './teacher.component.html',
  styleUrls: ['./teacher.component.css']
})
export class TeacherComponent implements OnInit {

  // Local properties
  students: Student[];
  student_search_filter: string = '';
  num_items: number = 10000;
  page: number = 1;
  orderBy: string = 'last_name';
  subject: string = 'math';
  options: Object = { title : { text : 'Loading...'} };
  tests: Test[];
  testsInSession: Test[][];
  testsCount: number[] = [0,0,0];
  mean: number[] = [0,0,0];
  median: number[] = [0,0,0];
  sessions: string[] = ['Winter 2017','Fall 2016','Spring 2016'];
  scores: number[][];
  chartData: Object[][];

  constructor(private router: Router, private route: ActivatedRoute, private testService: TestsService, private studentService: StudentsService) { }

  ngOnInit() {
    this.route.params.subscribe(params => { 
        this.subject = (params['subject'].charAt(0).toUpperCase() + params['subject'].slice(1)); // Uppercase first letter and set the subject from the URL
        /*** Reset Variable ***/
        this.chartData = [];
        this.testsInSession = [];
        this.scores = [];
        for(var testsSessions = 0; testsSessions < this.sessions.length; testsSessions++){
            this.chartData[testsSessions] = [{}];
            this.testsInSession[testsSessions] = [];
            this.scores[testsSessions] = [];
        }
        this.testsCount = [0,0,0];
        this.mean = [0,0,0];
        this.median = [0,0,0];
        /**********************/
        this.createCharts(); // Load blank placeholder chart until data is loaded
        this.loadStudents();
    });
  }

  // Load the students from the API and then call function to load tests
  loadStudents() {
    this.studentService.getStudents(this.page, this.num_items, this.student_search_filter, this.orderBy)
    .subscribe(
        students => {
            this.students = students, //Assign returned students to local property
            this.loadStudentTests();
        },
        err => { console.log(err); });
  }

  // Load tests froms API of given students and then call function to generate the graph
  loadStudentTests() {
    let studentIDs: string = '';
    for(var studentsI = 0; studentsI < this.students.length; studentsI++){
        studentIDs += this.students[studentsI].student_id + '||';
    }
    studentIDs = studentIDs.slice(0, -2);

    this.testService.getTestScores([{ 'test_type': this.subject },{ 'student_id': studentIDs }])
    .subscribe(
       chartDataFromApi => { 
         this.tests = chartDataFromApi; // Assign returned tests to local property
         for(var testsSessions = 0; testsSessions < this.sessions.length; testsSessions++){
            for(var testsI = 0; testsI < this.tests.length; testsI++){
                if (this.tests[testsI].test_season == this.sessions[testsSessions]){ // If test sessions matches current session, add to these variables
                    this.testsInSession[testsSessions].push(this.tests[testsI]);
                    this.chartData[testsSessions].push({ "name":this.tests[testsI].student_id, "x":Number(this.testsCount[testsSessions]), "y": Number(this.tests[testsI].score) }, );
                    this.testsCount[testsSessions]++;
                }
            }
         }
         this.getStats();
       }, 
       err => { console.log(err); });
  }

  getStats(){
    for(var testsSessions = 0; testsSessions < this.sessions.length; testsSessions++){ 
        for(var testsI = 0; testsI < this.testsInSession[testsSessions].length; testsI++){
            this.mean[testsSessions]+=Number(this.testsInSession[testsSessions][testsI].score);
            this.scores[testsSessions].push(Number(this.testsInSession[testsSessions][testsI].score));
        }

        /* Calculate Median */
        this.scores[testsSessions].sort((a, b) => a - b);
        let lowMiddle = Math.floor((this.scores[testsSessions].length - 1) / 2);
        let highMiddle = Math.ceil((this.scores[testsSessions].length - 1) / 2);
        this.median[testsSessions] = (this.scores[testsSessions][lowMiddle] + this.scores[testsSessions][highMiddle]) / 2;
        /* -Median- */

        this.mean[testsSessions]=+(this.mean[testsSessions]/this.testsCount[testsSessions]).toFixed(2);
    }
    this.createCharts();
  }

  // Function to calcuate percentiles for the given session
  getPercentile(session, percentile){
    const index = (percentile/100) * this.scores[session].length;
    if (Math.floor(index) == index){
        return (this.scores[session][index-1] + this.scores[session][index]/2)
    } else {
        return this.scores[session][Math.floor(index)];
    }
  }

  createCharts(){
    this.options = {
        chart: {
            type: 'scatter',
            zoomType: 'xy'
        },
        title : { text : this.subject},
        xAxis: {
            title: {
                enabled: true,
                text: 'Students'
            },
            labels: {
                enabled: false
            },
            minorTickLength: 0,
            tickLength: 0
        },
        yAxis: {
            title: {
                text: 'Scores'
            }
        },
        plotOptions: {
            scatter: {
                marker: {
                    radius: 5,
                    states: {
                        hover: {
                            enabled: true,
                            lineColor: 'rgb(100,100,100)'
                        }
                    }
                },
                states: {
                    hover: {
                        marker: {
                            enabled: false
                        }
                    }
                },
                tooltip: {
                    headerFormat: '<b>{series.name}</b><br>',
                    pointFormat: '{point.name}<br />Score: {point.y}'
                }
            }
        },
        series: [{
            name: this.sessions[0],
            color: 'rgba(223, 83, 83, .5)',
            data: this.chartData[0]
        },{
            name: this.sessions[1],
            color: 'rgba(119, 152, 191, .5)',
            data: this.chartData[1]
        },{
            name: this.sessions[2],
            color: 'rgba(80, 180, 50, .5)',
            data: this.chartData[2]
        }],
        credits: {
            enabled: false
        }
      };
  }

}

辅助档案:

我特别担心的是,我是否应该在这里或在另一个文件中进行平均、百分位数等计算。另外,是否有更好的方法来使用/设置本地属性?我想在整个视图中使用它们,但是当我选择不同的主题时,我似乎需要在ngOnInit中重新设置它们。

EN

回答 1

Code Review用户

发布于 2018-08-27 17:03:59

看起来你只是在一个组件上做所有的事情。这就是你现在应该如何创造角质成分。

在创建组件时,应该记住一条经验法则。也就是说,“组件的目的只应是向用户呈现数据,并让用户与数据交互”。

记住这个大拇指规则,我们就可以创建所谓的Skinny组件。

尽管如此,组件中应该存在的唯一代码应该是从服务中获取数据,然后将其显示给用户。如果需要对数据执行操作,则应将其委托给服务。

我在代码中看到的另一件事是,providers: [ StudentsService, TestsService ],。不知道你是不是故意这么做的。但是这样做将为TeacherComponent及其子服务创建这些服务的单独实例。

我要指出的最后一件事是,TeacherComponent中有几件事情,如createChartsgetPercentilegetStats等,所有这些都应该作为子组件的一部分来完成,然后子组件将依赖于服务以适当的形式获取适当的数据。

希望这能有所帮助。如果您需要更多的评论来获得更好的、更松散的耦合和更好的分离关注点,请让我知道。如果您能够创建一个StackBliz项目并在这里共享它,这样其他人就可以查看它,这也会有所帮助。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/157951

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档