import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import java.util.Vector;
import java.awt.Rectangle;
{
//runtime variables
boolean running = false;
boolean kill = false;
//buttons
//text
//scrollbars
private final int barHeight = 20, SLIDER_WIDTH = 10, MAXSPEED = 110, MINSPEED = 0, MAX_SIZE = 110, MIN_SIZE = 10;
//drawn objs
Ball ball;
//boundaries
static int boundx = 640;
static int boundy = 400;
//speed
int speed = MAXSPEED/2;
int delay = MAXSPEED - speed;
//initialize the applet and draw everything
public void init()
{
double colWeight[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};//15 cols
double rowWeight[] = {1,1,1,1,1,1,1,1,1,1}; //10 rows
int colWidth[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};//15 cols
int rowHeight[] = {1,1,1,1,1,1,1,1,1,1}; //10 rows
gbl.rowHeights = rowHeight;
gbl.rowWeights = rowWeight;
gbl.columnWeights = colWeight;
gbl.columnWidths = colWidth;
setBounds(0,0,480,640);
controlpanel.setLayout(gbl);
controlpanel.setSize(640,80);
drawingpanel
= new Panel(); drawingpanel.setSize(640,400);
ball = new Ball();
drawingpanel.add("Center",ball);
drawingpanel.setVisible(true);
//speed scrollbar
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 3;
c.gridheight = 1;
c.gridx = 1;
c.gridy = 7;
gbl.setConstraints(this.speedbar,c);
//run button
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 2;
c.gridheight = 1;
c.gridx = 5;
c.gridy = 7;
gbl.setConstraints(this.runbutton,c);
//pause button
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 2;
c.gridheight = 1;
c.gridx = 8;
c.gridy = 7;
gbl.setConstraints(this.pausebutton,c);
//size scrollbar
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 3;
c.gridheight = 1;
c.gridx = 11;
c.gridy = 7;
gbl.setConstraints(this.sizebar,c);
//speed text label
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 3;
c.gridheight = 1;
c.gridx = 1;
c.gridy = 8;
gbl.setConstraints(this.speedlabel,c);
//size text label
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 3;
c.gridheight = 1;
c.gridx = 11;
c.gridy = 8;
gbl.setConstraints(this.sizelabel,c);
//quit button
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 3;
c.gridheight = 1;
c.gridx = 6;
c.gridy = 9;
gbl.setConstraints(this.quitbutton,c);
//add to the screen
controlpanel.add(this.speedbar);
controlpanel.add(this.runbutton);
controlpanel.add(this.pausebutton);
controlpanel.add(this.sizebar);
controlpanel.add(this.speedlabel);
controlpanel.add(this.sizelabel);
controlpanel.add(this.quitbutton);
//add listners
speedbar.addAdjustmentListener(this);
runbutton.addActionListener(this);
pausebutton.addActionListener(this);
sizebar.addAdjustmentListener(this);
quitbutton.addActionListener(this);
ball.addMouseListener(this);
ball.addMouseMotionListener(this);
//add the panels
add("South", controlpanel);
add("Center", drawingpanel);
//drawing paramaters
//loc = new Point(loc.x+dx, loc.y+dy);
}
public void start()
{
if (ballThread == null)
{
ballThread
= new Thread(this); ballThread.start();
}
}
public void run()
{
while (!kill)
{
if (running)
{
ball.repaint();
}
try
{
}
}
stop();
}
{
super.paint(g);
}
{
if (!ball.flag)
{
p
= new Point(m.
getPoint()); Vector<Rectangle> v;
v = (Vector<Rectangle>)ball.r;
boolean done = false;
int i = 0;
while (!done)
{
if(v.elementAt(i).contains(p))
{
v.removeElement(i);
System.
err.
print("Element removed"); }
i++;
if(i>=v.size())
done=true;
}
ball.r = v;
}
}
{
ball.flag = true;
ball.start = m.getPoint();
ball.end = ball.start;
ball.cur = ball.start;
}
{
if (ball.flag == true)
{
ball.cur = m.getPoint();
}
}
{
//add rect method in ball
ball.end = ball.cur;
if (ball.flag)
{
ball.addrect();
}
ball.flag = false;
}
{
Object source
= e.
getSource(); if (source == this.runbutton)
{
running = true;
}
else if (source == this.pausebutton)
{
running = false;
}
else if (source == this.quitbutton)
{
//kill processes
kill = true;
//remove listeners
stop();
}
}
{
Object source
= e.
getSource(); //set the new size.
if (source == sizebar)
{
//check for clipping
int newsize = sizebar.getValue();
newsize = ball.resize(newsize);
sizebar.setValue(newsize);
}
if (source == speedbar)
{
speed = speedbar.getValue();
delay = MAXSPEED - speed;
}
}
public void stop()
{
this.speedbar.removeAdjustmentListener(this);
this.runbutton.removeActionListener(this);
this.pausebutton.removeActionListener(this);
this.sizebar.removeAdjustmentListener(this);
this.quitbutton.removeActionListener(this);
this.removeMouseListener(this);
this.removeMouseMotionListener(this);
}
}
//class to handle animations
{
static int size = 50;
static Point loc
= new Point(100,
100); //location of the ball
//boundaries
static int boundx = 640;
static int boundy = 400;
//directions
int dx = 1; //1 = left, -1 = right
int dy = 1; //1 = up, -1 = down
static boolean flag = false;
//rectangle vector and associated things
Vector<Rectangle> r = new Vector<Rectangle>();
public int resize(int newsize)
{
// x
if (loc.x+newsize >= boundx)
{
newsize = boundx - loc.x - 1;
return newsize;
}
// y
if (loc.y+newsize >= boundy + 100)
{
newsize = boundy+100 - loc.y - 1;
return newsize;
}
size = newsize;
return newsize;
}
public void move()
{
//if it will hit the right or left boundary, flip the x direction and set it
if (loc.x+size >= boundx || loc.x <= 0)
{ dx *= -1; }
//if it will hit the top or bottom boundray, flip the y direction and set it
if (loc.y+size >= boundy || loc.y <= 0)
{ dy *= -1; }
for (int i = 0; i < r.size(); i++)
{
int rx = temp.x;
int ry = temp.y;
int rh = temp.height;
int rw = temp.width;
//If the ball hits either side of the rectangle, change the x direction
if((loc.x > rx && loc.x > ry && loc.x < (ry + rh))||(loc.x < (rx + rw) && loc.x > rx && loc.x <(ry + rh)))
{dx *= -1;}
//If the ball hits either the top or bottom, change the y direction
if((loc.y > ry && loc.y > rx && loc.y < (rx + rw))||(loc.y < (ry + rh) && loc.y > ry && loc.y <(rx + rw)))
{dy *= -1;}
}
//Increment or decrement the location of the ball based on the X and Y directions.
loc.x += dx;
loc.y += dy;
}
public void addrect()
{
//What was wrong here is that for the final parameter, I had Math.abs(end.y-start.x).
if (end.x > start.x && end.y > start.y)
r.
add(new Rectangle(start.
x,start.
y,
Math.
abs(end.
x-start.
x),
Math.
abs(end.
y-start.
y))); if (end.x > start.x && end.y < start.y)
r.
add(new Rectangle(start.
x,end.
y,
Math.
abs(end.
x-start.
x),
Math.
abs(end.
y-start.
y))); if (end.x < start.x && end.y > start.y)
r.
add(new Rectangle(end.
x, start.
y,
Math.
abs(end.
x-start.
x),
Math.
abs(end.
y-start.
y))); if (end.x < start.x && end.y < start.y)
}
{
//super.update(g); //Getting rid of this fixed double buffering
// I looked at P-dawg's code and he didn't have it.
if (offscreen == null)
{
offscreen = createImage(getWidth(), getHeight());
}
buffer = offscreen.getGraphics();
buffer.setColor(getBackground());
buffer.fillRect(0,0,640, 410);
mypaint(buffer);
g.drawImage(offscreen, 0, 0, this);
}
{
//update loc
move();
//draw
for (int i = 0; i < r.size(); i++)
{
g.fillRect(t.x,t.y,t.width,t.height);
}
g.drawOval(loc.x, loc.y, size, size);
g.fillOval(loc.x, loc.y, size, size);
if (flag)
{
if (!r.isEmpty())
{
for (int i = 0; i < r.size(); i++)
{
if (cur.x > start.x && cur.y > start.y)
{
g.
drawRect(start.
x, start.
y,
Math.
abs(cur.
x - start.
x),
Math.
abs(cur.
y - start.
y)); g.
fillRect(start.
x, start.
y,
Math.
abs(cur.
x - start.
x),
Math.
abs(cur.
y - start.
y)); }
if (cur.x > start.x && cur.y < start.y)
{
g.
drawRect(start.
x, cur.
y,
Math.
abs(cur.
x - start.
x),
Math.
abs(cur.
y - start.
y)); g.
fillRect(start.
x, cur.
y,
Math.
abs(cur.
x - start.
x),
Math.
abs(cur.
y - start.
y)); }
if (cur.x < start.x && cur.y > start.y)
{
g.
drawRect(cur.
x, start.
y,
Math.
abs(cur.
x - start.
x),
Math.
abs(cur.
y - start.
y)); g.
fillRect(cur.
x, start.
y,
Math.
abs(cur.
x - start.
x),
Math.
abs(cur.
y - start.
y)); }
if (cur.x < start.x && cur.y < start.y)
{
g.
drawRect(cur.
x, cur.
y,
Math.
abs(cur.
x - start.
x),
Math.
abs(cur.
y - start.
y)); g.
fillRect(cur.
x, cur.
y,
Math.
abs(cur.
x - start.
x),
Math.
abs(cur.
y - start.
y)); }
}
}
}
}
}
aW1wb3J0IGphdmEuYXd0Lio7CmltcG9ydCBqYXZhLmFwcGxldC4qOwppbXBvcnQgamF2YS5hd3QuZXZlbnQuKjsKaW1wb3J0IGphdmEudXRpbC5WZWN0b3I7CmltcG9ydCBqYXZhLmF3dC5SZWN0YW5nbGU7CgpwdWJsaWMgY2xhc3MgQm91bmNlMiBleHRlbmRzIEFwcGxldCBpbXBsZW1lbnRzIEFjdGlvbkxpc3RlbmVyLCBBZGp1c3RtZW50TGlzdGVuZXIsIE1vdXNlTGlzdGVuZXIsIE1vdXNlTW90aW9uTGlzdGVuZXIsIFJ1bm5hYmxlCnsKICAvL3J1bnRpbWUgdmFyaWFibGVzCiAgYm9vbGVhbiBydW5uaW5nID0gZmFsc2U7CiAgYm9vbGVhbiBraWxsID0gZmFsc2U7CgogIC8vYnV0dG9ucwogIEJ1dHRvbiBydW5idXR0b24gPSBuZXcgQnV0dG9uKCJSdW4iKTsKICBCdXR0b24gcGF1c2VidXR0b24gPSBuZXcgQnV0dG9uKCJQYXVzZSIpOwogIEJ1dHRvbiBxdWl0YnV0dG9uID0gbmV3IEJ1dHRvbigiUXVpdCIpOwoKICAvL3RleHQKICBMYWJlbCBzcGVlZGxhYmVsID0gbmV3IExhYmVsKCJTcGVlZCIpOwogIExhYmVsIHNpemVsYWJlbCA9IG5ldyBMYWJlbCgiU2l6ZSIpOwoKICBQYW5lbCBkcmF3aW5ncGFuZWw7CgogIC8vc2Nyb2xsYmFycwogIHByaXZhdGUgZmluYWwgaW50IGJhckhlaWdodCA9IDIwLCBTTElERVJfV0lEVEggPSAxMCwgTUFYU1BFRUQgPSAxMTAsIE1JTlNQRUVEID0gMCwgTUFYX1NJWkUgPSAxMTAsIE1JTl9TSVpFID0gMTA7CiAgU2Nyb2xsYmFyIHNwZWVkYmFyID0gbmV3IFNjcm9sbGJhcihTY3JvbGxiYXIuSE9SSVpPTlRBTCwgTUFYU1BFRUQvMiwgU0xJREVSX1dJRFRILCBNSU5TUEVFRCwgTUFYU1BFRUQpOwogIFNjcm9sbGJhciBzaXplYmFyID0gbmV3IFNjcm9sbGJhcihTY3JvbGxiYXIuSE9SSVpPTlRBTCwgTUFYX1NJWkUvMiwgU0xJREVSX1dJRFRILCBNSU5fU0laRSwgTUFYX1NJWkUpOwoKICAvL2RyYXduIG9ianMKICBCYWxsIGJhbGw7CiAgCiAgcHJpdmF0ZSBUaHJlYWQgYmFsbFRocmVhZDsKCiAgLy9ib3VuZGFyaWVzCiAgc3RhdGljIGludCBib3VuZHggPSA2NDA7CiAgc3RhdGljIGludCBib3VuZHkgPSA0MDA7CgogIC8vc3BlZWQKICBpbnQgc3BlZWQgPSBNQVhTUEVFRC8yOwogIGludCBkZWxheSA9IE1BWFNQRUVEIC0gc3BlZWQ7CgogIC8vaW5pdGlhbGl6ZSB0aGUgYXBwbGV0IGFuZCBkcmF3IGV2ZXJ5dGhpbmcKICBwdWJsaWMgdm9pZCBpbml0KCkKICB7CiAgICBkb3VibGUgY29sV2VpZ2h0W10gPSB7MSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDF9Oy8vMTUgY29scwogICAgZG91YmxlIHJvd1dlaWdodFtdID0gezEsMSwxLDEsMSwxLDEsMSwxLDF9OyAvLzEwIHJvd3MKICAgIGludCBjb2xXaWR0aFtdID0gezEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxfTsvLzE1IGNvbHMKICAgIGludCByb3dIZWlnaHRbXSA9IHsxLDEsMSwxLDEsMSwxLDEsMSwxfTsgLy8xMCByb3dzCiAgICBHcmlkQmFnQ29uc3RyYWludHMgYyA9IG5ldyBHcmlkQmFnQ29uc3RyYWludHMoKTsKICAgIEdyaWRCYWdMYXlvdXQgZ2JsID0gbmV3IEdyaWRCYWdMYXlvdXQoKTsKICAgIGdibC5yb3dIZWlnaHRzID0gcm93SGVpZ2h0OwogICAgZ2JsLnJvd1dlaWdodHMgPSByb3dXZWlnaHQ7CiAgICBnYmwuY29sdW1uV2VpZ2h0cyA9IGNvbFdlaWdodDsKICAgIGdibC5jb2x1bW5XaWR0aHMgPSBjb2xXaWR0aDsKICAgIGMuYW5jaG9yID0gR3JpZEJhZ0NvbnN0cmFpbnRzLkNFTlRFUjsKCiAgICBzZXRCb3VuZHMoMCwwLDQ4MCw2NDApOwogICAgc2V0TGF5b3V0KG5ldyBCb3JkZXJMYXlvdXQoKSk7CiAgICBQYW5lbCBjb250cm9scGFuZWwgPSBuZXcgUGFuZWwoKTsKICAgIGNvbnRyb2xwYW5lbC5zZXRMYXlvdXQoZ2JsKTsKICAgIGNvbnRyb2xwYW5lbC5zZXRTaXplKDY0MCw4MCk7CgogICAgZHJhd2luZ3BhbmVsID0gbmV3IFBhbmVsKCk7CiAgICBkcmF3aW5ncGFuZWwuc2V0TGF5b3V0KG5ldyBCb3JkZXJMYXlvdXQoMCwwKSk7CiAgICBkcmF3aW5ncGFuZWwuc2V0U2l6ZSg2NDAsNDAwKTsKICAgIGJhbGwgPSBuZXcgQmFsbCgpOwogICAgZHJhd2luZ3BhbmVsLmFkZCgiQ2VudGVyIixiYWxsKTsKICAgIGRyYXdpbmdwYW5lbC5zZXRWaXNpYmxlKHRydWUpOwoKICAgIC8vc3BlZWQgc2Nyb2xsYmFyCiAgICBjLndlaWdodHggPSAxOwogICAgYy53ZWlnaHR5ID0gMTsKICAgIGMuZ3JpZHdpZHRoID0gMzsKICAgIGMuZ3JpZGhlaWdodCA9IDE7CiAgICBjLmdyaWR4ID0gMTsKICAgIGMuZ3JpZHkgPSA3OwogICAgYy5maWxsPSBHcmlkQmFnQ29uc3RyYWludHMuSE9SSVpPTlRBTDsKICAgIGdibC5zZXRDb25zdHJhaW50cyh0aGlzLnNwZWVkYmFyLGMpOwoKICAgIC8vcnVuIGJ1dHRvbgogICAgYy53ZWlnaHR4ID0gMTsKICAgIGMud2VpZ2h0eSA9IDE7CiAgICBjLmdyaWR3aWR0aCA9IDI7CiAgICBjLmdyaWRoZWlnaHQgPSAxOwogICAgYy5ncmlkeCA9IDU7CiAgICBjLmdyaWR5ID0gNzsKICAgIGMuZmlsbD0gR3JpZEJhZ0NvbnN0cmFpbnRzLkhPUklaT05UQUw7CiAgICBnYmwuc2V0Q29uc3RyYWludHModGhpcy5ydW5idXR0b24sYyk7CgogICAgLy9wYXVzZSBidXR0b24KICAgIGMud2VpZ2h0eCA9IDE7CiAgICBjLndlaWdodHkgPSAxOwogICAgYy5ncmlkd2lkdGggPSAyOwogICAgYy5ncmlkaGVpZ2h0ID0gMTsKICAgIGMuZ3JpZHggPSA4OwogICAgYy5ncmlkeSA9IDc7CiAgICBjLmZpbGw9IEdyaWRCYWdDb25zdHJhaW50cy5IT1JJWk9OVEFMOwogICAgZ2JsLnNldENvbnN0cmFpbnRzKHRoaXMucGF1c2VidXR0b24sYyk7CgogICAgLy9zaXplIHNjcm9sbGJhcgogICAgYy53ZWlnaHR4ID0gMTsKICAgIGMud2VpZ2h0eSA9IDE7CiAgICBjLmdyaWR3aWR0aCA9IDM7CiAgICBjLmdyaWRoZWlnaHQgPSAxOwogICAgYy5ncmlkeCA9IDExOwogICAgYy5ncmlkeSA9IDc7CiAgICBjLmZpbGw9IEdyaWRCYWdDb25zdHJhaW50cy5IT1JJWk9OVEFMOwogICAgZ2JsLnNldENvbnN0cmFpbnRzKHRoaXMuc2l6ZWJhcixjKTsKCiAgICAvL3NwZWVkIHRleHQgbGFiZWwKICAgIGMud2VpZ2h0eCA9IDE7CiAgICBjLndlaWdodHkgPSAxOwogICAgYy5ncmlkd2lkdGggPSAzOwogICAgYy5ncmlkaGVpZ2h0ID0gMTsKICAgIGMuZ3JpZHggPSAxOwogICAgYy5ncmlkeSA9IDg7CiAgICBjLmZpbGw9IEdyaWRCYWdDb25zdHJhaW50cy5IT1JJWk9OVEFMOwogICAgZ2JsLnNldENvbnN0cmFpbnRzKHRoaXMuc3BlZWRsYWJlbCxjKTsKCiAgICAvL3NpemUgdGV4dCBsYWJlbAogICAgYy53ZWlnaHR4ID0gMTsKICAgIGMud2VpZ2h0eSA9IDE7CiAgICBjLmdyaWR3aWR0aCA9IDM7CiAgICBjLmdyaWRoZWlnaHQgPSAxOwogICAgYy5ncmlkeCA9IDExOwogICAgYy5ncmlkeSA9IDg7CiAgICBjLmZpbGw9IEdyaWRCYWdDb25zdHJhaW50cy5IT1JJWk9OVEFMOwogICAgZ2JsLnNldENvbnN0cmFpbnRzKHRoaXMuc2l6ZWxhYmVsLGMpOwoKICAgIC8vcXVpdCBidXR0b24KICAgIGMud2VpZ2h0eCA9IDE7CiAgICBjLndlaWdodHkgPSAxOwogICAgYy5ncmlkd2lkdGggPSAzOwogICAgYy5ncmlkaGVpZ2h0ID0gMTsKICAgIGMuZ3JpZHggPSA2OwogICAgYy5ncmlkeSA9IDk7CiAgICBjLmZpbGw9IEdyaWRCYWdDb25zdHJhaW50cy5IT1JJWk9OVEFMOwogICAgZ2JsLnNldENvbnN0cmFpbnRzKHRoaXMucXVpdGJ1dHRvbixjKTsKCiAgICAvL2FkZCB0byB0aGUgc2NyZWVuCiAgICBjb250cm9scGFuZWwuYWRkKHRoaXMuc3BlZWRiYXIpOwogICAgY29udHJvbHBhbmVsLmFkZCh0aGlzLnJ1bmJ1dHRvbik7CiAgICBjb250cm9scGFuZWwuYWRkKHRoaXMucGF1c2VidXR0b24pOwogICAgY29udHJvbHBhbmVsLmFkZCh0aGlzLnNpemViYXIpOwogICAgY29udHJvbHBhbmVsLmFkZCh0aGlzLnNwZWVkbGFiZWwpOwogICAgY29udHJvbHBhbmVsLmFkZCh0aGlzLnNpemVsYWJlbCk7CiAgICBjb250cm9scGFuZWwuYWRkKHRoaXMucXVpdGJ1dHRvbik7CgogICAgLy9hZGQgbGlzdG5lcnMKICAgIHNwZWVkYmFyLmFkZEFkanVzdG1lbnRMaXN0ZW5lcih0aGlzKTsKICAgIHJ1bmJ1dHRvbi5hZGRBY3Rpb25MaXN0ZW5lcih0aGlzKTsKICAgIHBhdXNlYnV0dG9uLmFkZEFjdGlvbkxpc3RlbmVyKHRoaXMpOwogICAgc2l6ZWJhci5hZGRBZGp1c3RtZW50TGlzdGVuZXIodGhpcyk7CiAgICBxdWl0YnV0dG9uLmFkZEFjdGlvbkxpc3RlbmVyKHRoaXMpOwogICAgYmFsbC5hZGRNb3VzZUxpc3RlbmVyKHRoaXMpOwogICAgYmFsbC5hZGRNb3VzZU1vdGlvbkxpc3RlbmVyKHRoaXMpOwoKICAgIC8vYWRkIHRoZSBwYW5lbHMKICAgIGFkZCgiU291dGgiLCBjb250cm9scGFuZWwpOwogICAgYWRkKCJDZW50ZXIiLCBkcmF3aW5ncGFuZWwpOwoKCiAgICAvL2RyYXdpbmcgcGFyYW1hdGVycwogICAgLy9sb2MgPSBuZXcgUG9pbnQobG9jLngrZHgsIGxvYy55K2R5KTsKICB9CgogIHB1YmxpYyB2b2lkIHN0YXJ0KCkKICB7CiAgICBpZiAoYmFsbFRocmVhZCA9PSBudWxsKQogICAgewogICAgICBiYWxsVGhyZWFkID0gbmV3IFRocmVhZCh0aGlzKTsKICAgICAgYmFsbFRocmVhZC5zdGFydCgpOwogICAgfQogIH0KCiAgcHVibGljIHZvaWQgcnVuKCkKICB7CiAgICBUaHJlYWQuY3VycmVudFRocmVhZCgpLnNldFByaW9yaXR5KFRocmVhZC5NQVhfUFJJT1JJVFkpOwogICAgd2hpbGUgKCFraWxsKQogICAgewogICAgICBpZiAocnVubmluZykKICAgICAgewogICAgICAgIGJhbGwucmVwYWludCgpOwogICAgICB9CiAgICAgIHRyeQogICAgICB7CiAgICAgICAgVGhyZWFkLnNsZWVwKGRlbGF5KTsKICAgICAgfQogICAgICBjYXRjaChJbnRlcnJ1cHRlZEV4Y2VwdGlvbiBlKXtTeXN0ZW0uZXJyLnByaW50bG4oIkludGVycnVwdGVkLiIpO30KICAgIH0KICAgIHN0b3AoKTsKICB9CgogIHB1YmxpYyB2b2lkIHBhaW50KEdyYXBoaWNzIGcpCiAgewogICAgc3VwZXIucGFpbnQoZyk7CiAgfQoKCXB1YmxpYyB2b2lkIG1vdXNlQ2xpY2tlZChNb3VzZUV2ZW50IG0pCgl7CgkJaWYgKCFiYWxsLmZsYWcpCiAgICB7CiAgICAgIFBvaW50IHA7CiAgICAgIHAgPSBuZXcgUG9pbnQobS5nZXRQb2ludCgpKTsKICAgICAgVmVjdG9yPFJlY3RhbmdsZT4gdjsKICAgICAgdiA9IChWZWN0b3I8UmVjdGFuZ2xlPiliYWxsLnI7CiAgICAgIGJvb2xlYW4gZG9uZSA9IGZhbHNlOwogICAgICBpbnQgaSA9IDA7CgogICAgICB3aGlsZSAoIWRvbmUpCiAgICAgIHsKICAgICAgICBpZih2LmVsZW1lbnRBdChpKS5jb250YWlucyhwKSkKICAgICAgICB7CiAgICAgICAgICB2LnJlbW92ZUVsZW1lbnQoaSk7CiAgICAgICAgICBTeXN0ZW0uZXJyLnByaW50KCJFbGVtZW50IHJlbW92ZWQiKTsKICAgICAgICB9CiAgICAgICAgaSsrOwogICAgICAgIGlmKGk+PXYuc2l6ZSgpKQogICAgICAgICAgZG9uZT10cnVlOwogICAgICB9IAogICAgICBiYWxsLnIgPSB2OwogICAgfQoJfQoJCglwdWJsaWMgdm9pZCBtb3VzZVByZXNzZWQoTW91c2VFdmVudCBtKQoJewoJCWJhbGwuZmxhZyA9IHRydWU7CgkJYmFsbC5zdGFydCA9IG0uZ2V0UG9pbnQoKTsKICAgIGJhbGwuZW5kID0gYmFsbC5zdGFydDsKICAgIGJhbGwuY3VyID0gYmFsbC5zdGFydDsKCX0KCQoJcHVibGljIHZvaWQgbW91c2VEcmFnZ2VkKE1vdXNlRXZlbnQgbSkKCXsKCQlpZiAoYmFsbC5mbGFnID09IHRydWUpCgkJewoJCQliYWxsLmN1ciA9IG0uZ2V0UG9pbnQoKTsKCQl9Cgl9CgkKCXB1YmxpYyB2b2lkIG1vdXNlUmVsZWFzZWQoTW91c2VFdmVudCBtKQoJewogICAgLy9hZGQgcmVjdCBtZXRob2QgaW4gYmFsbAogICAgYmFsbC5lbmQgPSBiYWxsLmN1cjsKICAgIGlmIChiYWxsLmZsYWcpCiAgICB7CiAgICAgIGJhbGwuYWRkcmVjdCgpOwogICAgfQoJCWJhbGwuZmxhZyA9IGZhbHNlOwoJfSAKCQoJcHVibGljIHZvaWQgbW91c2VFbnRlcmVkKE1vdXNlRXZlbnQgbSl7fQoJcHVibGljIHZvaWQgbW91c2VFeGl0ZWQoTW91c2VFdmVudCBtKXt9CglwdWJsaWMgdm9pZCBtb3VzZU1vdmVkKE1vdXNlRXZlbnQgbSl7fQoKICBwdWJsaWMgdm9pZCBhY3Rpb25QZXJmb3JtZWQoQWN0aW9uRXZlbnQgZSkKICB7CiAgICBPYmplY3Qgc291cmNlID0gZS5nZXRTb3VyY2UoKTsKICAgIGlmIChzb3VyY2UgPT0gdGhpcy5ydW5idXR0b24pCiAgICB7CiAgICAgIHJ1bm5pbmcgPSB0cnVlOwogICAgfQogICAgZWxzZSBpZiAoc291cmNlID09IHRoaXMucGF1c2VidXR0b24pCiAgICB7CiAgICAgIHJ1bm5pbmcgPSBmYWxzZTsKICAgIH0KICAgIGVsc2UgaWYgKHNvdXJjZSA9PSB0aGlzLnF1aXRidXR0b24pCiAgICB7CiAgICAgIC8va2lsbCBwcm9jZXNzZXMKICAgICAga2lsbCA9IHRydWU7CiAgICAgIC8vcmVtb3ZlIGxpc3RlbmVycwogICAgICBzdG9wKCk7CiAgICB9CiAgfQoKICBwdWJsaWMgdm9pZCBhZGp1c3RtZW50VmFsdWVDaGFuZ2VkKEFkanVzdG1lbnRFdmVudCBlKQogIHsKICAgIE9iamVjdCBzb3VyY2UgPSBlLmdldFNvdXJjZSgpOwogICAgLy9zZXQgdGhlIG5ldyBzaXplLgogICAgaWYgKHNvdXJjZSA9PSBzaXplYmFyKQogICAgewogICAgICAvL2NoZWNrIGZvciBjbGlwcGluZwogICAgICBpbnQgbmV3c2l6ZSA9IHNpemViYXIuZ2V0VmFsdWUoKTsKICAgICAgbmV3c2l6ZSA9IGJhbGwucmVzaXplKG5ld3NpemUpOwogICAgICBzaXplYmFyLnNldFZhbHVlKG5ld3NpemUpOwogICAgfQogICAgaWYgKHNvdXJjZSA9PSBzcGVlZGJhcikKICAgIHsKICAgICAgc3BlZWQgPSBzcGVlZGJhci5nZXRWYWx1ZSgpOwogICAgICBkZWxheSA9IE1BWFNQRUVEIC0gc3BlZWQ7CiAgICB9CiAgfQoKICBwdWJsaWMgdm9pZCBzdG9wKCkKICB7CiAgICB0aGlzLnNwZWVkYmFyLnJlbW92ZUFkanVzdG1lbnRMaXN0ZW5lcih0aGlzKTsKICAgIHRoaXMucnVuYnV0dG9uLnJlbW92ZUFjdGlvbkxpc3RlbmVyKHRoaXMpOwogICAgdGhpcy5wYXVzZWJ1dHRvbi5yZW1vdmVBY3Rpb25MaXN0ZW5lcih0aGlzKTsKICAgIHRoaXMuc2l6ZWJhci5yZW1vdmVBZGp1c3RtZW50TGlzdGVuZXIodGhpcyk7CiAgICB0aGlzLnF1aXRidXR0b24ucmVtb3ZlQWN0aW9uTGlzdGVuZXIodGhpcyk7CiAgICB0aGlzLnJlbW92ZU1vdXNlTGlzdGVuZXIodGhpcyk7CiAgICB0aGlzLnJlbW92ZU1vdXNlTW90aW9uTGlzdGVuZXIodGhpcyk7CiAgICBUaHJlYWQuY3VycmVudFRocmVhZCgpLnNldFByaW9yaXR5KFRocmVhZC5NSU5fUFJJT1JJVFkpOwogIH0KfQkKCi8vY2xhc3MgdG8gaGFuZGxlIGFuaW1hdGlvbnMKY2xhc3MgQmFsbCBleHRlbmRzIENhbnZhcwp7ICAgCiAgUmVjdGFuZ2xlIHRlbXA7CiAgc3RhdGljIGludCBzaXplID0gNTA7CiAgcHJpdmF0ZSBHcmFwaGljcyBvYmo7CiAgSW1hZ2Ugb2Zmc2NyZWVuID0gbnVsbDsKICBzdGF0aWMgUG9pbnQgbG9jID0gbmV3IFBvaW50KDEwMCwxMDApOyAvL2xvY2F0aW9uIG9mIHRoZSBiYWxsCgogIC8vYm91bmRhcmllcwogIHN0YXRpYyBpbnQgYm91bmR4ID0gNjQwOwogIHN0YXRpYyBpbnQgYm91bmR5ID0gNDAwOwoKICAvL2RpcmVjdGlvbnMKICBpbnQgZHggPSAxOyAvLzEgPSBsZWZ0LCAtMSA9IHJpZ2h0CiAgaW50IGR5ID0gMTsgLy8xID0gdXAsIC0xID0gZG93bgoKICBzdGF0aWMgYm9vbGVhbiBmbGFnID0gZmFsc2U7CgogIC8vcmVjdGFuZ2xlIHZlY3RvciBhbmQgYXNzb2NpYXRlZCB0aGluZ3MKICBWZWN0b3I8UmVjdGFuZ2xlPiByID0gbmV3IFZlY3RvcjxSZWN0YW5nbGU+KCk7CiAgUG9pbnQgc3RhcnQsIGN1ciwgZW5kOwoKICBwdWJsaWMgaW50IHJlc2l6ZShpbnQgbmV3c2l6ZSkKICB7CiAgICAvLyB4CiAgICBpZiAobG9jLngrbmV3c2l6ZSA+PSBib3VuZHgpCiAgICB7CiAgICAgIG5ld3NpemUgPSBib3VuZHggLSBsb2MueCAtIDE7CiAgICAgIHJldHVybiBuZXdzaXplOwogICAgfQoKICAgIC8vIHkKICAgIGlmIChsb2MueStuZXdzaXplID49IGJvdW5keSArIDEwMCkKICAgIHsKICAgICAgbmV3c2l6ZSA9IGJvdW5keSsxMDAgLSBsb2MueSAtIDE7CiAgICAgIHJldHVybiBuZXdzaXplOwogICAgfQogICAgc2l6ZSA9IG5ld3NpemU7CiAgICByZXR1cm4gbmV3c2l6ZTsKICB9CgogIHB1YmxpYyB2b2lkIG1vdmUoKQogIHsKICAgIC8vaWYgaXQgd2lsbCBoaXQgdGhlIHJpZ2h0IG9yIGxlZnQgYm91bmRhcnksIGZsaXAgdGhlIHggZGlyZWN0aW9uIGFuZCBzZXQgaXQKICAgIGlmIChsb2MueCtzaXplID49IGJvdW5keCB8fCBsb2MueCA8PSAwKQogICAgeyBkeCAqPSAtMTsgfQogICAgLy9pZiBpdCB3aWxsIGhpdCB0aGUgdG9wIG9yIGJvdHRvbSBib3VuZHJheSwgZmxpcCB0aGUgeSBkaXJlY3Rpb24gYW5kIHNldCBpdAogICAgaWYgKGxvYy55K3NpemUgPj0gYm91bmR5IHx8IGxvYy55IDw9IDApCiAgICB7IGR5ICo9IC0xOyB9CiAgICAKCiAgICBmb3IgKGludCBpID0gMDsgaSA8IHIuc2l6ZSgpOyBpKyspCiAgICB7CgogICAgICB0ZW1wID0gbmV3IFJlY3RhbmdsZShyLmVsZW1lbnRBdChpKSk7CiAgICAgIGludCByeCA9IHRlbXAueDsKICAgICAgaW50IHJ5ID0gdGVtcC55OwogICAgICBpbnQgcmggPSB0ZW1wLmhlaWdodDsKICAgICAgaW50IHJ3ID0gdGVtcC53aWR0aDsKICAgICAgLy9JZiB0aGUgYmFsbCBoaXRzIGVpdGhlciBzaWRlIG9mIHRoZSByZWN0YW5nbGUsIGNoYW5nZSB0aGUgeCBkaXJlY3Rpb24KICAgICAgaWYoKGxvYy54ID4gcnggJiYgbG9jLnggPiByeSAmJiBsb2MueCA8IChyeSArIHJoKSl8fChsb2MueCA8IChyeCArIHJ3KSAmJiBsb2MueCA+IHJ4ICYmIGxvYy54IDwocnkgKyByaCkpKQogICAgICAgIHtkeCAqPSAtMTt9CiAgICAgIC8vSWYgdGhlIGJhbGwgaGl0cyBlaXRoZXIgdGhlIHRvcCBvciBib3R0b20sIGNoYW5nZSB0aGUgeSBkaXJlY3Rpb24KICAgICAgaWYoKGxvYy55ID4gcnkgJiYgbG9jLnkgPiByeCAmJiBsb2MueSA8IChyeCArIHJ3KSl8fChsb2MueSA8IChyeSArIHJoKSAmJiBsb2MueSA+IHJ5ICYmIGxvYy55IDwocnggKyBydykpKQogICAgICAgIHtkeSAqPSAtMTt9CiAgICB9CiAgICAvL0luY3JlbWVudCBvciBkZWNyZW1lbnQgdGhlIGxvY2F0aW9uIG9mIHRoZSBiYWxsIGJhc2VkIG9uIHRoZSBYIGFuZCBZIGRpcmVjdGlvbnMuCiAgICBsb2MueCArPSBkeDsKICAgIGxvYy55ICs9IGR5OwogIH0KCiAgcHVibGljIHZvaWQgYWRkcmVjdCgpCiAgewogICAgLy9XaGF0IHdhcyB3cm9uZyBoZXJlIGlzIHRoYXQgZm9yIHRoZSBmaW5hbCBwYXJhbWV0ZXIsIEkgaGFkIE1hdGguYWJzKGVuZC55LXN0YXJ0LngpLiAKICAgIGlmIChlbmQueCA+IHN0YXJ0LnggJiYgZW5kLnkgPiBzdGFydC55KQogICAgci5hZGQobmV3IFJlY3RhbmdsZShzdGFydC54LHN0YXJ0LnksIE1hdGguYWJzKGVuZC54LXN0YXJ0LngpLE1hdGguYWJzKGVuZC55LXN0YXJ0LnkpKSk7CiAgICBpZiAoZW5kLnggPiBzdGFydC54ICYmIGVuZC55IDwgc3RhcnQueSkKICAgICAgci5hZGQobmV3IFJlY3RhbmdsZShzdGFydC54LGVuZC55LCBNYXRoLmFicyhlbmQueC1zdGFydC54KSxNYXRoLmFicyhlbmQueS1zdGFydC55KSkpOyAgCiAgICBpZiAoZW5kLnggPCBzdGFydC54ICYmIGVuZC55ID4gc3RhcnQueSkKICAgICAgci5hZGQobmV3IFJlY3RhbmdsZShlbmQueCwgc3RhcnQueSwgTWF0aC5hYnMoZW5kLngtc3RhcnQueCksTWF0aC5hYnMoZW5kLnktc3RhcnQueSkpKTsKICAgIGlmIChlbmQueCA8IHN0YXJ0LnggJiYgZW5kLnkgPCBzdGFydC55KQogICAgICByLmFkZChuZXcgUmVjdGFuZ2xlKGVuZC54LCBlbmQueSwgTWF0aC5hYnMoZW5kLngtc3RhcnQueCksTWF0aC5hYnMoZW5kLnktc3RhcnQueSkpKTsKICB9CgogIHB1YmxpYyB2b2lkIHVwZGF0ZShHcmFwaGljcyBnKQogIHsKICAgIC8vc3VwZXIudXBkYXRlKGcpOyAgICAgICAvL0dldHRpbmcgcmlkIG9mIHRoaXMgZml4ZWQgZG91YmxlIGJ1ZmZlcmluZwogICAgLy8gSSBsb29rZWQgYXQgUC1kYXdnJ3MgY29kZSBhbmQgaGUgZGlkbid0IGhhdmUgaXQuCiAgICBHcmFwaGljcyBidWZmZXI7CiAgICBpZiAob2Zmc2NyZWVuID09IG51bGwpCiAgICB7CiAgICAgIG9mZnNjcmVlbiA9IGNyZWF0ZUltYWdlKGdldFdpZHRoKCksIGdldEhlaWdodCgpKTsKICAgIH0KICAgIGJ1ZmZlciA9IG9mZnNjcmVlbi5nZXRHcmFwaGljcygpOwogICAgYnVmZmVyLnNldENvbG9yKGdldEJhY2tncm91bmQoKSk7CiAgICBidWZmZXIuZmlsbFJlY3QoMCwwLDY0MCwgNDEwKTsKICAgIG15cGFpbnQoYnVmZmVyKTsKICAgIGcuZHJhd0ltYWdlKG9mZnNjcmVlbiwgMCwgMCwgdGhpcyk7CiAgfQoKICBwdWJsaWMgdm9pZCBteXBhaW50KEdyYXBoaWNzIGcpCiAgewogICAgLy91cGRhdGUgbG9jCiAgICBtb3ZlKCk7CgogICAgLy9kcmF3CiAgICBnLnNldENvbG9yKENvbG9yLlJFRCk7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IHIuc2l6ZSgpOyBpKyspCiAgICB7CiAgICAgIFJlY3RhbmdsZSB0OwogICAgICB0ID0gbmV3IFJlY3RhbmdsZShyLmVsZW1lbnRBdChpKSk7CiAgICAgIGcuZmlsbFJlY3QodC54LHQueSx0LndpZHRoLHQuaGVpZ2h0KTsKICAgIH0KICAgIGcuc2V0Q29sb3IoQ29sb3IuQkxBQ0spOwogICAgZy5kcmF3T3ZhbChsb2MueCwgbG9jLnksIHNpemUsIHNpemUpOwogICAgZy5maWxsT3ZhbChsb2MueCwgbG9jLnksIHNpemUsIHNpemUpOwoKICAgIGlmIChmbGFnKQogICAgewogICAgICBpZiAoIXIuaXNFbXB0eSgpKQogICAgICB7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCByLnNpemUoKTsgaSsrKSAKICAgICAgICB7CiAgICAgICAgICBpZiAoY3VyLnggPiBzdGFydC54ICYmIGN1ci55ID4gc3RhcnQueSkKICAgICAgICAgIHsKICAgICAgICAgICAgZy5kcmF3UmVjdChzdGFydC54LCBzdGFydC55LCBNYXRoLmFicyhjdXIueCAtIHN0YXJ0LngpLCBNYXRoLmFicyhjdXIueSAtIHN0YXJ0LnkpKTsKICAgICAgICAgICAgZy5zZXRDb2xvcihDb2xvci5ncmF5KTsKICAgICAgICAgICAgZy5maWxsUmVjdChzdGFydC54LCBzdGFydC55LCBNYXRoLmFicyhjdXIueCAtIHN0YXJ0LngpLCBNYXRoLmFicyhjdXIueSAtIHN0YXJ0LnkpKTsKICAgICAgICAgIH0gIAogICAgICAgICAgaWYgKGN1ci54ID4gc3RhcnQueCAmJiBjdXIueSA8IHN0YXJ0LnkpCiAgICAgICAgICB7CiAgICAgICAgICAgIGcuZHJhd1JlY3Qoc3RhcnQueCwgY3VyLnksIE1hdGguYWJzKGN1ci54IC0gc3RhcnQueCksIE1hdGguYWJzKGN1ci55IC0gc3RhcnQueSkpOwogICAgICAgICAgICBnLnNldENvbG9yKENvbG9yLmdyYXkpOwogICAgICAgICAgICBnLmZpbGxSZWN0KHN0YXJ0LngsIGN1ci55LCBNYXRoLmFicyhjdXIueCAtIHN0YXJ0LngpLCBNYXRoLmFicyhjdXIueSAtIHN0YXJ0LnkpKTsgICAgICAgICAgICAgIAogICAgICAgICAgfQogICAgICAgICAgaWYgKGN1ci54IDwgc3RhcnQueCAmJiBjdXIueSA+IHN0YXJ0LnkpCiAgICAgICAgICB7CiAgICAgICAgICAgIGcuZHJhd1JlY3QoY3VyLngsIHN0YXJ0LnksIE1hdGguYWJzKGN1ci54IC0gc3RhcnQueCksIE1hdGguYWJzKGN1ci55IC0gc3RhcnQueSkpOwogICAgICAgICAgICBnLnNldENvbG9yKENvbG9yLmdyYXkpOwogICAgICAgICAgICBnLmZpbGxSZWN0KGN1ci54LCBzdGFydC55LCBNYXRoLmFicyhjdXIueCAtIHN0YXJ0LngpLCBNYXRoLmFicyhjdXIueSAtIHN0YXJ0LnkpKTsgCiAgICAgICAgICB9CiAgICAgICAgICBpZiAoY3VyLnggPCBzdGFydC54ICYmIGN1ci55IDwgc3RhcnQueSkKICAgICAgICAgIHsKICAgICAgICAgICAgZy5kcmF3UmVjdChjdXIueCwgY3VyLnksIE1hdGguYWJzKGN1ci54IC0gc3RhcnQueCksIE1hdGguYWJzKGN1ci55IC0gc3RhcnQueSkpOwogICAgICAgICAgICBnLnNldENvbG9yKENvbG9yLmdyYXkpOwogICAgICAgICAgICBnLmZpbGxSZWN0KGN1ci54LCBjdXIueSwgTWF0aC5hYnMoY3VyLnggLSBzdGFydC54KSwgTWF0aC5hYnMoY3VyLnkgLSBzdGFydC55KSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQp9