Chris Ching Course Part 5 (Challenge 3)

Four days?! Wow, that's longer than I thought! This is not going to be a typical thing - such big gaps between coding. To make up for this, I will be sure to have a good session today and tomorrow - at least an hour for each. So, last time, I completed both of the Chris Ching challenges. I got MOST of the elements correct, though the second one had me puzzled in places. For the last part of the Chris Ching course, there is the third and final challenge. Here we go!

// Challenge #3: The Library Challenge
//
// Instructions:
// Complete the class definition so that you get the expected output in the console (specified below the class definitions). See TODOs.
//

class Person {
    
    var name:String!
    
    init(_ fullName:String) {
        name = fullName
    }
}

class Book {
    
    var title:String!
    var author:String!
    
    init(_ bookTitle:String, _ bookAuthor:String) {
        title = bookTitle
        author = bookAuthor
    }
    
}

// --- Your code goes below this line ---

class Library {
    
    var catalogue = ["ORW":Book("1985", "George Orwell"),
                     "RAY":Book("Fahrenheit 451", "Ray Bradbury")]
    
    var checkedOutBooks = [String:Person]()
    
    func searchByTitle(_ title:String) -> String {
        
        // TODO: This function searches the catalogue dictionary for a title
        //
        // Returns "Available" if the book exists and isn't checked out
        //
        // Returns "Checked out by name" if the book exists and is checked out
        //
        // Returns "Not in catalogue" if the book doesn't exist
        
        return ""
    }
    
    func checkOut(_ bookId:String, _ person:Person) -> String {
        
        // TODO: This function adds to the checkedOutBooks dictionary
        //
        // Returns "Error: Book already checked out" if the book is already in the checkedOutBooks dictionary
        //
        // Returns "Successfully checked out" and adds the bookId,person key-value pair if the book doesn't currently exist in the checkedOutbooks dictionary
        //
        // Returns "Book doesn't exist" if the book isn't in the catalogue dictionary
        
        return ""
    }
    
    func checkIn(_ bookId:String) -> String {
        
        // TODO: This function removes the bookId,person key-value pair from the checkedOutBooks dictionary
        //
        // Returns "Book doesn't exist" if the book isn't in the catalogue dictionary
        //
        // Returns "Error: Can't check in a book that hasn't been checked out" if the book wasn't checked out in the first place
        //
        // Returns "Successfully checked in"
        
        
        
        return ""
    }
    
}
// --- Your code goes above this line ---

// --- Don't edit or add anything below this line ---

let lib = Library()
let borrower1 = Person("Curious George")
let borrower2 = Person("Mark Twain")

// George searches for a book
let searchResult = lib.searchByTitle("1985")
print(searchResult)

// Expected Output in console:
// "Available"

// George checks out the book
let borrowResult = lib.checkOut("ORW", borrower1)
print(borrowResult)

// Expected Output in console:
// "Successfully checked out"

// Mark searches for a book
let searchResult2 = lib.searchByTitle("1985")
print(searchResult2)

// Expected Output in console:
// "Checked out by Curious George"

// Mark tries to borrow a book that's already checked out
let borrowResult2 = lib.checkOut("ORW", borrower2)
print(borrowResult2)

// Expected Output in console:
// "Error: Book already checked out"

// A book is checked in
let checkInResult = lib.checkIn("RAY")
print(checkInResult)

// Expected Output in console:
// "Error: Can't check in a book that hasn't been checked out"

// George checks in his book
let checkInResult2 = lib.checkIn("ORW")
print(checkInResult2)

// Expected Output in console:
// "Successfully checked in"

// Mark attempts to borrow the book again
let borrowResult3 = lib.checkOut("ORW", borrower2)
print(borrowResult3)

// Expected Output in console:

// "Successfully checked out"

So as you can see there is a LOT to this! I'm now watching the video of the instructions in full....


OK, so the ONLY bit that I am editing is the Library class. Let's make a list of what else we need to know....

  • There are three functions that each need adding to 
  • The first function needs to do a for in loop for the array of books
  • Or it could be a switch/if statement - will try both!
  • The second function again needs one of the above; it also needs to add to a dictionary
  • Third function is similar to the second but kind of does the reverse

OK bearing all of that in mind let's go!

I'm having a go but have come across a snag...

