//Study10.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct TestResultStruct* TestResult;

typedef enum {
    TEST_TYPE_NATIONAL_LANG = 0,
    TEST_TYPE_MATH,
    TEST_TYPE_SCIENCE,
    TEST_TYPE_SOCIAL,
    TEST_TYPE_ENGLISH,
    TEST_TYPES_NUM
} TestTypes;

TestResult TestResult_Create(char ClassName, int StudentNo, const char* StudentName);
void TestResult_Delete(TestResult Result);

int TestResult_SetScore(TestResult Result, TestTypes TestType, int Score);
int TestResult_SetTotalScoreRank(TestResult Result);

char TestResult_GetClassName(TestResult Result);
int TestResult_GetStudentNo(TestResult Result);
const char* TestResult_GetStudentName(TestResult Result);
int TestResult_GetScore(TestResult Result, TestTypes TestType);
int TestResult_GetTotalScore(TestResult Result);
char TestResult_GetRank(TestResult Result);

const char* GetTestTypeName(TestTypes TestType);

int main (int argc, const char * argv[])
{
    char ClassName, *StudentName;
    int StudentNo, Score, i, j;
    TestResult Result;

    printf("クラスを入力して下さい\t");
    fflush(stdout);
    scanf("%c", &ClassName);

    printf("出席番号を入力して下さい\t");
    fflush(stdout);
    scanf("%d", &StudentNo);

    printf("名前を入力して下さい\t");
    fflush(stdout);
    StudentName = (char*)malloc(128);
    scanf("%s", StudentName);

    Result = TestResult_Create(ClassName, StudentNo, StudentName);

    for (i=0; i<TEST_TYPES_NUM; i++) {
        printf("%sを入力して下さい\t", GetTestTypeName(i));
        fflush(stdout);
        scanf("%d", &Score);
        TestResult_SetScore(Result, i, Score);
    }
    TestResult_SetTotalScoreRank(Result);

    printf("クラス:%c\t出席番号:%d\t名前:%s\n", TestResult_GetClassName(Result),
                                            TestResult_GetStudentNo(Result),
                                            TestResult_GetStudentName(Result));
    for (j=0; j<TEST_TYPES_NUM; j++)
        printf("%s:%d\t", GetTestTypeName(j), TestResult_GetScore(Result, j));
    printf("合計:%d\t", TestResult_GetTotalScore(Result));
    printf("評価:%c\n", TestResult_GetRank(Result));

    TestResult_Delete(Result);
    free(StudentName);
    return 0;
}

typedef struct TestResultStruct {
    char ClassName;
    int StudentNo;
    const char* StudentName;
    int Score[TEST_TYPES_NUM];
    int TotalScore;
    char Rank;
} TestResultStruct;

TestResult TestResult_Create(char ClassName, int StudentNo, const char* StudentName)
{
    int i;
    TestResult Result = (TestResult)malloc(sizeof(TestResultStruct));
    Result->ClassName = ClassName;
    Result->StudentNo = StudentNo;
    Result->StudentName = StudentName;
    for (i=0; i<TEST_TYPES_NUM; i++)
        Result->Score[i] = 0;
    Result->TotalScore = 0;
    Result->Rank = 'E';
    return Result;
}

void TestResult_Delete(TestResult Result)
{
    free(Result);
}

int TestResult_SetScore(TestResult Result, TestTypes TestType, int Score)
{
    if (!Result ||
        TestType < 0 || TestType >= TEST_TYPES_NUM ||
        Score < 0 || Score > 100)
        return -1;

    Result->Score[TestType] = Score;
    return 0;
}

void SetTotalScore(TestResult Result)
{
    int i, sum = 0;
    for (i=0; i<TEST_TYPES_NUM; i++)
        sum += Result->Score[i];
    Result->TotalScore = sum;
}

void SetRank(TestResult Result)
{
    const char RankChar[] = "EDCBA";
    int Rank = Result->TotalScore / 100;
    if (Rank >= strlen(RankChar))
        Rank = strlen(RankChar) - 1;
    Result->Rank = RankChar[Rank];
}

int TestResult_SetTotalScoreRank(TestResult Result)
{
    if (!Result)
        return -1;

    SetTotalScore(Result);
    SetRank(Result);
    return 0;
}

char TestResult_GetClassName(TestResult Result)
{
    if (!Result)
        return '-';
    return Result->ClassName;
}

int TestResult_GetStudentNo(TestResult Result)
{
    if (!Result)
        return -1;
    return Result->StudentNo;
}

const char* TestResult_GetStudentName(TestResult Result)
{
    if (!Result)
        return NULL;
    return Result->StudentName;
}

int TestResult_GetScore(TestResult Result, TestTypes TestType)
{
    if (!Result || TestType < 0 || TestType >= TEST_TYPES_NUM)
        return -1;
    return Result->Score[TestType];
}

int TestResult_GetTotalScore(TestResult Result)
{
    if (!Result)
        return -1;
    return Result->TotalScore;
}

char TestResult_GetRank(TestResult Result)
{
    if (!Result)
        return '-';
    return Result->Rank;
}

const char* GetTestTypeName(TestTypes TestType)
{
    const char* TestTypeNames[] = { "国語", "数学", "理科", "社会", "英語" };

    if (TestType < 0 || TestType >= TEST_TYPES_NUM)
        return NULL;

    return TestTypeNames[TestType];
}
