﻿/*********************************************************************************
 * 순천향 대학교
 * 
 * 2007/09/10
 * 
 * 윈도우프로그래밍 C# 과제물
 * 
 * 담당 교수님: 이상정
 * 
 * 
 * 학과: 정보기술 공학부
 * 학번: 20022845
 * 이름: 이원재
 * 메일: mellowlee@naver.com
 * 
 * 
 * -과제물 목표-
 * 
 * 2장의 성적 프로그램을 개선하여 다음과 같이 프로그램을 작성하라.
 * 
 * • 학생의 번호,이름, 점수 등의 자료를 배열 대신 클래스로 정의
 * • 학생 별 총점, 평균, 석차 계산
 * • 과목별 총점,평균
 * • 학생의 이름과 번호로 검색하여 점수를 출력
 *  
 * 
 * ******************************************************************************/


using System;
using System.Collections;   //ArrayList Class를 사용하기 위해서 필요한 Namespace

/*********************************************
 * 
 * Class Student 
 * 
 * ●멤버 변수
 * 
 * 학번, 이름, 성적(국어, 영어, 수학),
 * 총점, 평균
 * 
 * ●멤버 함수
 * 
 * Student(int, string)
 * CompareTo(object)
 * SetScore()
 * SetStudent(int, int, int)
 * GetStudentMath()
 * GetStudentEng()
 * GetStudentKor()
 * GetStudentAverage()
 * GetStudentNumber()
 * GetStudentName()
 * GetStudentSum()
 * 
 *  
 * *******************************************/

class Student : IComparable
{
    private readonly int iStudentNumber;    // 학생 학번
    private readonly string sStudentName;   // 학생 이름
    private int iKorean;    // 국어 성적
    private int iEnglish;   // 영어 성적
    private int iMath;      // 수학 성적
    private int iSum;       // 국&영&수 총점
    private float fAverage; // 국&영&수 평균

    /******************************************
     * 
     * 생성자
     *  
     ******************************************/
    public Student(int iStudentNumber, string sStudentName) // 생성자 - 학생의 학번과 이름을 가지고 만든다.
    {
        this.iStudentNumber = iStudentNumber;
        this.sStudentName = sStudentName;
    }

    public Student(int iStudentNumber, string sStudentName, int iKorean, int iEnglish, int iMath)
    {
        this.iStudentNumber = iStudentNumber;
        this.sStudentName = sStudentName;
        this.iKorean = iKorean;
        this.iEnglish = iEnglish;
        this.iMath = iMath;
        SetScore();
    }

    /******************************************
     * 
     * InCompareable 의 Interface 부분
     *  
     ******************************************/

    public int CompareTo(object o)  // Compare의 Interface는 기본적으로 매개변수가 object이다. 이경우 boxing과 unboxing의 오버헤드가 발생한다.
    {
        Student s = (Student)o;

        int temp = (int)(this.fAverage - s.fAverage);// 정렬의 Key가 되는 클래스의 멤버는 fAvarage에 해당된다.

        if (temp > 0)
            return -1;
        else if (temp < 0)
            return 1;
        else
            return 0;
    }

    public int CompareTo(Student s) // CompareTo에 대한 오버로딩
    {
        int temp = (int)(this.fAverage - s.fAverage);// 정렬의 Key가 되는 클래스의 멤버는 fAvarage에 해당된다.

        if (temp > 0)
            return -1;
        else if (temp < 0)
            return 1;
        else
            return 0;

    }


    /******************************************
    * 
    * 각 멤버들에 변경하기 위한 함수들
    *  
    ******************************************/

    private void SetScore() //입력받은 국어 영어 수학의 성적을 가지고 총점과 평균을 계산하는 Function
    {
        this.iSum = this.iKorean + this.iEnglish + this.iMath;
        this.fAverage = iSum / 3;
    }

    public void SetStudent(int iKorean, int iEnglish, int iMath) // 국어 영어 수학 성적을 설정하는 Function
    {
        this.iKorean = iKorean;
        this.iEnglish = iEnglish;
        this.iMath = iMath;

        SetScore();
    }