func searchByTitle(_ title:String) -> String {
        
        for title in catalogue {
            
            if title 

Whatever I do, an error returns with not having the right syntax for being in catalogue. Do I even need the for loop?

OK I need some help, just initially with this syntax! I think my idea is good...

Right, I checked online about looping in dictionaries - I've done it as the (key, value) pair. Not sure if it's worked as my Xcode keeps saying 'running'...

class Library {
    
    var catalogue = ["ORW":Book("1985", "George Orwell"),
                     "RAY":Book("Fahrenheit 451", "Ray Bradbury")]
    
    var checkedOutBooks = [String:Person]()
    
    var returnString: String = ""
    
    func searchByTitle(_ title:String) -> String {
        
        for (bookTitle, _) in catalogue {
            
            for (checkedOutBook, _) in checkedOutBooks {
            
            if bookTitle == title && checkedOutBook != title {
                
                returnString = "Available"
                
            } else if bookTitle == title && checkedOutBook == title {
                
                returnString = "Checked out by name"
                
            } else {
                returnString = "Not in catalogue"
                }
        // TODO: This function searches the catalogue dictionary for a title
        //
        // Returns "Available" if the book exists and isn't checked out
        //
        // Returns "Checked out by name" if the book exists and is checked out
        //
        // Returns "Not in catalogue" if the book doesn't exist
        
            }
        }
        
        return returnString
    }
    
Even if this doesn't work, I'm proud of the logic. One of the key parts was looping through using the right value part of the dictionary. Also, it didn't like no return statements, so I created a variable for the return value to be stored before returning it at the end. Before I continue I'm going to check the solution for the first stage before potentially getting all three aspects totally wrong!

So Chris has done it a little differently - he has used a key value pair but the syntax and approach is a bit different. 

I'm honestly not sure if mine works or not!

The next stage, I have cheated a little by seeing how Chris has started this. So I need to figure out if the catalogue has the book, then code accordingly....

I needed A LOT of help with this:

 func checkOut(_ bookId:String, _ person:Person) -> String {
        
        if catalogue[bookId] == nil {
            return "Book doesn't exist"
            
        } else if catalogue[bookId] != nil {
            return "Error: Book already checked out"
        } else {
            checkedOutBooks[bookId] = person
            return "Successfully checked out"
            
            
        }
        // TODO: This function adds to the checkedOutBooks dictionary
        //
        // Returns "Error: Book already checked out" if the book is already in the checkedOutBooks dictionary
        //
        // Returns "Successfully checked out" and adds the bookId,person key-value pair if the book doesn't currently exist in the checkedOutbooks dictionary
        //
        // Returns "Book doesn't exist" if the book isn't in the catalogue dictionary
        
    
    }

More or less copied from Chris - it does work but not proud of myself! Let's try the last bit without help.....

Just a reminder - 

 func checkIn(_ bookId:String) -> String {
        
        // TODO: This function removes the bookId,person key-value pair from the checkedOutBooks dictionary
        //
        // Returns "Book doesn't exist" if the book isn't in the catalogue dictionary
        //
        // Returns "Error: Can't check in a book that hasn't been checked out" if the book wasn't checked out in the first place
        //
        // Returns "Successfully checked in"
        
        
        
        return ""
    }
    
}

So for this one I need to do the removeAtIndex, or remove this particular key to get the item off the checkedOutBooks dictionary. If it's not there, then book doesn't exist (could start with this). If it wasn't checkedOut (a bool needed...) then there's an error message....

Let's have a go!

func checkIn(_ bookId:String) -> String {
        
        if checkedOutBooks[bookId] == nil {
            return "Book doesn't exist"
        } else if catalogue[bookId] != nil {
            return "Error: can't check in a book that hasn't been checked out"
        } else {
            checkedOutBooks.removeValue(forKey: bookId)
            return "Successfully checked in"
        }
        // TODO: This function removes the bookId,person key-value pair from the checkedOutBooks dictionary
        //
        // Returns "Book doesn't exist" if the book isn't in the catalogue dictionary
        //
        // Returns "Error: Can't check in a book that hasn't been checked out" if the book wasn't checked out in the first place
        //
        // Returns "Successfully checked in"
        
        
    }
    
}

I THINK I've done it! Let's see if anything comes out the print console....

Xcode just says 'Running...' - again! Let's see what Chris did...

Right a logical error straight off - I missed something!

   func checkIn(_ bookId:String) -> String {
        
        if catalogue[bookId] == nil {
            return "Book doesn't exist"
        }
        if checkedOutBooks[bookId] == nil {
            return "Error: can't check in a book that hasn't been checked out"
        } else {
            checkedOutBooks.removeValue(forKey: bookId)
            return "Successfully checked in"
        }

}

I needed to return book doesn't exist for the CATALOGUE entry first! So now I've got it!

Chris does this instead of the removeValue:

 checkedOutBooks[bookId] = nil

But I think my line of removeValue would still work. 

So overall here's how I did -

Stage 1 - got some of this but didn't get the syntax for iterating through dictionaries and values - I need more practice with that element of it. 

Stage 2 - lost a lot of confidence and had no idea how to start. So I got a lot of help and ended up copying Chris. 

Stage 3 - I got some of this and was actually fairly close, just rushed and didn't get all of the logic. 

So not a bad effort. It's good to try these practical challenges but I must say, without my knowledge outside of this course (which is quite a bit to be fair!) I wouldn't have had a chance. Tough challenges Chris! But good practice all the same. I think I'm going to go back to Angela's course next. Hopefully there'll be enough there to keep building my knowledge and clear up the difficulties I've found along the way. Until tomorrow!

*Didn't do the start time etc. but I worked on this challenge for approximately 1 hour 20 minutes. 


Comments

Popular posts from this blog

*Xcode Project Entry 2* F1 Quiz - part 1

Angela Yu Course Part 10 (up to lesson 112)

Angela Yu Xcode 12 Course - Part 7 (lectures 74 to 79)