Let's now work on the login functionality and there,
I want to log every round that happened in the game,
every event that happened to the game -
so when we attack the monster, when we launch a strong attack, when we heal ourselves, when the monster
hits us and also when the game is over. And for that, we can add a new function, maybe up there, which I'll
name writeToLog because that's what's going to happen in there.
Now in this function, the idea is that we write the different events to a log and for that,
we of course also need a variable that holds our log.
So here at the beginning of our file maybe, we can add a new variable, battle log and initially that's
an empty array let's say,
now I want to add entries to that array in the writeToLog function. For that,
it would make sense to expect some kind of event parameter, event identifier which describes the events
that happened and then have multiple if and else if blocks to check for the different events we want
to support.
Now just as in the last lecture with the attack modes which I set up as global identifiers, I want to
do the same for my log events
so that we avoid typos and there I can have my log event player attack for example and give this an
identifier of player attack or use a number instead of a string, that's really up to you. Have my log
event player strong attack within a text of player strong attack let's say. Now these texts, as well as
any variable or constant names here are totally up to you of course, I just try to describe what we'll
use them for and I use this uppercase only notation here to make it clear that these are static values
I, the developer define here, hardcode here at the beginning of my script. Then I also want
to have a log event monster attack of course because the monster may hit us, like this and also a log
event player, heal player, heal because we might heal and also a log event
game over, game over, something like this.
Now that could be the log events with which want to deal and therefore now we can check for them,
we can check if event is equal to log event player attack let's say and if that is the case, I want to
add a new entry, a new object to my battle log which hold some information about that event.
So for that, I'll actually create a new variable inside of the writeToLog function,
so which is only available instead of that function
and that's my log entry
and then here we can set a log entry equal to a new object and in that object, I want to have my event
identifier which is a human readable string and actually therefore here, I prefer having a string identifier
as we set it up up here over a number because later when we print that log to the console, for us humans
it's easier to see which kind of events that was if we have a string that describes the event,
then if we have a number which we then have to translate with the help of our code to find out which
event that was.
So here, I store the event,
then I also want to store the value for the event let's say, so the damage costs,
so that's probably also something we should get here as our argument, as an argument. So I'll expect a
value here, a value argument and store that in my value prop here
and in case it's confusing for you that we have the same names for the keys
as for the values here, of course you could get let's say ev here and a val
and then use ev here and here and then val here to make it clear that the key names are totally detached
from the value variable names here.
So now I'm storing the event which is something like player attack, the value for that event which for
the player attack would be the damage dealt, for player heal it would be the damage for which you healed.
For game over, it could be the the name of the winner,
so player or monster for example and I also want to output the final monster health here and for that I
can access the current monster health,
alternatively we also expect this as an argument here which might be cleaner. We could use the global
variable but by using an internal parameter, we make this function a more pure function which only
works with data provided to it instead of also taking some global value which is always kind of dirty
or harder to follow if you're reading the code, it might be unexpected that a function also pulls in
some information from outside, especially if it's a function that also does take parameters and also the
final player health here maybe
and for that I also expect to get my player health snapshot here and store that. So that could be a log
entry we want to create and then we can reach out to the battle log and push that log entry onto the battle
log,
this is how we could add a new entry there.
Now of course we don't just have that case that we have the player attack,
we also have many other events that can occur for which we set up identifiers. So we can add another
else if statement here where we check if event is maybe equal to log event player strong attack let's
say. If that is the case, I will basically create my log entry in the same way though,
so therefore actually, we don't really need an else if log here, right
because we only populate the log entry with the data we got here.
Well that's indeed true,
you could totally create that function without any if checks if log entry is always created in the same
way with dynamic data that changes when you call the function but not inside of the function, to again
practice if statements,
I will add some extra information here which depends on the event that occurred.
I want to say target and here, say monster,
that's some information we're not getting from outside. Here,
I'll also add target
monster and then just as before, push this entry into my log
and then add another else if block where I check if the event is equal to let's say log event monster
attack, in which case we can also copy that code here
and here the target would be player,
that's the difference.
Now let's add another case because we also might have the event that we healed the player,
so log event player heal here and therefore again, we can copy in that code,
the target here is the player of course
and then we have the last else if block here,
the event is that
we have the game over case and there we have no target,
so I don't need to set a target here,
instead I just have my log entry like this where I output the final health value,
then in this case could be the name of the winner,
so player or monster or draw if we have a draw and then we push this onto our log.
Now I push to the log in every case and therefore we can actually remove that line from the if cases
here, so for all the else if blocks and for the main if block I remove this and instead, I can push
log entry onto the battle log after the entire if block because we know we have a log entry variable, it
will hold some value after all these if checks unless we passed in an ev identifier which is not
covered here and then we push that entry onto the log and that uncovered event identifier case shouldn't
really happen here because we will call that function and we as a developer here will make sure we don't
call that function with an invalid value.
Alternatively of course, you could add an extra check and before you execute any code, check if ev
is log event player attack or strong attack or monster attack and so on and if that is not the case,
so actually check if it's not that or not that or not that and so on, then you could return basically such
a check as we also added it earlier in this module in the calculator already. Here,
I'll not do it but it is something you could do.
Now with that, we create these different log entries here and you could even refine this code a bit more
and actually set log entry to an object here where you do have all these fields which are always the
same,
didn't want to cut them there,
so everything except for target
and then here you would only add logEntry.target and set this equal to monster
here for example,
so only add a new property dynamically which you can do in Javascript with the dot notation
if you access a property which doesn't exist yet,
this will add it dynamically.
So you could do that and save even more code,
I will leave these other log entries here like this though, just to make it really clear that we do set
this information on every if block,
we do it with this other approach too but this might be easier to read and to understand,
this approach however where you only change the target of course is the more dynamic or the shorter
approach and therefore the approach you might want to use in bigger apps.
Side note, if you do follow that approach where you set up that object up there and thereafter you only
change the target,
you can of course omit that last if else if block here because there we don't set a target,
so there we already got the readily configured log entry with our default log entry up there.
So that's just a side note,
creating all these extra objects is a bit redundant but I'll leave it like this for readability here.
Then we push that onto our log
and with that, we should have a log,
now let's make sure we can also output it
and for that in the vendor.js file, we have that log button to which we can add an event listener,
so I'll do that in app.js at the very bottom here,
I add my event listener for a click event and there, I want to have my let's say printLogHandler
function which doesn't exist yet which we have to create,
maybe right down there, the printLogHandler function and in that function, I want to output the log
and for now, I'll just console log the battle log, the variable which should be that array.
Now we just need to make sure that we actually call write to log for every event that we do want to
log because right now, that's not something we're doing.
So let's do it
and for that of course in and round when the monster hit us, I want to call writeToLog with my log
event monster attack identifier because the monster attacked us. The value then is player damage and
the monster health at this point
then is the current monster health and the player health is currentPlayerHealth.
So this is how we can call this function here,
we can also really structure this across multiple lines with the auto formatting shortcut to make that
a bit easier to read,
so that's writeToLog after the monster hit us.
Now I also want to log when the game is over and that of course is the case whenever we also call reset
but I need to know whether we won or lost or had a draw so
I will actually write to the logs here in these checks where I do know whether we won or the monster
won.
Then here, I will create my log event game over, the value which I now pass in is not the damage
but instead the result of the game,
so here that could be player1, whatever you want to use here,
that's any text you want to put into your log message, into your log object,
the health snapshots and then do the same here for the monster if it won, so monster won and
also down there if we have a draw, then maybe output a text of a draw. In the end, you can put any data
you want in there.
And now we got two other events which I want to log or three other events actually,
that's when we attack the monster strong or with a weak attack
and also when we heal ourselves.
So let's start with attacking the monster,
so here I also want to write to the log after we reduce the monsters health and which event I
write to the log differs based on the mode we have here,
so actually we can add a new variable, log event and then log event is either equal to log event player
attack here or if we selected a strong attack,
it's log event strong attack. And now log event is a variable that holds either of the two identifiers,
so the string value is stored in these constants in the end
and therefore now here when I write to the log, I can use log event, this variable which is one of my identifiers
or to be precise, the values stored in these identifiers of course. The value which I want to write to
the log is the damage that was actually dealt
and then again, I take my current monster and player health snapshot.
And now there's one last thing I want to write to the log and that is when we heal ourselves. There, after
we adjusted the player health, I have my log player heal event, then I healed by the heal value here, heal
value like this because that's the actual heal value by which we healed
and then again my health snapshots.
So now with that, we should have all that functionality implemented. Back in the app, we can open the developer
tools now to see the console.
Now if we now reload and start a new game and we attack and a strong attack and we heal and then I show
the log, we have six events in there
and that makes sense,
we have a player attack where we hit the monster for a value of around six and
that makes sense because the monster health thereafter is around 94.
Then the monster attacks us for around four damage points which again makes sense,
monster health is still what it had after we hit it
but now the player health is reduced by that damage here and then we launch a strong attack with the
value of 10, monster health
thereafter is 83 which makes sense, it was 93 something before, now it's 83 something,
after hitting it for 10 something
player health is unchanged.
Monster attacks us, so now
this is the damage it dealt to us,
this is our health thereafter
and so on. We healed ourselves,
there you see we healed ourselves for around six, fully up to 100 thereafter but then the monster hits
us again, takes us down to 90 and that's basically what we see there.
Now let's continue here and launch a couple of strong attacks until we win,
yes we did and now print the log, lots of messages in there. In the end,
you see the game over message and there you see player won and the final monster health, below zero of
course, player health above zero
and therefore this all works.
This is how we can write to the log and how we can output the log like this.
Now later, we will learn about loops and therefore how we can output this log in a bit of a nicer way
instead of just throwing the entire array in there like this
but for now, this will do
and with that we also had a lot of if usage. Now I want a dive into some of the neat features which
we haven't really talked about yet when it comes to if statements, about conditional code before we
thereafter dive into loops.