示例#1
0
        public QuickInputSemesterScoreForm(JHStudentRecord student)
            : this()
        {
            _student = student;
            JHScoreCalcRuleRecord record = student.ScoreCalcRule;

            _calculator = new ScoreCalculator(record);
            _util       = new SemesterHistoryUtility(JHSemesterHistory.SelectByStudentID(student.ID));
            _semesterScoreRecordList = JHSemesterScore.SelectByStudentID(_student.ID);

            errorProvider.SetError(cboSchoolYear, "無效的學年度");
            errorProvider.SetError(cboSemester, "無效的學期");
        }
        public ScoreCalculator(JHScoreCalcRuleRecord record)
        {
            if (record == null)
            {
                return;
            }

            XmlElement content = record.Content;

            XmlElement subject     = (XmlElement)content.SelectSingleNode("成績計算規則/各項成績計算位數/科目成績計算");
            XmlElement domain      = (XmlElement)content.SelectSingleNode("成績計算規則/各項成績計算位數/領域成績計算");
            XmlElement learnDomain = (XmlElement)content.SelectSingleNode("成績計算規則/各項成績計算位數/學習領域成績計算");
            XmlElement graduate    = (XmlElement)content.SelectSingleNode("成績計算規則/各項成績計算位數/畢業成績計算");

            if (subject != null)
            {
                _subjectRound.SetData(int.Parse(subject.GetAttribute("位數")), subject.GetAttribute("進位方式"));
            }
            if (domain != null)
            {
                _domainRound.SetData(int.Parse(domain.GetAttribute("位數")), domain.GetAttribute("進位方式"));
            }
            if (learnDomain != null)
            {
                _learnDomainRound.SetData(int.Parse(learnDomain.GetAttribute("位數")), learnDomain.GetAttribute("進位方式"));
            }
            if (graduate != null)
            {
                _graduateRound.SetData(int.Parse(graduate.GetAttribute("位數")), graduate.GetAttribute("進位方式"));
            }

            //ScoreCalcRule>
            //            <成績計算規則>
            //                <各項成績計算位數>
            //                    <學期科目成績計算 位數="2" 進位方式="四捨五入"/>
            //                    <學期領域成績計算 位數="2" 進位方式="四捨五入"/>
            //                    <學期學習領域成績計算 位數="2" 進位方式="四捨五入"/>
            //                    <畢業成績計算 位數="2" 進位方式="四捨五入"/>
        }
        public static void Calculate(List <StudentRecord> students)
        {
            const string LearnDomain = "學習領域";
            const string CourseLearn = "課程學習";

            ScoreCalcRule.Instance.SyncAllBackground();
            //SemesterScore.Instance.SyncAllBackground();
            Dictionary <string, List <JHSemesterScoreRecord> > studentSemesterScoreRecordCache = new Dictionary <string, List <JHSchool.Data.JHSemesterScoreRecord> >();

            foreach (JHSemesterScoreRecord record in JHSemesterScore.SelectByStudentIDs(students.AsKeyList()))
            {
                if (!studentSemesterScoreRecordCache.ContainsKey(record.RefStudentID))
                {
                    studentSemesterScoreRecordCache.Add(record.RefStudentID, new List <JHSchool.Data.JHSemesterScoreRecord>());
                }
                studentSemesterScoreRecordCache[record.RefStudentID].Add(record);
            }

            List <GradScoreRecordEditor> editors = new List <GradScoreRecordEditor>();

            BackgroundWorker worker = new BackgroundWorker();

            worker.WorkerReportsProgress = true;

            MultiThreadBackgroundWorker <GradScoreRecordEditor> multiWorker = new MultiThreadBackgroundWorker <GradScoreRecordEditor>();

            multiWorker.WorkerReportsProgress = true;
            multiWorker.AutoReportsProgress   = true;
            multiWorker.PackageSize           = 50;
            multiWorker.Loading = MultiThreadLoading.Light;

            worker.DoWork += delegate
            {
                Dictionary <string, ScoreCalculator> calc = new Dictionary <string, ScoreCalculator>();

                double studentTotal = students.Count;
                double studentCount = 0;

                foreach (StudentRecord student in students)
                {
                    studentCount++;

                    #region 取得成績計算規則
                    string calcID = string.Empty;
                    ScoreCalcRuleRecord calcRecord = student.GetScoreCalcRuleRecord();
                    if (calcRecord != null)
                    {
                        calcID = calcRecord.ID;
                        if (!calc.ContainsKey(calcID))
                        {
                            JHScoreCalcRuleRecord        record = null;
                            List <JHScoreCalcRuleRecord> list   = JHScoreCalcRule.SelectByIDs(new string[] { calcRecord.ID });
                            if (list.Count > 0)
                            {
                                record = list[0];
                            }
                            calc.Add(calcID, new ScoreCalculator(record));
                        }
                    }
                    else
                    {
                        if (!calc.ContainsKey(string.Empty))
                        {
                            calc.Add(string.Empty, new ScoreCalculator(null));
                        }
                    }
                    #endregion

                    #region 取得各學期成績
                    List <JHSemesterScoreRecord> semesterScoreRecordList;
                    if (studentSemesterScoreRecordCache.ContainsKey(student.ID))
                    {
                        semesterScoreRecordList = studentSemesterScoreRecordCache[student.ID];
                    }
                    else
                    {
                        semesterScoreRecordList = new List <JHSemesterScoreRecord>();
                    }
                    Dictionary <string, List <decimal> > domainScores = new Dictionary <string, List <decimal> >();

                    foreach (JHSemesterScoreRecord record in semesterScoreRecordList)
                    {
                        foreach (K12.Data.DomainScore domain in record.Domains.Values)
                        {
                            if (!domainScores.ContainsKey(domain.Domain))
                            {
                                domainScores.Add(domain.Domain, new List <decimal>());
                            }

                            if (domain.Score.HasValue)
                            {
                                domainScores[domain.Domain].Add(domain.Score.Value);
                            }
                        }

                        if (!domainScores.ContainsKey(LearnDomain))
                        {
                            domainScores.Add(LearnDomain, new List <decimal>());
                        }
                        if (record.LearnDomainScore.HasValue)
                        {
                            domainScores[LearnDomain].Add(record.LearnDomainScore.Value);
                        }

                        if (!domainScores.ContainsKey(CourseLearn))
                        {
                            domainScores.Add(CourseLearn, new List <decimal>());
                        }
                        if (record.CourseLearnScore.HasValue)
                        {
                            domainScores[CourseLearn].Add(record.CourseLearnScore.Value);
                        }
                    }
                    #endregion

                    #region 產生畢業成績資料
                    GradScoreRecordEditor editor;
                    GradScoreRecord       gradScoreRecord = GradScore.Instance.Items[student.ID];
                    if (gradScoreRecord != null)
                    {
                        editor = gradScoreRecord.GetEditor();
                    }
                    else
                    {
                        editor = new GradScoreRecordEditor(student);
                    }

                    editor.LearnDomainScore = null;
                    editor.CourseLearnScore = null;
                    editor.Domains.Clear();

                    foreach (string domain in domainScores.Keys)
                    {
                        decimal total = 0;
                        decimal count = domainScores[domain].Count;

                        if (count <= 0)
                        {
                            continue;
                        }

                        foreach (decimal score in domainScores[domain])
                        {
                            total += score;
                        }

                        total = total / count;
                        total = calc[calcID].ParseGraduateScore(total);


                        if (domain == LearnDomain)
                        {
                            editor.LearnDomainScore = total;
                        }
                        else if (domain == CourseLearn)
                        {
                            editor.CourseLearnScore = total;
                        }
                        else
                        {
                            if (!editor.Domains.ContainsKey(domain))
                            {
                                editor.Domains.Add(domain, new GradDomainScore(domain));
                            }
                            editor.Domains[domain].Score = total;
                        }
                    }

                    editors.Add(editor);
                    #endregion

                    worker.ReportProgress((int)(studentCount * 100 / studentTotal));
                }
            };
            worker.ProgressChanged += delegate(object sender, ProgressChangedEventArgs e)
            {
                FISCA.Presentation.MotherForm.SetStatusBarMessage("計算畢業成績中", e.ProgressPercentage);
            };
            worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
            {
                if (e.Error != null)
                {
                    MsgBox.Show("計算畢業成績時發生錯誤。" + e.Error.Message);
                    editors.Clear();
                }
                else
                {
                    multiWorker.RunWorkerAsync(editors);
                }
            };

            multiWorker.DoWork += delegate(object sender, PackageDoWorkEventArgs <GradScoreRecordEditor> e)
            {
                IEnumerable <GradScoreRecordEditor> list = e.Items;
                list.SaveAllEditors();
            };
            multiWorker.ProgressChanged += delegate(object sender, ProgressChangedEventArgs e)
            {
                FISCA.Presentation.MotherForm.SetStatusBarMessage("上傳畢業成績中", e.ProgressPercentage);
            };
            multiWorker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
            {
                if (e.Error != null)
                {
                    MsgBox.Show("上傳畢業成績時發生錯誤。" + e.Error.Message);
                }
                else
                {
                    FISCA.Presentation.MotherForm.SetStatusBarMessage("上傳畢業成績完成");
                }
            };

            worker.RunWorkerAsync();
        }
 public ScoreCalculator(JHScoreCalcRuleRecord record) : base(record)
 {
 }
        private void CalcWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            bool error = false;

            List <StudentRecord> students    = _students;
            List <string>        student_ids = new List <string>();

            foreach (StudentRecord each in students)
            {
                student_ids.Add(each.ID);
            }
            double total = students.Count;
            double count = 0;

            #region 寫入學期歷程
            if (_studentHistoryDict != null && _studentHistoryDict.Count > 0)
            {
                try
                {
                    List <JHSchool.Data.JHSemesterHistoryRecord> list = new List <JHSchool.Data.JHSemesterHistoryRecord>();
                    int    size   = 50;
                    double count2 = 0;
                    double total2 = _studentHistoryDict.Count;
                    foreach (JHSchool.Data.JHSemesterHistoryRecord record in _studentHistoryDict.Values)
                    {
                        if (_calc_worker.CancellationPending)
                        {
                            return;
                        }

                        list.Add(record);
                        count2++;
                        if (list.Count == size)
                        {
                            JHSchool.Data.JHSemesterHistory.Update(list);
                            list.Clear();
                            _calc_worker.ReportProgress((int)(count2 * 100 / total2), "寫入學期歷程中…");
                        }
                    }
                    if (list.Count > 0)
                    {
                        JHSchool.Data.JHSemesterHistory.Update(list);
                        list.Clear();
                        _calc_worker.ReportProgress(100, "學期歷程寫入完成");
                    }
                }
                catch (Exception ex)
                {
                    MsgBox.Show("寫入學期歷程失敗。" + ex.Message);
                    e.Result = null;
                    return;
                }
            }
            #endregion

            #region 計算課程成績

            _viewer.Clear();
            _viewer.SetHeader("課程");

            _calc_worker.ReportProgress(0, "計算課程成績…");

            if (_calc_worker.CancellationPending)
            {
                return;
            }
            _raw_data = new CourseDataLoader();
            _raw_data.LoadCalculationData(this, _students, intSchoolYear.Value, intSemester.Value);

            foreach (CW.Course course in _raw_data.Courses.Values)
            {
                if (string.IsNullOrEmpty(course.ExamTemplateId) && course.ExamRequired)
                {
                    _viewer.SetMessage(course.CourseName, new List <string>(new string[] { "缺少評量設定" }));
                    error = true;
                }
            }

            if (error)
            {
                e.Result = error;
                return;
            }

            _viewer.Clear();
            if (_calc_worker.CancellationPending)
            {
                return;
            }
            CourseScoreCalculate calculate = new CourseScoreCalculate(_raw_data.Courses);
            calculate.Calculate();

            foreach (CW.Course course in _raw_data.Courses.Values)
            {
                Dictionary <string, string> examLacks       = new Dictionary <string, string>();
                Dictionary <string, int>    examScoreLacks  = new Dictionary <string, int>();
                Dictionary <string, int>    examEffortLacks = new Dictionary <string, int>();

                List <CW.SCAttend> scattends         = new List <CW.SCAttend>();
                List <CW.SCAttend> no_exam_scattends = new List <CW.SCAttend>();
                foreach (CW.SCAttend scattend in course.SCAttends.Values)
                {
                    if (student_ids.Contains(scattend.StudentIdentity))
                    {
                        if (scattend.ContainsLack)
                        {
                            scattends.Add(scattend);
                        }
                        if (scattend.NoExam)
                        {
                            no_exam_scattends.Add(scattend);
                        }
                    }
                }

                foreach (CW.SCAttend scattend in scattends)
                {
                    foreach (string exam in scattend.ScoreLack)
                    {
                        if (!examLacks.ContainsKey(exam))
                        {
                            examLacks.Add(exam, "");
                        }

                        if (!examScoreLacks.ContainsKey(exam))
                        {
                            examScoreLacks.Add(exam, 0);
                        }
                        examScoreLacks[exam]++;
                    }

                    foreach (string exam in scattend.EffortLack)
                    {
                        if (!examLacks.ContainsKey(exam))
                        {
                            examLacks.Add(exam, "");
                        }

                        if (!examEffortLacks.ContainsKey(exam))
                        {
                            examEffortLacks.Add(exam, 0);
                        }
                        examEffortLacks[exam]++;
                    }
                }

                if (scattends.Count > 0)
                {
                    List <string> msgs = new List <string>();
                    foreach (string exam in new List <string>(examLacks.Keys))
                    {
                        if (examScoreLacks.ContainsKey(exam))
                        {
                            examLacks[exam] += "有" + examScoreLacks[exam] + "位學生缺少分數評量,";
                        }
                        if (examEffortLacks.ContainsKey(exam))
                        {
                            examLacks[exam] += "有" + examEffortLacks[exam] + "位學生缺少努力程度,";
                        }
                        if (!string.IsNullOrEmpty(examLacks[exam]))
                        {
                            examLacks[exam] = examLacks[exam].Substring(0, examLacks[exam].Length - 1);
                        }

                        msgs.Add(exam + ":" + examLacks[exam]);
                    }
                    _viewer.SetMessage(course.CourseName, msgs);
                    error = true;
                }

                if (no_exam_scattends.Count > 0)
                {
                    _viewer.SetMessage(course.CourseName, new List <string>(new string[] { "沒有設定各次評量" }));
                    error = true;
                }
            }

            if (error)
            {
                e.Result = true;
                return;
            }

            if (_calc_worker.CancellationPending)
            {
                return;
            }
            CourseScoreUpdater updater = new CourseScoreUpdater(_raw_data.Courses, this, false);
            updater.UpdateToServer();
            #endregion

            #region 計算學期成績

            //List<SemesterScoreRecordEditor> editors = new List<SemesterScoreRecordEditor>();
            List <JHSemesterScoreRecord> semesterScoreRecordList = new List <JHSchool.Data.JHSemesterScoreRecord>();

            JHSchool.Evaluation.SCAttend.Instance.SyncAllBackground();

            Dictionary <string, List <JHSemesterScoreRecord> > studentSemesterScoreCache = new Dictionary <string, List <JHSchool.Data.JHSemesterScoreRecord> >();
            foreach (JHSemesterScoreRecord record in JHSemesterScore.SelectByStudentIDs(students.AsKeyList()))
            {
                if (!studentSemesterScoreCache.ContainsKey(record.RefStudentID))
                {
                    studentSemesterScoreCache.Add(record.RefStudentID, new List <JHSchool.Data.JHSemesterScoreRecord>());
                }
                studentSemesterScoreCache[record.RefStudentID].Add(record);
            }

            count = 0;
            foreach (StudentRecord each in students)
            {
                count++;

                ScoreCalcRuleRecord   old       = GetScoreCalcRuleRecord(each);
                JHScoreCalcRuleRecord dalrecord = null;
                if (old != null)
                {
                    List <JHScoreCalcRuleRecord> list = JHScoreCalcRule.SelectByIDs(new string[] { old.ID });
                    if (list.Count > 0)
                    {
                        dalrecord = list[0];
                    }
                }
                ScoreCalculator calculator = new ScoreCalculator(dalrecord);

                List <SCAttendRecord> scattends = new List <SCAttendRecord>();
                foreach (SCAttendRecord scattend in JHSchool.Evaluation.SCAttend.Instance.GetStudentAttend(each.ID))
                {
                    CourseRecord course = scattend.Course;
                    if (course.SchoolYear == intSchoolYear.Value &&
                        course.Semester == intSemester.Value &&
                        !string.IsNullOrEmpty(course.RefAssessmentSetupID) &&
                        course.CalculationFlag == "1"
                        )
                    {
                        scattends.Add(scattend);
                    }
                }

                if (scattends.Count > 0)
                {
                    List <K12.Data.SubjectScore> subjectScores = _inner_calculator.CalculateSubjectScore(scattends);
                    foreach (K12.Data.SubjectScore subject in subjectScores)
                    {
                        subject.Score = calculator.ParseSubjectScore((decimal)subject.Score);
                    }
                    List <K12.Data.DomainScore> domainScores = _inner_calculator.CalculateDomainScore(subjectScores);
                    foreach (K12.Data.DomainScore domain in domainScores)
                    {
                        domain.Score = calculator.ParseDomainScore((decimal)domain.Score);
                    }

                    List <K12.Data.DomainScore> domainListWithoutElastic = new List <K12.Data.DomainScore>();
                    bool hasElasticCourse = false;
                    foreach (K12.Data.DomainScore domain in domainScores)
                    {
                        if (domain.Domain == "彈性課程")
                        {
                            hasElasticCourse = true;
                        }
                        else
                        {
                            domainListWithoutElastic.Add(domain);
                        }
                    }

                    decimal?learnDomainScore = calculator.ParseLearnDomainScore(_inner_calculator.CalculateTotalDomainScore(domainListWithoutElastic));
                    decimal?courseLearnScore = null;
                    if (hasElasticCourse)
                    {
                        courseLearnScore = calculator.ParseLearnDomainScore(_inner_calculator.CalculateTotalDomainScore(domainScores));
                    }

                    JHSemesterScoreRecord current = null;
                    if (studentSemesterScoreCache.ContainsKey(each.ID))
                    {
                        foreach (JHSemesterScoreRecord record in studentSemesterScoreCache[each.ID])
                        {
                            if (record.SchoolYear == intSchoolYear.Value && record.Semester == intSemester.Value)
                            {
                                current = record;
                            }
                        }
                    }

                    if (current != null)
                    {
                        //editor = current.GetEditor();
                        current.Subjects = new Dictionary <string, K12.Data.SubjectScore>();
                        current.Domains  = new Dictionary <string, K12.Data.DomainScore>();
                    }
                    else
                    {
                        //current = new SemesterScoreRecordEditor(each, intSchoolYear.Value, intSemester.Value, _gradeYears[each.ID]);
                        current = new JHSchool.Data.JHSemesterScoreRecord();
                        current.RefStudentID = each.ID;
                        current.SchoolYear   = intSchoolYear.Value;
                        current.Semester     = intSemester.Value;
                    }

                    foreach (K12.Data.SubjectScore subject in subjectScores)
                    {
                        current.Subjects.Add(subject.Subject, subject);
                    }
                    foreach (K12.Data.DomainScore domain in domainScores)
                    {
                        current.Domains.Add(domain.Domain, domain);
                    }
                    current.LearnDomainScore = learnDomainScore;
                    current.CourseLearnScore = courseLearnScore;

                    //editors.Add(editor);
                    semesterScoreRecordList.Add(current);
                }

                _calc_worker.ReportProgress((int)((double)count * 100 / (double)total), "計算學期成績…");
            }

            e.Result = semesterScoreRecordList;
            #endregion
        }