    /******************************************
     * 
     * 각 멤버들에 접근하기 위한 함수들입니다.
     *  
     ******************************************/
    /******************************************
   * 
   * 각 멤버들에 접근하기 위한 함수들입니다.
   *  
   ******************************************/
    public int GetStudentMath(){return this.iMath;}
    public int GetStudentEng(){return this.iEnglish;}
    public int GetStudentKor(){return this.iKorean;}
    public int GetStudentSum() { return this.iSum; }
    public float GetStudentAverage(){return this.fAverage;}
    public int GetStudentNumber() {return this.iStudentNumber;}
    public string GetStudentName() {return this.sStudentName;}
}

class Show // 출력을 위한 Class
{
    public static void ShowMenu() // Main Menu를 출력하는 Method
    {
        Console.WriteLine();
        Console.WriteLine("◈성적 프로그램입니다.◈");
        Console.WriteLine("------------------------");
        Console.WriteLine("메뉴:1 학생 추가");
        Console.WriteLine("메뉴:2 성적 입력");
        Console.WriteLine("메뉴:3 학생 입력사항 보기");
        Console.WriteLine("메뉴:4 등수 보기");
        Console.WriteLine("메뉴:5 과목별 평균 보기");
        Console.WriteLine("메뉴:6 나가기");
        Console.WriteLine("메뉴:7 Special Menu (미리 저장된 Data를 출력합니다.)");
        Console.Write("숫자를 입력해주세요 ---> ");
    }
    /***********************************************
     * 
     * 현재 입력되어 있는 학생들의 학번과 이름을 출력합니다. 
     * 
     * 예)    
     *     20022845   이원재  
     *     
     **********************************************/
    public static void ShowDataSummary(Student s)
    {
        Console.WriteLine("{0} {1}", s.GetStudentNumber(), s.GetStudentName());
    }
    /***********************************************
   * 
   * 현재 입력되어 있는 학생들의 학번과 이름을 출력합니다. 
   * 
   * 예)   
   *     20022845   이원재  100 100 90 290 9
   *     
   **********************************************/
    public static void ShowData(Student s) //
    {
        Console.Write("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}", s.GetStudentNumber(),
                                                     s.GetStudentName(),
                                                     s.GetStudentKor(),
                                                     s.GetStudentEng(),
                                                     s.GetStudentMath(),
                                                     s.GetStudentSum(),
                                                     s.GetStudentAverage());

    }

    public static void ShowTitle()
    {
        Console.Write("학번\t\t이름\t국어\t영어\t수학\t총점\t평균\n");
        Console.WriteLine("------------------------------------------------------------");
        Console.WriteLine();
    }

    public static void ShowEnd()
    {
        Console.WriteLine();
        Console.WriteLine("           /:::::::　　　　＼　　　　　 　/　 ｜      |                        ");
        Console.WriteLine("         /::::::::::　　　　　 ￣─＿＿＿/　　｜       ＼ㅋㅋ 드뎌 다했다!!...");
        Console.WriteLine("　　   /::::::::::　　　　　　　　　　　　　　 ＼       ＼__________________");
        Console.WriteLine("　   /:::::::::　　　　　　　　　　　　　　　　　＼          ");
        Console.WriteLine("　 /:::::::::　　　　　＜　○ ＼　　　　　　　　 　＼        ");
        Console.WriteLine(" /::::::::　　　　　　　（￣￣（　　　　 　  /　○ > ｜      ");
        Console.WriteLine("｜::::::　　　　　　　　 ）　　  ）　　　　　＼￣ （￣（｜   ");
        Console.WriteLine("｜:::::::　　　　　　　（　　　（　　  ￣　　  ）　 ） ｜　  ");
        Console.WriteLine("｜::::::　　　　　　　  ）　　　）＿＿＿＿　　（　 （　｜    ");
        Console.WriteLine(" ＼::::::　　　　　　（　　　（   ＼──／　　  ）　）／　　 ");
        Console.WriteLine("　 ＼:::::　　　　　  ）　　　）　　　　　　  （　 （／      ");
        Console.WriteLine("　　 ＼　　　　　　（　　　（　　　　　　　 　      ／       ");
        Console.WriteLine();
    }
}



