B1 Informatics 1 WS 2023/24

Website of Prof. Dr. Barne Kleinen, Professor for Media Informatics (Bachelor/Master) at HTW Berlin

KaraClock Complete

     <prev

This is a complete overview of the KaraClock Exercises that lead to the implementation of the KaraClockDisplay-Example. The exercises are distributed through three Labs, as shown by the headlines here.

The material section contains an article about why I made this addition to the ClockDisplay example: ClockDisplay Example: Reflections and Improvements.

Open the Greenfoot-Kara project https://github.com/htw-imi-info1/kara-clock-lab. It contains several test worlds. Make sure you’ve instantiated the correct test world!

If you haven’t already done so, you need to install Greenfoot to open the scenarios. The main file is project.greenfoot.

Lab 02

0. Count Leaves with act() loop and a field

(optional if you skip to 2. Count Leaves but also a good preparation for it)

  1. Open TestWorld4WithMyKara. Make Kara move up to the tree and count the leaves found on it’s way. It should move up and count one step with each call to the act() method. It should stop (by calling Greenfoot.stop();) either at the tree above or on the first free field.

    Add an accessor(getter) (public int getCount() or similar) to return the number of leaves counted so far.

1. Multi-Move

  1. copy the multiMove method we discussed in class from chapter02/kara/kara-loop-examples to DigitDisplayKara (the method definition is already there, you just need to fill it). Test it in TestWorld0 and TestWorld1. TestWorld1 contains a setup you don’t need to understand just now - just click “act” once and all Karas should be aligned in the middle like this:
Initial TestWorld1TestWorld1 after act()
TestWorld1 beforeTestWorld1 after
  1. Extend Multi-Move to move backwards: Extend the multiMove(int steps)-method to allow Kara to move backwards if a negative number is passed as parameter. It should turnAround (a method with the same name might be handy), move the appropriate number of steps and turnAround again. Hint: You can get the absolute value of a number steps using Math.abs(steps). Use TestWorld0 during the development; after you’re done test it in TestWorld2:
Initial TestWorld2TestWorld2 after act()
TestWorld1 beforeTestWorld1 after

2. Move Up And Count

  1. Open TestWorld4. complete the method public int moveUpAndCount() in DigitDisplayKara. It should move up and count the leaves. It should stop either at the tree above or on the first free field. It returns the number of leaves counted. Test your method by calling it from Kara’s context menu.
  2. When you’re done, test your method in TestWorld5, which contains some edge cases like a full row and one with zero leaves.
TestWorld5 beforeTestWorld5 outputTestWorld5 after act()
TestWorld5 beforeTestWorld5 outputTestWorld5 after

Lab 03

3. Count Leaves (and go back)

  1. Open TestWorld4 again. Complete the method public int count() in DigitDisplayKara. It should combine the public int moveUpAndCount() and public int multiMove() methods (that is, use them both by calling them) to walk up, count the leaves, return to the original position and return the number of leaves counted.

  2. When you’re done, test your method in TestWorld6Count, which contains some edge cases like a full row and one with zero leaves.

beforeoutputafter act()
TestWorld5 beforesame as with TestWorld5: TestWorld5 outputexactly the same as before calling act!

4. Increment Leaves

  1. Open TestWorld4 again. Complete the method public int increment() in DigitDisplayKara. It should call public int moveUpAndCount() and then either a. add one more leaf, return to the original position using public int multiMove() and return the new leaf count (including the leaf just added) b. if the tree is reached (no more space, overflow!) return to the original position and collect all leaves on its way (hint: this is exactly like multiMove with one addition!) and return a 0 as the new leaf count.

  2. When you’re done, test your method in TestWorld7Increment, which contains some edge cases like a full row and one with zero leaves.

beforeoutputafter act()
TestWorld7 beforeTestWorld7 outputTestWorld7 after

5. Decimal Number

Now, with a DigitDisplayKara that can count and increment its leaves, you can use it to build a number - where DigitDisplayKara has a placeValue (e.g. 1,10,100,1000 etc for Decimal Numbers).

  1. Open the World DecimalNumberWorld - with the implemented methods, it should work! Experiment with calling act() and run().

  2. For the Curious: (optional) Duplicate DecimalNumberWorld to create a number with a different base - e.g. BinaryNumberWorld for base 2. Change the BASE constant to 2 and try it out by calling act() and run().

DecimalNumberWorld

Lab 04

6. Initialize DigitDisplayKara (set count of leaves)

In order to be able to set the clock to a given time, each digit needs to be able to initialize with a given number of leaves.

This could be achieved with the same number of ticks, but would take some time and would not be as elegant.

You can use the DecimalNumberWorld to test it. After completed, call DisplayKara’s setValue(1234567890); to achieve the pattern in part 5.

7. The first Kara Clock

Now, with your completed DigitalDisplayKara, the first Kara Clock can be built.

Open ClockDisplayWorld1 - it contains three DigitDisplayKaras: one for minutes, one for ten minutes, and one for hours. Experiment a bit with it!

Showing 24 hours is difficult though - 24 leaves would be too much, using two digits - one for 10 hours, one for single hours - would need to toggle the limit for the single hour DigitDisplayKara between 10 and 4.

If you want a real clock open ClockDisplayWorld12Hours. It starts a thread and calls tick() every second, you can start and stop it using the respective methods in ClockDisplayKara

8. The 12 Hour Clock with am/pm

To show all 24 hours, a 12 hours am/pm is a good solution for the Kara-Clock!

The first step of changing it to a proper 12h clock with am/pm display has already been made in ClockDisplayWorld12Hours. It uses a special HoursDisplayKara for the hours, which shows a “12” instead of the “0”. Find the getDisplayText(int count) to see how this is implemented. You can use this as a guide to create an AmPmDisplayKara that is also a subclass of DigitDisplayKara and only overrides the public String getDisplayText(int count) (note that this is only used to set the text below the lower tree line.)

Use ClockDisplayWorldAmPm (which is a copy of ClockDisplayWorld12Hours) to implement this. Find and read its prepareColumns() method to understand how the clock display is built and what you need to do to add another digit.

Technically, the ClockDisplayWorld is just a number with different rollOverLimits for each digit. The place value has to be the product of the previous (mostly right) digit and its place value:

am/pmhoursten minutesminutes
limit212610
placeValue12*606*1010*11

Your task is to add the am/pm display.

It is just another digit with a place value of 12 hours, and should show am/pm instead of 0 and 1. Also, it has a special (quite illogical) position at the end, eg. 12:00 am.

To enable the DisplayKara to find and walk to the next DigitDisplayKara, each digit stores the number of steps (which may be negative as it is simply passed to multiMove() ) in its field stepsToNextDigit which can be set with the constructor:

public DigitDisplayKara(int rollOverLimit, long placeValue, int stepsToNextDigit)

KaraClock