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

= Col.05 -- Building Directory

You are going to implement a building information system.

* Situation:
** A building has multiple floors
** On each floor none, one or more companies have their offices
** Each employee of a company has an office room assigned
* We are going to support this user story:
** You received a business card from a clerk and are now on your way to visit them at their office
** Enter the building, and you find an overview:
*** Which floors exist
*** Which companies are on each floor
** Select a floor and use the elevator to get there
** Once arrived at the selected floor follow the directions, labeled with the company names, to find the reception desk of the chosen company
** Hand the business card to the reception clerk who will then tell you the room number of the person you've come to visit
** Go to the room and conduct your business
* These scenarios will be implemented with a _generic dictionary (hash map)_

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

class BusinessCard {
    +string FirstName [readonly]
    +string LastName [readonly]
    +string Department [readonly]
    +string? PhoneNumber [readonly]
    +string EMail [readonly]

    +BusinessCard(string, string, string, string?, string)
    +bool Equals(object?) [override]
    +int GetHashCode() [override]
    -bool Equals(BusinessCard)
}
class Company {
    -MyDictionary<BusinessCard, int> _employeeRooms [readonly]
    +string Name [readonly]
    +int NoOfEmployees [readonly]

    +Company(MyDictionary<BusinessCard, int>, string)
    +int? AskForRoom(BusinessCard)
}
enum Floor {
    Ground
    First
    Second
    Third
}
class BuildingInformation {
    -MyDictionary<Floor, MyDictionary<string, Company>> _companiesPerFloor

    +BuildingInformation(MyDictionary<Floor, MyDictionary<string, Company>>)
    +List<Floor> GetFloorSelection()
    +List<string>? GetCompaniesOnFloor(Floor)
    +Company? GetCompany(Floor, string)
}
class MyDictionary<TKey, TValue> {
    -int InitialBuckets [const]
    -int MaxDepth [const]
    -List<KeyValue>[] _buckets
    -int _currentMaxDepth
    -int NoOfBuckets [readonly]
    +int Count [private set]
    +TValue? this[TKey key]

    +MyDictionary()
    +MyDictionary(int)
    +List<TKey> GetKeys()
    +List<TValue> GetValues()
    +void Add(TKey, TValue)
    +bool Remove(TKey)
    +bool TryGetValue(TKey, out TValue?)
    +bool ContainsKey(TKey)
}

Company "1" -r- "n" BusinessCard
BuildingInformation "1" -- "n" Company
BuildingInformation -r- "n" Floor

@enduml
----

== Dictionary

* Remember: a dictionary, also called a _hash map_ is similar to a hash set
** The keys are unique
** The content is unordered
* Different from a hash set, a dictionary assigns a value to each key
** Values are added _with_ and _by_ their key
** Values are retrieved by their key
* A value is not constrained
** It can occur multiple times
** It can be any object
*** Not only a single value
*** But also a collection of other values

=== Example

[cols="1,5a"]
|===
|Class |Students

|2AHIF
|
[cols="1,2"]
!===
!ID !FirstName

!IF231234
!Anna

!IF231235
!Max

!IF231236
!Linda
!===

|2BHIF
|
[cols="1,2"]
!===
!ID !FirstName

!IF234321
!Anna

!IF234322
!Anna

!IF234323
!Max
!===
|===

* `Class` & `ID` have to be _unique_ (within one dictionary)
* `Students` & `FirstName` _can_ contain the same value multiple times

=== Implementation Hint

The following _private_ members might be helpful when you implement `MyDictionary`.

[source,csharp]
----
private bool TryGetValue(TKey key, out KeyValue? existingKeyValue) [...]
private List<KeyValue> GetKeysAndValues() [...]
private void Grow() [...]
private static List<KeyValue>[] CreateBuckets(int amount) [...]

private sealed class KeyValue <1>
{
    public KeyValue(TKey key, TValue value)
    {
        Key = key;
        Value = value;
    }

    public TKey Key { get; }
    public TValue Value { get; set; }

    private bool Equals(KeyValue other) [...]
    public override bool Equals(object? obj) [...]
    public override int GetHashCode() [...]
}
----
<1> If implemented _within_ `MyDictionary` the type parameters `TKey` & `TValue` will be taken from the surrounding class and _don't_ have to be specified

== Tasks

As usual:

* Implement missing code pieces marked with `TODO`
* Mind the provided XMLDoc & UnitTests