Question

In: Computer Science

Modify the "spiral" method in the "DrawDemo" class so that a spiral appears in the center...

Modify the "spiral" method in the "DrawDemo" class so that a spiral appears in the center of the canvas. However, instead of displaying the lines as black, randomize the color of each line between Color.RED, Color.GREEN, and Color.BLUE (each line should be randomized, don't display a single color for the whole spiral).

import java.awt.Color;
import java.util.Random;
import java.awt.Dimension;

/**
* Class DrawDemo - provides some short demonstrations showing how to use the
* Pen class to create various drawings.
*
* @author Michael Kölling and David J. Barnes
* @version 2016.02.29
*/

public class DrawDemo
{
    private Canvas myCanvas;
    private Random random;

    /**
     * Prepare the drawing demo. Create a fresh canvas and make it visible.
     */
    public DrawDemo()
    {
        myCanvas = new Canvas("Drawing Demo", 500, 400);
        random = new Random();
    }

    /**
     * Draw a square on the screen.
     */
    public void drawSquare()
    {
        Pen pen = new Pen(320, 260, myCanvas);
        pen.setColor(Color.BLUE);

        square(pen);
    }

    /**
     * Draw a polygon with the given number of sides.
     * @param n The number of sides.
     */
    public void drawPolygon(int n)
    {
        Pen pen = new Pen(320, 260, myCanvas);
        pen.setColor(Color.MAGENTA);
        polygon(pen, n);
    }

    /**
     * Draw a wheel made of many squares.
     */
    public void drawWheel()
    {
        Pen pen = new Pen(250, 200, myCanvas);
        pen.setColor(Color.RED);

        for(int i=0; i<36; i++) {
            square(pen);
            pen.turn(10);
        }
    }
   
    /**
     * Draw a spiral.
     */
    public void drawSpiral()
    {
        Pen pen = new Pen(320, 260, myCanvas);
        pen.setColor(Color.BLACK);
        spiral(pen);
    }

    /**
     * Draw a square in the pen's color at the pen's location.
     */
    private void square(Pen pen)
    {
        for(int i = 0; i < 4; i++) {
            pen.move(100);
            pen.turn(90);
        }
    }

    /**
     * Draw a polygon with the given number of side
     * in the pen's color at the pen's location.
     * @param sides The number of sides.
     */
    private void polygon(Pen pen, int sides)
    {
        for(int i = 0; i < sides; i++) {
            pen.move(100);
            pen.turn(360 / sides);
        }
    }
   
    /**
     * Draw a spiral in the pen's color at the pen's location.
     */
    private void spiral(Pen pen)
    {       
        // Start in the middle.
        pen.penUp();
        Dimension size = myCanvas.getSize();
        pen.moveTo(size.width / 2, size.height / 2);
        // Face downwards.
        pen.turnTo(90);
        pen.penDown();
    }

    /**
     * Draw some random squiggles on the screen, in random colors.
     */
    public void colorScribble()
    {
        Pen pen = new Pen(250, 200, myCanvas);

        for (int i=0; i<10; i++) {
            // pick a random color
            int red = random.nextInt(256);
            int green = random.nextInt(256);
            int blue = random.nextInt(256);
            pen.setColor(new Color(red, green, blue));
           
            pen.randomSquiggle();
        }
    }
   
    /**
     * Clear the screen.
     */
    public void clear()
    {
        myCanvas.erase();
    }
}

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

/**
* Class Canvas - a class to allow for simple graphical
* drawing on a canvas.
*
* @author Michael Kölling (mik)
* @author Bruce Quig
*
* @version 2016.02.29
*/

public class Canvas
{
    private JFrame frame;
    private CanvasPane canvas;
    private Graphics2D graphic;
    private Color backgroundColor;
    private Image canvasImage;

    /**
     * Create a Canvas with default height, width and background color
     * (300, 300, white).
     * @param title title to appear in Canvas Frame    
     */
    public Canvas(String title)
    {
        this(title, 300, 300, Color.white);
    }

    /**
     * Create a Canvas with default background color (white).
     * @param title title to appear in Canvas Frame
     * @param width the desired width for the canvas
     * @param height the desired height for the canvas
     */
    public Canvas(String title, int width, int height)
    {
        this(title, width, height, Color.white);
    }

    /**
     * Create a Canvas.
     * @param title title to appear in Canvas Frame
     * @param width the desired width for the canvas
     * @param height the desired height for the canvas
     * @param bgClour the desired background color of the canvas
     */
    public Canvas(String title, int width, int height, Color bgColor)
    {
        frame = new JFrame();
        canvas = new CanvasPane();
        frame.setContentPane(canvas);
        frame.setTitle(title);
        canvas.setPreferredSize(new Dimension(width, height));
        backgroundColor = bgColor;
        frame.pack();
        setVisible(true);
    }

    /**
     * Set the canvas visibility and brings canvas to the front of screen
     * when made visible. This method can also be used to bring an already
     * visible canvas to the front of other windows.
     * @param visible boolean value representing the desired visibility of
     * the canvas (true or false)
     */
    public void setVisible(boolean visible)
    {
        if(graphic == null) {
            // first time: instantiate the offscreen image and fill it with
            // the background color
            Dimension size = canvas.getSize();
            canvasImage = canvas.createImage(size.width, size.height);
            graphic = (Graphics2D)canvasImage.getGraphics();
            graphic.setColor(backgroundColor);
            graphic.fillRect(0, 0, size.width, size.height);
            graphic.setColor(Color.black);
        }
        frame.setVisible(true);
    }

    /**
     * Provide information on visibility of the Canvas.
     * @return true if canvas is visible, false otherwise
     */
    public boolean isVisible()
    {
        return frame.isVisible();
    }

    /**
     * Draw the outline of a given shape onto the canvas.
     * @param shape the shape object to be drawn on the canvas
     */
    public void draw(Shape shape)
    {
        graphic.draw(shape);
        canvas.repaint();
    }

    /**
     * Fill the internal dimensions of a given shape with the current
     * foreground color of the canvas.
     * @param shape the shape object to be filled
     */
    public void fill(Shape shape)
    {
        graphic.fill(shape);
        canvas.repaint();
    }

    /**
     * Fill the internal dimensions of the given circle with the current
     * foreground color of the canvas.
     * @param xPos The x-coordinate of the circle center point
     * @param yPos The y-coordinate of the circle center point
     * @param diameter The diameter of the circle to be drawn
     */
    public void fillCircle(int xPos, int yPos, int diameter)
    {
        Ellipse2D.Double circle = new Ellipse2D.Double(xPos, yPos, diameter, diameter);
        fill(circle);
    }

    /**
     * Fill the internal dimensions of the given rectangle with the current
     * foreground color of the canvas. This is a convenience method. A similar
     * effect can be achieved with the "fill" method.
     */
    public void fillRectangle(int xPos, int yPos, int width, int height)
    {
        fill(new Rectangle(xPos, yPos, width, height));
    }

    /**
     * Erase the whole canvas.
     */
    public void erase()
    {
        Color original = graphic.getColor();
        graphic.setColor(backgroundColor);
        Dimension size = canvas.getSize();
        graphic.fill(new Rectangle(0, 0, size.width, size.height));
        graphic.setColor(original);
        canvas.repaint();
    }

    /**
     * Erase the internal dimensions of the given circle. This is a
     * convenience method. A similar effect can be achieved with
     * the "erase" method.
     */
    public void eraseCircle(int xPos, int yPos, int diameter)
    {
        Ellipse2D.Double circle = new Ellipse2D.Double(xPos, yPos, diameter, diameter);
        erase(circle);
    }

    /**
     * Erase the internal dimensions of the given rectangle. This is a
     * convenience method. A similar effect can be achieved with
     * the "erase" method.
     */
    public void eraseRectangle(int xPos, int yPos, int width, int height)
    {
        erase(new Rectangle(xPos, yPos, width, height));
    }

    /**
     * Erase a given shape's interior on the screen.
     * @param shape the shape object to be erased
     */
    public void erase(Shape shape)
    {
        Color original = graphic.getColor();
        graphic.setColor(backgroundColor);
        graphic.fill(shape);              // erase by filling background color
        graphic.setColor(original);
        canvas.repaint();
    }

    /**
     * Erases a given shape's outline on the screen.
     * @param shape the shape object to be erased
     */
    public void eraseOutline(Shape shape)
    {
        Color original = graphic.getColor();
        graphic.setColor(backgroundColor);
        graphic.draw(shape); // erase by drawing background color
        graphic.setColor(original);
        canvas.repaint();
    }

    /**
     * Draws an image onto the canvas.
     * @param image   the Image object to be displayed
     * @param x       x co-ordinate for Image placement
     * @param y       y co-ordinate for Image placement
     * @return returns boolean value representing whether the image was
     *          completely loaded
     */
    public boolean drawImage(Image image, int x, int y)
    {
        boolean result = graphic.drawImage(image, x, y, null);
        canvas.repaint();
        return result;
    }

    /**
     * Draws a String on the Canvas.
     * @param text   the String to be displayed
     * @param x      x co-ordinate for text placement
     * @param y      y co-ordinate for text placement
     */
    public void drawString(String text, int x, int y)
    {
        graphic.drawString(text, x, y);  
        canvas.repaint();
    }

    /**
     * Erases a String on the Canvas.
     * @param text     the String to be displayed
     * @param x        x co-ordinate for text placement
     * @param y        y co-ordinate for text placement
     */
    public void eraseString(String text, int x, int y)
    {
        Color original = graphic.getColor();
        graphic.setColor(backgroundColor);
        graphic.drawString(text, x, y);  
        graphic.setColor(original);
        canvas.repaint();
    }

    /**
     * Draws a line on the Canvas.
     * @param x1   x co-ordinate of start of line
     * @param y1   y co-ordinate of start of line
     * @param x2   x co-ordinate of end of line
     * @param y2   y co-ordinate of end of line
     */
    public void drawLine(int x1, int y1, int x2, int y2)
    {
        graphic.drawLine(x1, y1, x2, y2);  
        canvas.repaint();
    }

    /**
     * Sets the foreground color of the Canvas.
     * @param newColor   the new color for the foreground of the Canvas
     */
    public void setForegroundColor(Color newColor)
    {
        graphic.setColor(newColor);
    }

    /**
     * Returns the current color of the foreground.
     * @return   the color of the foreground of the Canvas
     */
    public Color getForegroundColor()
    {
        return graphic.getColor();
    }

    /**
     * Sets the background color of the Canvas.
     * @param newColor   the new color for the background of the Canvas
     */
    public void setBackgroundColor(Color newColor)
    {
        backgroundColor = newColor;  
        graphic.setBackground(newColor);
    }

    /**
     * Returns the current color of the background
     * @return   the color of the background of the Canvas
     */
    public Color getBackgroundColor()
    {
        return backgroundColor;
    }

    /**
     * changes the current Font used on the Canvas
     * @param newFont   new font to be used for String output
     */
    public void setFont(Font newFont)
    {
        graphic.setFont(newFont);
    }

    /**
     * Returns the current font of the canvas.
     * @return     the font currently in use
     **/
    public Font getFont()
    {
        return graphic.getFont();
    }

    /**
     * Sets the size of the canvas.
     * @param width    new width
     * @param height   new height
     */
    public void setSize(int width, int height)
    {
        canvas.setPreferredSize(new Dimension(width, height));
        Image oldImage = canvasImage;
        canvasImage = canvas.createImage(width, height);
        graphic = (Graphics2D)canvasImage.getGraphics();
        graphic.setColor(backgroundColor);
        graphic.fillRect(0, 0, width, height);
        graphic.drawImage(oldImage, 0, 0, null);
        frame.pack();
    }

    /**
     * Returns the size of the canvas.
     * @return     The current dimension of the canvas
     */
    public Dimension getSize()
    {
        return canvas.getSize();
    }

    /**
     * Waits for a specified number of milliseconds before finishing.
     * This provides an easy way to specify a small delay which can be
     * used when producing animations.
     * @param milliseconds the number
     */
    public void wait(int milliseconds)
    {
        try
        {
            Thread.sleep(milliseconds);
        }
        catch (InterruptedException e)
        {
            // ignoring exception at the moment
        }
    }

    /************************************************************************
     * Inner class CanvasPane - the actual canvas component contained in the
     * Canvas frame. This is essentially a JPanel with added capability to
     * refresh the image drawn on it.
     */
    private class CanvasPane extends JPanel
    {
        public void paint(Graphics g)
        {
            g.drawImage(canvasImage, 0, 0, null);
        }
    }
}

import java.awt.Color;
import java.util.Random;

/**
* A pen can be used to draw on a canvas. The pen maintains a position, direction, color,
* and an up/down state. The pen can be moved across the canvas. If the pen is down, it
* leaves a line on the canvas when moved. (If it is up, it will not draw a line.)
*
* @author Michael Kölling & David J. Barnes
* @version 2016.02.29
*/
public class Pen
{
    // constants for randomSquiggle method
    private static final int SQIGGLE_SIZE = 40;
    private static final int SQIGGLE_COUNT = 30;
   
    private int xPosition;
    private int yPosition;
    private int rotation;
    private Color color;
    private boolean penDown;

    private Canvas canvas;
    private Random random;

    /**
     * Create a new Pen with its own canvas. The pen will create a new canvas for
     * itself to draw on, and start in the default state (centre of canvas, direction
     * right, color black, pen down).
     */
    public Pen()
    {
        this (280, 220, new Canvas("My Canvas", 560, 440));
    }

    /**
     * Create a new Pen for a given canvas. The direction is initially 0 (to the right),
     * the color is black, and the pen is down.
     *
     * @param xPos the initial horizontal coordinate of the pen
     * @param yPos the initial vertical coordinate of the pen
     * @param drawingCanvas the canvas to draw on
     */
    public Pen(int xPos, int yPos, Canvas drawingCanvas)
    {
        xPosition = xPos;
        yPosition = yPos;
        rotation = 0;
        penDown = true;
        color = Color.BLACK;
        canvas = drawingCanvas;
        random = new Random();
    }

    /**
     * Move the specified distance in the current direction. If the pen is down,
     * leave a line on the canvas.
     *
     * @param distance The distance to move forward from the current location.
     */
    public void move(int distance)
    {
        double angle = Math.toRadians(rotation);
        int newX = (int) Math.round(xPosition + Math.cos(angle) * distance);
        int newY = (int) Math.round(yPosition + Math.sin(angle) * distance);
       
        moveTo(newX, newY);
    }

    /**
     * Move to the specified location. If the pen is down, leave a line on the canvas.
     *
     * @param x   The x-coordinate to move to.
     * @param y   The y-coordinate to move to.
     */
    public void moveTo(int x, int y)
    {
        if (penDown) {
            canvas.setForegroundColor(color);
            canvas.drawLine(xPosition, yPosition, x, y);
        }

        xPosition = x;
        yPosition = y;
    }

    /**
     * Turn the specified amount (out of a 360 degree circle) clockwise from the current
     * rotation.
     *
     * @param degrees The amount of degrees to turn. (360 is a full circle.)
     */
    public void turn(int degrees)
    {
        rotation = rotation + degrees;
    }

    /**
     * Turn to the specified direction. 0 is right, 90 is down, 180 is left, 270 is up.
     *
     * @param angle The angle to turn to.
     */
    public void turnTo(int angle)
    {
        rotation = angle;
    }

    /**
     * Set the drawing color.
     *
     * @param newColor The color to use for subsequent drawing operations.
     */
    public void setColor(Color newColor)
    {
        color = newColor;
    }

    /**
     * Lift the pen up. Moving afterwards will not leave a line on the canvas.
     */
    public void penUp()
    {
        penDown = false;
    }

    /**
     * Put the pen down. Moving afterwards will leave a line on the canvas.
     */
    public void penDown()
    {
        penDown = true;
    }

    /**
     * Scribble on the canvas in the current color. The size and complexity of the
     * squiggle produced is defined by the constants SQIGGLE_SIZE and SQIGGLE_COUNT.
     */
    public void randomSquiggle()
    {
        for (int i=0; i<SQIGGLE_COUNT; i++) {
            move(random.nextInt(SQIGGLE_SIZE));
            turn(160 + random.nextInt(40));
        }

    }

}

Solutions

Expert Solution

The spiral method in DrawDemo class has been modified to display a square spiral which has each line randomly colored in Red, Green or Blue. The Pen and Canvas classes have no change.

DrawDemo:

import java.awt.Color;
import java.util.ArrayList;
import java.util.Random;
import java.awt.Dimension;
/**
 * Class DrawDemo - provides some short demonstrations showing how to use the
 * Pen class to create various drawings.
 *
 * @author Michael Kölling and David J. Barnes
 * @version 2016.02.29
 */
public class DrawDemo
{
    private Canvas myCanvas;
    private Random random;
    /**
     * Prepare the drawing demo. Create a fresh canvas and make it visible.
     */
    public DrawDemo()
    {
        myCanvas = new Canvas("Drawing Demo", 500, 400);
        random = new Random();
    }
    /**
     * Draw a square on the screen.
     */
    public void drawSquare()
    {
        Pen pen = new Pen(320, 260, myCanvas);
        pen.setColor(Color.BLUE);
        square(pen);
    }
    /**
     * Draw a polygon with the given number of sides.
     * @param n The number of sides.
     */
    public void drawPolygon(int n)
    {
        Pen pen = new Pen(320, 260, myCanvas);
        pen.setColor(Color.MAGENTA);
        polygon(pen, n);
    }
    /**
     * Draw a wheel made of many squares.
     */
    public void drawWheel()
    {
        Pen pen = new Pen(250, 200, myCanvas);
        pen.setColor(Color.RED);
        for(int i=0; i<36; i++) {
            square(pen);
            pen.turn(10);
        }
    }

    /**
     * Draw a spiral.
     */
    public void drawSpiral()
    {
        Pen pen = new Pen(320, 260, myCanvas);
        spiral(pen);
    }

    /**
     * Draw a square in the pen's color at the pen's location.
     */
    private void square(Pen pen)
    {
        for(int i = 0; i < 4; i++) {
            pen.move(100);
            pen.turn(90);
        }
    }
    /**
     * Draw a polygon with the given number of side
     * in the pen's color at the pen's location.
     * @param sides The number of sides.
     */
    private void polygon(Pen pen, int sides)
    {
        for(int i = 0; i < sides; i++) {
            pen.move(100);
            pen.turn(360 / sides);
        }
    }

    /**
     * Draw a spiral in the pen's color at the pen's location.
     */
    private void spiral(Pen pen)
    {
        int length = 1;
        int gapBetweenEachLine = 10;
        // Start in the middle.
        pen.penUp();
        Dimension size = myCanvas.getSize();
        pen.moveTo(size.width / 2, size.height / 2);
        // Face downwards.
        pen.turnTo(90);
        pen.penDown();
        for (int i = 0; i < 10 ; i++) {
            pen.setColor(getRandomColor());
            pen.move(length);
            pen.turn(270);
            length = length + gapBetweenEachLine;
        }
    }

    private Color getRandomColor()
    {
        //Pick a random color out of Red, Green and Blue.
        ArrayList<Color> colorList = new ArrayList<>();
        colorList.add(Color.RED);
        colorList.add(Color.GREEN);
        colorList.add(Color.BLUE);

        return colorList.get(random.nextInt(3));
    }
    /**
     * Draw some random squiggles on the screen, in random colors.
     */
    public void colorScribble()
    {
        Pen pen = new Pen(250, 200, myCanvas);
        for (int i=0; i<10; i++) {
            // pick a random color
            int red = random.nextInt(256);
            int green = random.nextInt(256);
            int blue = random.nextInt(256);
            pen.setColor(new Color(red, green, blue));

            pen.randomSquiggle();
        }
    }

    /**
     * Clear the screen.
     */
    public void clear()
    {
        myCanvas.erase();
    }
}

Related Solutions

Modify the processFile method so that it will compile and it will not produce a runtime...
Modify the processFile method so that it will compile and it will not produce a runtime error: public static void processFile(File file) { File input = "contents.txt"; String line = null; try { input = new File(file); while ((line = input.readLine()) != null) { System.out.println(line); } return; } finally { if (file != null) { file.close(); } } }
Modify the FeetInches class so that it overloads the following operators: <= >= != Demonstrate the...
Modify the FeetInches class so that it overloads the following operators: <= >= != Demonstrate the class's capabilities in a simple program. this is what needs to be modified // Specification file for the FeetInches class #ifndef FEETINCHES_H #define FEETINCHES_H #include <iostream> using namespace std; class FeetInches; // Forward Declaration // Function Prototypes for Overloaded Stream Operators ostream &operator << (ostream &, const FeetInches &); istream &operator >> (istream &, FeetInches &); // The FeetInches class holds distances or measurements...
Modify the method so that the item with the highest key is not only returned by...
Modify the method so that the item with the highest key is not only returned by the method but is also removed from the array. Call the method removeMax(). // highArray.java // demonstrates array class with high-level interface // to run this program: C>java HighArrayApp //////////////////////////////////////////////////////////////// class HighArray { private long[] a; // ref to array a private int nElems; // number of data items //----------------------------------------------------------- public HighArray(int max) // constructor { a = new long[max]; // create the array...
1.) First Question on Class – the class Circle Given the code below, modify it so...
1.) First Question on Class – the class Circle Given the code below, modify it so that it runs. This will require you to add a class declaration and definition for Circle. For the constructor of Circle that takes no arguments, set the radius of the circle to be 10. You are to design the class Circle around the main method. You may NOT modify the body of the main method in anyway, if you do your code WILL NOT...
You are to modify the Pez class so that all errors are handled by exceptions. The...
You are to modify the Pez class so that all errors are handled by exceptions. The constructor must be able to handle invalid parameters. The user should not be able to get a piece of candy when the Pez is empty. The user should not be able to put in more candy than the Pez can hold. I would like you to do 3 types of exceptions. One handled within the class itself, one handled by the calling method and...
Modify the insertionSort() method in insertSort.java so it counts the number of copies and the number...
Modify the insertionSort() method in insertSort.java so it counts the number of copies and the number of comparisons it makes during a sort and displays the totals. To count comparisons, you will need to break up the double condition in the inner while loop. Use this program to measure the number of copies and comparisons for different amounts of inversely sorted data. Do the results verify O(N2 ) efficiency? Do the same for almost-sorted data (only a few items out...
Modify Example 5.1 to add a ReadAccount method to the BankAccount class that will return a...
Modify Example 5.1 to add a ReadAccount method to the BankAccount class that will return a BankAccountconstructed from data input from the keyboard. Override ReadAccount in SavingsAccount to return an account that refers to a SavingsAccount that you construct, again initializing it with data from the keyboard. Similarly, implement ReadAccount in the CheckingAccount class. Use the following code to test your work. public static void testCode()         {             SavingsAccount savings = new SavingsAccount(100.00, 3.5);             SavingsAccount s = (SavingsAccount)savings.ReadAccount();...
**** IN C++ **** 1) Modify the class pointerDataClass so the main function below is working...
**** IN C++ **** 1) Modify the class pointerDataClass so the main function below is working properly. Use deep copy. int main() { pointerDataClass list1(10); list1.insertAt(0, 50); list1.insertAt(4, 30); list1.insertAt(8, 60); cout<<"List1: " < list1.displayData(); cout<<"List 2: "< pointerDataClass list2(list1); list2.displayData(); list1.insertAt(4,100); cout<<"List1: (after insert 100 at indext 4) " < list1.displayData(); cout<<"List 2: "< list2.displayData(); return 0; } Code: #include using namespace std; class pointerDataClass { int maxSize; int length; int *p; public: pointerDataClass(int size); ~pointerDataClass(); void insertAt(int index,...
**** IN C++ **** 1) Modify the class pointerDataClass so the main function below is working...
**** IN C++ **** 1) Modify the class pointerDataClass so the main function below is working properly. Use shallow copy. int main() { pointerDataClass list1(10); list1.insertAt(0, 50); list1.insertAt(4, 30); list1.insertAt(8, 60); cout<<"List1: " < list1.displayData(); cout<<"List 2: "< pointerDataClass list2(list1); list2.displayData(); list1.insertAt(4,100); cout<<"List1: (after insert 100 at indext 4) " < list1.displayData(); cout<<"List 2: "< list2.displayData(); return 0; } Code: #include using namespace std; class pointerDataClass { int maxSize; int length; int *p; public: pointerDataClass(int size); ~pointerDataClass(); void insertAt(int index,...
Modify the GreenvilleRevenue program so that it uses the Contestant class and performs the following tasks:...
Modify the GreenvilleRevenue program so that it uses the Contestant class and performs the following tasks: The program prompts the user for the number of contestants in this year’s competition; the number must be between 0 and 30. The program continues to prompt the user until a valid value is entered. The expected revenue is calculated and displayed. The revenue is $25 per contestant. For example if there were 3 contestants, the expected revenue would be displayed as: Revenue expected...
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT