/*
 * Name: Haroon Malik
 * Fall 2026 Intro to Programming with C - Midterm
 */
#include <stdio.h>
#include <string.h>

#define PI 3.14159265358979323846f

/* Question 1: Dimensions are assumed to be nonnegative. */

/* **************************************************
 * Function: calcAreaOfTriangle
 * Description: Calculates a triangle's area.
 * Parameters: base - base length; height - perpendicular height.
 * Returns: Area in square units.
 * ************************************************** */
float calcAreaOfTriangle(float base, float height)
{
    return 0.5f * base * height;
}

/* **************************************************
 * Function: calcAreaOfRectangle
 * Description: Calculates a rectangle's area.
 * Parameters: length - length; width - width.
 * Returns: Area in square units.
 * ************************************************** */
float calcAreaOfRectangle(float length, float width)
{
    return length * width;
}

/* **************************************************
 * Function: calcAreaOfSquare
 * Description: Calculates a square's area.
 * Parameters: side - side length.
 * Returns: Area in square units.
 * ************************************************** */
float calcAreaOfSquare(float side)
{
    return side * side;
}

/* **************************************************
 * Function: calcAreaOfCircle
 * Description: Calculates a circle's area.
 * Parameters: radius - circle radius.
 * Returns: Area in square units.
 * ************************************************** */
float calcAreaOfCircle(float radius)
{
    return PI * radius * radius;
}

/* **************************************************
 * Function: calcAreaOfParallelogram
 * Description: Calculates a parallelogram's area.
 * Parameters: base - base length; height - perpendicular height.
 * Returns: Area in square units.
 * ************************************************** */
float calcAreaOfParallelogram(float base, float height)
{
    return base * height;
}

/* **************************************************
 * Function: calcAreaOfTrapezoid
 * Description: Calculates a trapezoid's area.
 * Parameters: base1, base2 - parallel side lengths;
 *             height - perpendicular distance between them.
 * Returns: Area in square units.
 * ************************************************** */
float calcAreaOfTrapezoid(float base1, float base2, float height)
{
    return 0.5f * (base1 + base2) * height;
}

/* Question 2 */
/* **************************************************
 * Function: frequency
 * Description: Counts occurrences of x in the first n elements.
 * Parameters: theArray - array with at least n elements;
 *             n - nonnegative element count; x - value to count.
 * Returns: Number of elements equal to x.
 * ************************************************** */
int frequency(int theArray[], int n, int x)
{
    int frequency = 0;

    for (int i = 0; i < n; i++)
    {
        if (theArray[i] == x)
        {
            frequency++;
        }
    }
    return frequency;
}

/* Question 3: ASSUMPTIONS because the validation rules were omitted.
 * This classroom model accepts full years 2013-2026, halfYear 1 or 2,
 * one county letter from C/D/G/L/T/W (either case), and sequence
 * numbers 1-999999. These are chosen exercise rules, not a complete
 * validator for actual Irish registration plates. Replace them with
 * your instructor's rules. The year range is inclusive and does not
 * attempt to check whether a registration is in the future.
 */
/* **************************************************
 * Function: irishLicensePlateValidator
 * Description: Checks the four fields against the exercise rules above.
 * Parameters: year - full year; halfYear - half of year;
 *             countyCode - single county letter;
 *             sequenceNumber - registration sequence.
 * Returns: 1 if every field is valid; otherwise 0.
 * ************************************************** */
int irishLicensePlateValidator(int year, int halfYear,
                              char countyCode, int sequenceNumber)
{
    if (year < 2013 || year > 2026)
    {
        return 0;
    }
    if (halfYear != 1 && halfYear != 2)
    {
        return 0;
    }
    if (sequenceNumber < 1 || sequenceNumber > 999999)
    {
        return 0;
    }

    /* Accept either case for each supported county. */
    switch (countyCode)
    {
        case 'C': case 'c':
        case 'D': case 'd':
        case 'G': case 'g':
        case 'L': case 'l':
        case 'T': case 't':
        case 'W': case 'w':
            return 1;
        default:
            return 0;
    }
}

/* Question 4 */
/* **************************************************
 * Function: minimumOfFour
 * Description: Finds the minimum using conditional operators and AND.
 * Parameters: value1, value2, value3, value4 - integers to compare.
 * Returns: The smallest input, including when inputs are tied.
 * ************************************************** */
int minimumOfFour(int value1, int value2, int value3, int value4)
{
    /* <= ensures tied minimum values are handled correctly. */
    int min4 = ((value1 <= value2) && (value1 <= value3) &&
                (value1 <= value4)) ? value1 :
               ((value2 <= value1) && (value2 <= value3) &&
                (value2 <= value4)) ? value2 :
               ((value3 <= value1) && (value3 <= value2) &&
                (value3 <= value4)) ? value3 : value4;
    return min4;
}

/* Question 5 */
/* **************************************************
 * Function: calcLetterGrade
 * Description: Converts a score using 90/80/70/60 grade thresholds.
 * Parameters: score - integer percentage.
 * Returns: A, B, C, D, or F; returns '?' for values outside 0-100.
 * ************************************************** */
char calcLetterGrade(int score)
{
    char result;

    /* Reject invalid scores before assigning a letter grade. */
    if (score < 0 || score > 100)
        result = '?';
    else if (score >= 90)
        result = 'A';
    else if (score >= 80)
        result = 'B';
    else if (score >= 70)
        result = 'C';
    else if (score >= 60)
        result = 'D';
    else
        result = 'F';

    return result;
}