/*********************************************
 * 
 * Class TestResult
 * 
 *  
 * ●Main Function
 * 
 * Student(int, string)
 * CompareTo(object)
 * SetScore()
 * SetStudent(int, int, int)
 * GetStudentMath()
 * GetStudentEng()
 * GetStudentKor()
 * GetStudentAverage()
 * GetStudentNumber()
 * GetStudentName()
 * ShowDataSummary()
 * ShowData()
 * 
 * *******************************************/



class TestResult:Show
{
    public static void Main()
    {

        ArrayList aStudentList = new ArrayList();   //ArrayList를 생성하여 Student 객체를 저장할 것입니다.
        Student temp;// Student 클래스의 임시 객체를 만들어 놓았다.
        int iMenuValue = 0;// Menu의 key를 저장하기 위한 변수

        /******************************************
        * 
        * Main Procedure의 사작입니다.
        *  
        ******************************************/

        do
        {
            ShowMenu(); // Menu 출력
            iMenuValue = Convert.ToInt32(Console.ReadLine());// Menu 선택

            switch (iMenuValue)
            {
                case 1://메뉴:1 학생 추가
                    {
                        Console.Write("학번을 입력하세요.: ");
                        int iStudentNumber = Convert.ToInt32(Console.ReadLine());

                        Console.Write("이름을 입력하세요.: ");
                        string sStudentName = Console.ReadLine();

                        temp = new Student(iStudentNumber, sStudentName); // 학생에 대한 학번과 이름을 가지고 객체를 생성합니다.

                        /******************************************
                        * 
                        * 한번에 성적을 입력할 것인지 물어봅니다. 
                        * 
                        ******************************************/
                        Console.Write("성적을 입력하시겠습니까? \n (Y)es or (N)o : ");
                        string yn = Console.ReadLine(); // 성적을 추가 입력할지를 결정합니다.

                        int won = 0;// do_while 문의 Loop를 탈출하기 위한 Key입니다. 

                        do
                        {
                            if ((yn == "y") || (yn == "Y")) // 성적을 추가로 입력하는 경우입니다.
                            {
                                won = 0;
                                Console.Write("국어점수를 입력하세요: ");
                                int kor = Convert.ToInt32(Console.ReadLine());  // 국어점수를 입력 받습니다.
                                Console.Write("영어점수를 입력하세요: ");
                                int eng = Convert.ToInt32(Console.ReadLine());  // 영어점수를 입력 받습니다.
                                Console.Write("수학점수를 입력하세요: ");
                                int math = Convert.ToInt32(Console.ReadLine()); // 수학 점수를 입력 받습니다.

                                temp.SetStudent(kor, eng, math);

                            }
                            else if ((yn == "n") || (yn == "N")) // 성적을 추가로 입력하지 않는 경우입니다.
                            {
                                won = 0;
                                Console.WriteLine("수고하셨습니다.");
                            }
                            else
                            {
                                won = 1;
                                Console.WriteLine("잘못된 키를 누르셨습니다. 다시 눌러주세요.!!");

                            }
                        } while (won == 1);

                        /******************************************
                         * 
                         * ArrayList에 추가하는 부분 
                         * 
                         ******************************************/

                        aStudentList.Add(temp); // ArrayList에 객체를 추가 시킵니다.
                        aStudentList.Sort(); // 평균값에 의한 Sorting을 실행합니다.
                        // 새로운 객체가 ArrayList에 추가될때 마다 평균값에 의한 Sorting이 발생합니다.
                        // 기존의 객체가 새로운 값으로 변경될 경우 평균값에 의한 Sorting이 발생합니다.
                    }
                    break;

                case 2://메뉴:2 성적 입력
                    {
                        Console.WriteLine();
                        Console.WriteLine("학번\t\t이름\t");
                        Console.WriteLine();
                        foreach (Student s in aStudentList) // ArrayList에 등록된 Student 객체들을 각각 순환하면서 ShowDataSummary()함수를 실행시킨다.
                            ShowDataSummary(s);
                        Console.WriteLine();

                       /***********************************************
                        * 
                        * 위 학번과 이름을 보고 성적을 변경할 학생을 선택합니다. 
                        * 
                        * 학번을 기준으로 선택합니다.
                        * 
                        **********************************************/

                        Console.Write("찾고자하는 학생의 학번 or 이름을 입력하세요: ");
                        string stemp = Console.ReadLine();
                        int count = 0;
                        /*******************************************************
                         * 
                         * 학번 or 이름을 입력하면  
                         * 
                         * 학번일 경우와 이름일 경우를 나눠서 루틴을 실행시킨다.
                         * 
                         *******************************************************/
                        if ('0' <= (char)stemp[0] && (char)stemp[0] <= '9')
                        {
                            int iStudentNumber = Convert.ToInt32(stemp);

                            foreach (Student s in aStudentList)
                            {
                                if (s.GetStudentNumber() == iStudentNumber)
                                    break;
                                count++;
                            }
                        }
                        else
                        {
                            foreach (Student s in aStudentList)
                            {
                                if (s.GetStudentName() == stemp)
                                    break;
                                count++;
                            }
                        }
                        temp = (Student)aStudentList[count]; // 해당 학생을 ArrayList에서 찾았습니다.              

                       /***********************************************
                        * 
                        * 설정할 학점을 국어/영어/수학 순으로 입력하고 
                        * 
                        * 객체의 멤버를 초기화합니다.
                        * 
                        **********************************************/

                        Console.Write("국어점수를 입력하세요: ");
                        int kor = Convert.ToInt32(Console.ReadLine());
                        Console.Write("영어점수를 입력하세요: ");
                        int eng = Convert.ToInt32(Console.ReadLine());
                        Console.Write("수학점수를 입력하세요: ");
                        int math = Convert.ToInt32(Console.ReadLine());
                        temp.SetStudent(kor, eng, math);

                       /***********************************************
                        * 
                        * 새로운 값으로 객체가 초기화되었으므로 
                        * 
                        * ArrayList를 Sorting합니다.
                        * 
                        ***********************************************/


                        aStudentList.Sort();

                    }
                    break;

                case 3://메뉴:3 학생 입력사항 보기
                    {
                        Console.WriteLine();
                        foreach (Student s in aStudentList)
                            ShowDataSummary(s);
                        Console.WriteLine();

                       /**********************************************
                        * 
                        * 성적을 보고자하는 학생의 학번을 기입합니다. 
                        * 
                        **********************************************/

                        Console.Write("찾고자하는 학생의 학번 or 이름을 입력하세요: ");
                        string stemp = Console.ReadLine();
                        int count = 0;
                        /*******************************************************
                         * 
                         * 학번 or 이름을 입력하면  
                         * 
                         * 학번일 경우와 이름일 경우를 나눠서 루틴을 실행시킨다.
                         * 
                         *******************************************************/
                        if ('0' <= (char)stemp[0] && (char)stemp[0] <= '9')
                        {
                            int iStudentNumber = Convert.ToInt32(stemp);

                            foreach (Student s in aStudentList)
                            {
                                if (s.GetStudentNumber() == iStudentNumber)
                                    break;
                                count++;
                            }
                        }
                        else
                        {
                            foreach (Student s in aStudentList)
                            {
                                if (s.GetStudentName() == stemp)
                                    break;
                                count++;
                            }
                        }
                        temp = (Student)aStudentList[count];

                       /***********************************************
                        * 
                        * 출력문입니다.
                        * 
                        **********************************************/

                        Console.WriteLine();
                        ShowTitle();
                        ShowData(temp);
                        Console.WriteLine();
                    }
                    break;

                case 4://메뉴:4 등수 보기
                    {
                        int count = 1;
                        Console.WriteLine();
                        Console.WriteLine("석차\t학번\t\t이름\t\t평균");
                        Console.WriteLine("----------------------------------------------");
                        Console.WriteLine();

                        foreach (Student s in aStudentList)
                        {
                            Console.Write("Rank {0}\t", count++);
                            Console.WriteLine("{0}\t{1}\t\t{2}", s.GetStudentNumber(), s.GetStudentName(), s.GetStudentAverage());
                        }
                    }
                    break;

                case 5://메뉴:5 과목별 평균 보기
                    {
                        Console.Write("(K)or (E)ng (M)ath: ");
                        string lesson = Console.ReadLine();
                        int ClassSum = 0;

                       /***********************************************
                        * 
                        * 보고자하는 과목만의 평균을 보여줍니다.
                        * 
                        **********************************************/
                        Console.WriteLine("\n-------------------------");
                        
                        if (lesson == "K" || lesson == "k")
                        {

                            foreach (Student s in aStudentList)
                            {
                                ClassSum += s.GetStudentKor();
                            }

                            Console.WriteLine("국어의 평균은 {0} 입니다.", ClassSum / aStudentList.Count);
                        }
                        else if (lesson == "E" || lesson == "e")
                        {
                            foreach (Student s in aStudentList)
                            {
                                ClassSum += s.GetStudentEng();
                            }
                            Console.WriteLine("영어의 평균은 {0} 입니다.", ClassSum / aStudentList.Count);

                        }
                        else if (lesson == "M" || lesson == "m")
                        {
                            foreach (Student s in aStudentList)
                            {
                                ClassSum += s.GetStudentMath();
                            }
                            Console.WriteLine("수학의 평균은 {0} 입니다.", ClassSum / aStudentList.Count);
                        }

                        Console.WriteLine("-------------------------");
                    }
                    break;

                case 6://메뉴:6 나가기
                    {
                        /***********************************************
                        * 
                        * 끝(End !!)
                        * 
                        **********************************************/
                        ShowEnd();
                    }
                    break;

                case 7: // Special Menu
                    {                               // 학번      이름    KOR  ENG  MATH
                        Student[] aS = { new Student(20022845, "이원재", 100, 100, 100 ), 
                                         new Student(20022999, "홍길동",  90,  90, 100 ), 
                                         new Student(20022899, "양현종", 100,  90,  79 ), 
                                         new Student(20077777, "양순이",  89,  78,  10 ), 
                                         new Student(20012121, "장호성",  99,  77,  61 ), 
                                         new Student(20013123, "최원제",  71,  99,  74 ), 
                                         new Student(20008372, "권회경",  22, 100,  81 ), 
                                         new Student(19998382, "정음봉",  76, 100, 100 ), 
                                         new Student(19973938, "유병동",  77,  78,  54 )};

                        /***********************************************
                         * 
                         * 숙제를 위해서 미리 설정된 Data를 삽입합니다. 
                         * 
                         * 총 9명 입니다.
                         * 
                         **********************************************/

                        for (int i = 0; i < 9; i++)
                            aStudentList.Add(aS[i]);

                        aStudentList.Sort();

                        /***********************************************
                         * 
                         * 현재 입력되어 있는 학생들의 학번과 이름을 출력합니다. 
                         * 
                         * 예) 학번        이름
                         *     ----------------
                         *     20022845   이원재
                         *     20022899   홍길동
                         **********************************************/

                        Console.WriteLine();
                        Console.WriteLine("학번\t   이름\t");
                        Console.WriteLine("--------------------------");
                        Console.WriteLine();

                        foreach (Student s in aStudentList) // ArrayList에 등록된 Student 객체들을 각각 순환하면서 ShowDataSummary()함수를 실행시킨다.
                            ShowDataSummary(s);
                        Console.WriteLine();
                    }
                    break;

            }
        } while (!(iMenuValue == 6));
    }
}
