[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/x4y2o3YI)
:sectnums:
:nofooter:
:toc: left
:icons: font
:data-uri:
:stem: latexmath
:source-highlighter: highlightjs

= OOB.01 -- Pupils

Your goal is to implement a `class` which represents a pupil.
Take a look at the following _class diagram_.

[plantuml]
----
@startuml
hide empty methods

class Pupil {
    {static} -int _nextId
    -DateOnly _dateOfBirth [readonly]
    -int? _zipCode
    +Pupil(string, string, DateOnly)
    +int Age [readonly]
    +string FirstName [readonly]
    +int Id [readonly]
    +string LastName [readonly]
    +int? ZipCode

    +bool IsOfAge(AgeType)
    +bool IsOlderThan(Pupil)
    +bool LivesNearby(Pupil)
}
enum AgeType {
    VotingAge,
    FullAge,
    RetirementAge
}

@enduml
----

We will create several _instances_ of the `Pupil` class.
With those we perform some checks and comparisons, e.g. is one person older than the other or who lives nearby.

WARNING: _This_ time you have been provided with a detailed description of all class _members_. In future assignments you'll have to rely on the class diagram and the general task description only.

== Members

[cols="2,1,1,1,1,4"]
|===
|Name |DataType |Nullable |Static |Readonly |Description

|_nextId
|int
|false
|true
|false
a|
* Shared between all instances of the class
* Supplies the next free (incremented) id
** Which is assigned in the _constructor_

|_dateOfBirth
|DateOnly
|false
|false
|true
|The date of birth of the person

|_zipCode
|int
|true
|false
|false
a|
* Backing field for the `ZipCode` property
* Could be omitted in a class diagram, because implementation detail

|Age
|int
|false
|false
|true
|A _computed_ property which returns the current age in years based on the date of birth

|FirstName
|string
|false
|false
|true
|_Getter_ for retrieving the first name of a person

|Id
|int
|false
|false
|true
|_Getter_ for retrieving the unique id of a person

|LastName
|string
|false
|false
|true
|_Getter_ for retrieving the last name of a person

|ZipCode
|int
|true
|false
|false
a|
* Property for the ZIP Code of the pupil's living address
* *Constrained to the stem:[1000 \le x \le 9999] range*
** _Ignore_ invalid values
|===

Do _not_ forget the *visibility*! Some members are private, others public.
In the diagram above private is indicated as a red square and public as a green circle.

== Operations

[cols="1,2,3,5"]
|===
|Name |Input |Output |Description

|`IsOfAge`
|A single `AgeType` value
|A flag indicating if the pupil fulfills the age requirement
a|
* Checks if the age of the pupil _instance_ is high enough to satisfy the requirement of the `AgeType` value passed as parameter
* Thresholds:
** VotingAge = 16
** FullAge = 18
** RetirementAge = 65

|`IsOlderThan`
|A single `Pupil` reference
|A flag indicating if the one pupil is older than the other
|Checks if the `Pupil` _instance_ on which the method has been called is older than the `Pupil` instance passed as parameter

|`LivesNearby`
|A single `Pupil` reference
|A flag indicating if two pupils live near each other
a|
* Compares the ZIP codes of both pupils
** One from the current instance, the other from the passed instance
* If the first two digits match they live near each other
** Examples:
*** 4060 & 4030 => live nearby
*** 4060 & 1010 => don't live nearby
** If one or both pupils don't have a ZIP set (`null`) this method returns false
|===

TIP: Make sure you understand the difference between _value_ & _reference_ parameters! +
If you aren't confident read it up again, this should be clear by now.

== Impl. Requirements for `Pupil`

You have to create and implement the `Pupil` `class` yourself.
Thus, it is not already given in the starter code.

. Create the `class` and implement it (= add members and methods) as described above
** The usual requirements for _good_ & _clean_ code apply of course
. Create unit tests to test all your _public_ methods
** At least one 'happy path' test plus the major edge cases
. Write the XMLDoc for (at least) all your public methods and properties as well as for the `class`

== `Program` & Sample Run

CAUTION: The existence of the `Pupil` `class` (e.g. constructor, properties,...) is _required_ for the business logic to execute => the application will _not_ compile until you have completed `Pupil`. +
If you want to unit test your individual parts (https://en.wikipedia.org/wiki/Test-driven_development[TDD]) you can comment out parts of `Program` to allow your solution to compile.

The main `Program` has already been provided with the starter code.
It performs the following actions:

. It creates several `Pupil` instances
. It sets (valid & invalid) ZIP codes
. It performs several age checks
. It compares the ages of some pupils
. It checks if some pupils live each other

The results are printed to the terminal and should look like this:

image::pics/sample_run.png[Sample Run]