/* Question 6: Preserve the member names supplied in the question.
 * Assumed single-character codes: C, D, G, L, T, W.
 */
struct countyTotals
{
    int totalCorkCodes;
    int totalDublinCodes;
    int totalGalwayCodes;
    int totalLimerickCodes;
    int totalTiperaryCodes;
    int totalWaterfordCodes;
    int totalInvalidCountryCodes;
};

/* **************************************************
 * Function: freqOfIrishCounties
 * Description: Counts county letters without regard to case.
 * Parameters: countyArrayList - array with at least size elements;
 *             size - nonnegative element count.
 * Returns: Structure of six county counts and an invalid-code count.
 * ************************************************** */
struct countyTotals freqOfIrishCounties(char countyArrayList[], int size)
{
    struct countyTotals myCountyTotals = {0, 0, 0, 0, 0, 0, 0};

    for (int i = 0; i < size; i++)
    {
        switch (countyArrayList[i])
        {
            case 'C': case 'c':
                myCountyTotals.totalCorkCodes++;
                break;
            case 'D': case 'd':
                myCountyTotals.totalDublinCodes++;
                break;
            case 'G': case 'g':
                myCountyTotals.totalGalwayCodes++;
                break;
            case 'L': case 'l':
                myCountyTotals.totalLimerickCodes++;
                break;
            case 'T': case 't':
                myCountyTotals.totalTiperaryCodes++;
                break;
            case 'W': case 'w':
                myCountyTotals.totalWaterfordCodes++;
                break;
            default:
                myCountyTotals.totalInvalidCountryCodes++;
                break;
        }
    }
    return myCountyTotals;
}

/* Question 7: Function prototypes */
float toCelsius(int theFahrenheitTemp);
float toFahrenheit(int theCelsiusTemp);

/* **************************************************
 * Function: main
 * Description: Prints both temperature tables in one-degree steps.
 * Parameters: None.
 * Returns: 0 on successful completion.
 * ************************************************** */
int main(void)
{
    int i; /* Current temperature in the source scale. */

    printf("Celsius to Fahrenheit\n");
    printf("%10s %12s\n", "Celsius", "Fahrenheit");
    printf("---------- ------------\n");
    for (i = 0; i <= 100; i++)
    {
        printf("%10d %12.2f\n", i, toFahrenheit(i));
    }

    printf("\nFahrenheit to Celsius\n");
    printf("%10s %12s\n", "Fahrenheit", "Celsius");
    printf("---------- ------------\n");
    for (i = 32; i <= 212; i++)
    {
        printf("%10d %12.2f\n", i, toCelsius(i));
    }
    return 0;
}

/* **************************************************
 * Function: toCelsius
 * Description: Converts Fahrenheit to Celsius.
 * Parameters: theFahrenheitTemp - temperature in Fahrenheit.
 * Returns: Corresponding Celsius temperature.
 * ************************************************** */
float toCelsius(int theFahrenheitTemp)
{
    /* Floating-point division preserves the fractional part. */
    return (theFahrenheitTemp - 32.0f) * (5.0f / 9.0f);
}

/* **************************************************
 * Function: toFahrenheit
 * Description: Converts Celsius to Fahrenheit.
 * Parameters: theCelsiusTemp - temperature in Celsius.
 * Returns: Corresponding Fahrenheit temperature.
 * ************************************************** */
float toFahrenheit(int theCelsiusTemp)
{
    return theCelsiusTemp * (9.0f / 5.0f) + 32.0f;
}

/* Question 8: The prompt does not specify the additional fields or
 * required operations. The following is an illustrative completion
 * using strings, nested structures, and the supplied 100-officer array.
 * Confirm the required fields with your full question.
 */
struct date
{
    int day;
    int month;
    int year;
};

struct assignment
{
    char shipName[51];       /* Up to 50 characters plus '\0'. */
    char department[31];    /* Up to 30 characters plus '\0'. */
};

struct officer
{
    char starFleetID[9];    /* Up to 8 characters plus '\0'. */
    struct date dateOfBirth;
    char firstName[31];
    char lastName[31];
    char rank[31];
    struct assignment currentAssignment;
};

struct officer officers[100];

/* **************************************************
 * Function: initializeExampleOfficer
 * Description: Demonstrates assigning strings and nested members.
 * Parameters: None; modifies the global officers array at index zero.
 * Returns: Nothing.
 * ************************************************** */
void initializeExampleOfficer(void)
{
    /* Each string literal fits its destination, including '\0'. */
    strcpy(officers[0].starFleetID, "SF000001");
    strcpy(officers[0].firstName, "Alex");
    strcpy(officers[0].lastName, "Morgan");
    strcpy(officers[0].rank, "Ensign");
    officers[0].dateOfBirth.day = 15;
    officers[0].dateOfBirth.month = 6;
    officers[0].dateOfBirth.year = 2300;
    strcpy(officers[0].currentAssignment.shipName, "Enterprise");
    strcpy(officers[0].currentAssignment.department, "Engineering");
}

/* Question 9:
 * Your Compiler/IDE: Ideone
 *
 * 1) I like that error messages show line numbers, making mistakes
 *    easier to find.
 *
 * 2) Compiling and running programs is simple because I can paste
 *    my C code and run it directly in the browser.
 *
 * 3) I dislike the limited debugging tools. I use printf statements
 *    to check variable values and find errors.
 *
 * 4) Entering input before running can be awkward when a program
 *    asks for several values.
 */