class Beta implements Task {
Maru maru;
Group<Teki> tekis;
Group<Flag> flags;
Beta
(Maru maru,
Field field, Group
<Teki
> tekis, Group
<Flag
> flags
) { this.maru = maru;
this.field = field;
this.tekis = tekis;
this.flags = flags;
}
void draw() {
}
void field_with_tekis() {
for (Teki teki : tekis) {
if (teki.x() < field.x()) {
teki.x(field.w());
} else if (teki.x() > field.w()) {
teki.x(field.y());
}
if (teki.y() < field.y()) {
teki.y(field.h());
} else if (teki.y() > field.h()) {
teki.y(field.y());
}
}
}
void maru_with_tekis() {
if(maru.isMuteki())return;
for (Teki teki : tekis) {
if (maru.r() + teki.r() > dist(maru.x(), maru.y(), teki.x(), teki.y())) {
field.alert();
teki.damaged();
maru.damaged();
}
}
}
boolean isHit(Sprite a, Sprite b){
return abs(a.cx()-b.cx()) < a.w2() + b.w2() && abs(a.cy()-b.cy()) < a.h2() + b.h2();
}
void maru_with_flags() {
for (Flag flag : flags) {
if(flag.isTouched()) continue;
if (isHit(maru, flag)) {
flag.touch();
}
}
}
void update() {
field_with_tekis();
maru_with_tekis();
maru_with_flags();
}
boolean isEnd() {
return false;
}
void mousePressed() {
}
}
enum State {
Normal, Damaged,
}
class Field extends Sprite
{ color normal;
color damaged;
State state;
int count;
final int max = 10;
Field(float x,
float y,
float w,
float h
) { this.position = new PVector(x, y);
this.w = w;
this.h = h;
this.d = w;
this.r = w/2;
this.normal = color(0, 0, 100);
this.damaged = color(60, 100, 100);
this.state = State.Normal;
}
void draw() {
switch(state) {
case Normal:
noStroke();
fill(normal);
rect(x(), y(), w(), h());
break;
case Damaged:
noStroke();
fill(damaged);
rect(x(), y(), w(), h());
break;
}
}
void alert() {
state = State.Damaged;
count = 0;
}
void update() {
switch(state) {
case Normal:
break;
case Damaged:
count++;
if (count > max) {
state = State.Normal;
}
break;
}
}
boolean isEnd() {
return false;
}
void mousePressed() {
}
}
class Flag extends Sprite {
boolean touched;
//color before;
color after;
PVector ps[];//points for triangle
Flag(float x, float y) {
position = new PVector(x, y);
velocity = new PVector(0, 0);
touched = false;
w = 30;
h = 30;
d = w;
r = d/2;
after = color(120, 40, 100);
ps = new PVector[3];
ps[0] = new PVector(x(), y());
ps[1] = new PVector(x()+w()*0.5, y()+h2()/2);
ps[2] = new PVector(x(), y()+h2());
}
void drawRect(){
rect(x(), y(), w(), h());
}
void drawFlag(){
triangle(ps[0].x, ps[0].y, ps[1].x, ps[1].y, ps[2].x, ps[2].y);
line(x(), y()+h2(), x(), yh());
}
void draw() {
if (touched) {
fill(after);
stroke(0, 0, 0);
//drawRect();//check, ok
drawFlag();
} else {
noFill();
stroke(0, 0, 0);
//drawRect();//check, ok
drawFlag();
}
}
void update() {
}
boolean isEnd() {
return false;
}
void touch() {
touched = true;
}
void mousePressed() {
}
boolean isTouched() {
return touched;
}
}
import java.lang.Iterable;
import java.util.Iterator;
class Group<T extends Task> implements Task, Iterable<T> {
ArrayList<T> self;
this.self = new ArrayList<T>();
}
void draw() {
for (T t : self) {
t.draw();
}
}
void update() {
for (int i=self.size()-1; i>=0; i--) {
self.get(i).update();
if (self.get(i).isEnd()) {
self.remove(i);
}
}
}
boolean isEnd() {
return false;
}
void add(T t) {
self.add(t);
}
boolean isEmpty() {
return self.isEmpty();
}
@Override
public Iterator<T> iterator() {
return self.iterator();
}
int size() {
return self.size();
}
T get(int i) {
return self.get(i);
}
void mousePressed() {
for (T t : self) {
t.mousePressed();
}
}
}
enum MaruState {
Normal, Muteki,
}
class Maru extends Sprite {
float e = 0.095;
int life;
int lifeMax;
float ts = 36;
float tx;
float ty;
float margin = 10;
MaruState state;
int count;
final int max = 80;
Maru(float x, float y) {
position = new PVector(x, y);
velocity = new PVector(0, 0);
v = 2;
d = 20;
r = d/2;
w = d;
h = d;
lifeMax = 12;
life = lifeMax;
state = MaruState.Normal;
ty = height - ts - margin;
}
void drawLife(){
float tw = textWidth(s);
tx = width - tw - margin;
textSize(ts);
text(s, tx, ty);
}
void draw() {
switch(state) {
case Normal:
drawLife();
noFill();
stroke(0);
ellipse(x(), y(), d, d);
break;
case Muteki:
drawLife();
if (count%10 < 5) {
noFill();
stroke(0);
ellipse(x(), y(), d, d);
} else {
//
}
break;
}
}
void move_old() {
if (x() < mouseX) {
position.x += v;
} else {
position.x -= v;
}
if (y() < mouseY) {
position.y += v;
} else {
position.y -= v;
}
}
void move_easing() {
position.x += (mouseX-x())*e;
position.y += (mouseY-y())*e;
}
void update() {
switch(state) {
case Normal:
move_easing();
break;
case Muteki:
move_easing();
count++;
if (count > max) {
state = MaruState.Normal;
}
break;
}
}
void damaged() {
life--;
state = MaruState.Muteki;
count = 0;
}
boolean isMuteki(){
return state == MaruState.Muteki;
}
boolean isEnd() {
return life <= 0;
}
void mousePressed() {
}
}
interface Scene extends Task {
}
interface Changer {
void change(Scene next);
}
class SceneManager implements Task, Changer {
Scene current;
Scene next;
SceneManager() {
current = new Title(this);
}
void draw() {
current.draw();
}
void update() {
if (next != null) {
current = next;
next = null;
}
current.update();
}
boolean isEnd() {
return false;
}
void change(Scene next) {
this.next = next;
}
void mousePressed() {
current.mousePressed();
}
}
class Title implements Scene {
Changer changer;
//String s = "avoiding game";
float ts = 42;
float x, y;
Title(Changer changer) {
this.changer = changer;
textSize(ts);
float w = textWidth(s);
this.x = width/2 - w/2;
this.y = height/2 - ts;
}
void draw() {
background(0, 0, 100);
fill(140, 100, 100);
textSize(ts);
text(s, x, y);
}
void update() {
}
boolean isEnd() {
return false;
}
void mousePressed() {
changer.change(new Stage(changer));
}
}
class Failure implements Scene {
Changer changer;
float ts = 42;
float x, y;
Failure(Changer changer) {
this.changer = changer;
textSize(ts);
float w = textWidth(s);
this.x = width/2 - w/2;
this.y = height/2 - ts;
}
void draw() {
background(0, 0, 100);
fill(140, 100, 100);
textSize(ts);
text(s, x, y);
}
void update() {
}
boolean isEnd() {
return false;
}
void mousePressed() {
changer.change(new Title(changer));
}
}
class Clear implements Scene {
Changer changer;
float ts = 42;
float x, y;
Clear(Changer changer) {
this.changer = changer;
textSize(ts);
float w = textWidth(s);
this.x = width/2 - w/2;
this.y = height/2 - ts;
}
void draw() {
background(0, 0, 100);
fill(140, 100, 100);
textSize(ts);
text(s, x, y);
}
void update() {
}
boolean isEnd() {
return false;
}
void mousePressed() {
changer.change(new Title(changer));
}
}
interface Task {
void draw();
void update();
boolean isEnd();
void mousePressed();
}
abstract class Sprite implements Task {
PVector position;
PVector velocity;
float v;
float w, h;
float d, r;
float x() {
return position.x;
}
float y() {
return position.y;
}
void x(float value) {
position.x = value;
}
void y(float value) {
position.y = value;
}
float w() {
return w;
}
float h() {
return h;
}
float d() {
return d;
}
float r() {
return r;
}
float w2() {
return w()/2;
}
float h2() {
return h()/2;
}
float cx(){
return x()+w2();
}
float cy(){
return y()+h2();
}
float xw() {
return x()+w();
}
float yh() {
return y()+h();
}
}
class Stage implements Scene {
Changer changer;
Maru maru;
Group<Teki> tekis;
final int tekiMax = 100;
Group<Flag> flags;
final int flagX = 8;
final int flagY = 5;
final int flagsAll = flagX * flagY;
Beta beta;
Group<Task> tasks;
Stage(Changer changer) {
this.changer = changer;
field
= new Field(0,
0, width, height
);
final float d = 20;
maru = new Maru(width/2-d/2, height/2-d/2);
tekis = new Group<Teki>();
init_tekis();
flags = new Group<Flag>();
init_flags();
beta = new Beta(maru, field, tekis, flags);
tasks = new Group<Task>();
tasks.add(field);
tasks.add(flags);
tasks.add(tekis);
tasks.add(maru);
tasks.add(beta);
}
void init_tekis() {
for (int i=0; i<tekiMax; i++) {
final float x = random(width);
final float y = random(height);
final float v = 1;
final float theta = random(TWO_PI);
tekis.add(new Teki(x, y, v, theta));
}
}
void init_flags() {
final float dx = width/(flagX+2);
final float dy = height/(flagY+2);
for (int j=0; j<flagY; j++) {
final float y = (j+1) * dy;
for (int i=0; i<flagX; i++) {
final float x = (i+1) * dx;
flags.add(new Flag(x, y));
}
}
}
void draw() {
tasks.draw();
}
void update() {
tasks.update();
if(maru.isEnd()){
changer.change(new Failure(changer));
}else if(flags_all_touched()){
changer.change(new Clear(changer));
}
}
boolean flags_all_touched(){
for(Flag flag: flags){
if(!flag.isTouched())return false;
}
return true;
}
boolean isEnd() {
//return tasks.isEnd();
return false;
//return maru.isEnd();
}
void mousePressed() {
tasks.mousePressed();
}
}
class Teki extends Sprite {
int life;
Teki(float x, float y, float v, float theta) {
position = new PVector(x, y);
velocity = new PVector(v, 0);
velocity.rotate(theta);
v = 1;
d = 20;
r = d/2;
w = d;
h = d;
life = 1;
}
void draw() {
noFill();
stroke(0, 100, 100);
ellipse(x(), y(), d, d);
}
void update() {
position.add(velocity);
}
void damaged() {
life--;
}
boolean isEnd() {
return life <= 0;
}
void mousePressed() {
}
}
SceneManager sceneManager;
void setup() {
size(800, 500);
colorMode(HSB, 360, 100, 100);
sceneManager = new SceneManager();
}
void draw() {
sceneManager.draw();
sceneManager.update();
}
void mousePressed() {
sceneManager.mousePressed();
}
Y2xhc3MgQmV0YSBpbXBsZW1lbnRzIFRhc2sgewogIE1hcnUgbWFydTsKICBGaWVsZCBmaWVsZDsKICBHcm91cDxUZWtpPiB0ZWtpczsKICBHcm91cDxGbGFnPiBmbGFnczsKCiAgQmV0YShNYXJ1IG1hcnUsIEZpZWxkIGZpZWxkLCBHcm91cDxUZWtpPiB0ZWtpcywgR3JvdXA8RmxhZz4gZmxhZ3MpIHsKICAgIHRoaXMubWFydSA9IG1hcnU7CiAgICB0aGlzLmZpZWxkID0gZmllbGQ7CiAgICB0aGlzLnRla2lzID0gdGVraXM7CiAgICB0aGlzLmZsYWdzID0gZmxhZ3M7CiAgfQogIHZvaWQgZHJhdygpIHsKICB9CiAgdm9pZCBmaWVsZF93aXRoX3Rla2lzKCkgewogICAgZm9yIChUZWtpIHRla2kgOiB0ZWtpcykgewogICAgICBpZiAodGVraS54KCkgPCBmaWVsZC54KCkpIHsKICAgICAgICB0ZWtpLngoZmllbGQudygpKTsKICAgICAgfSBlbHNlIGlmICh0ZWtpLngoKSA+IGZpZWxkLncoKSkgewogICAgICAgIHRla2kueChmaWVsZC55KCkpOwogICAgICB9CiAgICAgIGlmICh0ZWtpLnkoKSA8IGZpZWxkLnkoKSkgewogICAgICAgIHRla2kueShmaWVsZC5oKCkpOwogICAgICB9IGVsc2UgaWYgKHRla2kueSgpID4gZmllbGQuaCgpKSB7CiAgICAgICAgdGVraS55KGZpZWxkLnkoKSk7CiAgICAgIH0KICAgIH0KICB9CiAgdm9pZCBtYXJ1X3dpdGhfdGVraXMoKSB7CiAgICBpZihtYXJ1LmlzTXV0ZWtpKCkpcmV0dXJuOwogICAgCiAgICBmb3IgKFRla2kgdGVraSA6IHRla2lzKSB7CiAgICAgIGlmIChtYXJ1LnIoKSArIHRla2kucigpID4gZGlzdChtYXJ1LngoKSwgbWFydS55KCksIHRla2kueCgpLCB0ZWtpLnkoKSkpIHsKICAgICAgICBmaWVsZC5hbGVydCgpOwogICAgICAgIHRla2kuZGFtYWdlZCgpOwogICAgICAgIG1hcnUuZGFtYWdlZCgpOwogICAgICB9CiAgICB9CiAgfQogIGJvb2xlYW4gaXNIaXQoU3ByaXRlIGEsIFNwcml0ZSBiKXsKICAgIHJldHVybiBhYnMoYS5jeCgpLWIuY3goKSkgPCBhLncyKCkgKyBiLncyKCkgJiYgYWJzKGEuY3koKS1iLmN5KCkpIDwgYS5oMigpICsgYi5oMigpOwogIH0KICB2b2lkIG1hcnVfd2l0aF9mbGFncygpIHsKICAgIGZvciAoRmxhZyBmbGFnIDogZmxhZ3MpIHsKICAgICAgaWYoZmxhZy5pc1RvdWNoZWQoKSkgY29udGludWU7CiAgICAgIAogICAgICBpZiAoaXNIaXQobWFydSwgZmxhZykpIHsKICAgICAgICBmbGFnLnRvdWNoKCk7CiAgICAgIH0KICAgIH0KICB9CiAgdm9pZCB1cGRhdGUoKSB7CiAgICBmaWVsZF93aXRoX3Rla2lzKCk7CiAgICBtYXJ1X3dpdGhfdGVraXMoKTsKICAgIG1hcnVfd2l0aF9mbGFncygpOwogIH0KICBib29sZWFuIGlzRW5kKCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICB2b2lkIG1vdXNlUHJlc3NlZCgpIHsKICB9Cn0KZW51bSBTdGF0ZSB7CiAgTm9ybWFsLCBEYW1hZ2VkLAp9CmNsYXNzIEZpZWxkIGV4dGVuZHMgU3ByaXRlIHsKICBjb2xvciBub3JtYWw7CiAgY29sb3IgZGFtYWdlZDsKICBTdGF0ZSBzdGF0ZTsKCiAgaW50IGNvdW50OwogIGZpbmFsIGludCBtYXggPSAxMDsKCiAgRmllbGQoZmxvYXQgeCwgZmxvYXQgeSwgZmxvYXQgdywgZmxvYXQgaCkgewogICAgdGhpcy5wb3NpdGlvbiA9IG5ldyBQVmVjdG9yKHgsIHkpOwogICAgdGhpcy53ID0gdzsKICAgIHRoaXMuaCA9IGg7CiAgICB0aGlzLmQgPSB3OwogICAgdGhpcy5yID0gdy8yOwogICAgdGhpcy5ub3JtYWwgPSBjb2xvcigwLCAwLCAxMDApOwogICAgdGhpcy5kYW1hZ2VkID0gY29sb3IoNjAsIDEwMCwgMTAwKTsKICAgIHRoaXMuc3RhdGUgPSBTdGF0ZS5Ob3JtYWw7CiAgfQogIHZvaWQgZHJhdygpIHsKICAgIHN3aXRjaChzdGF0ZSkgewogICAgY2FzZSBOb3JtYWw6CiAgICAgIG5vU3Ryb2tlKCk7CiAgICAgIGZpbGwobm9ybWFsKTsKICAgICAgcmVjdCh4KCksIHkoKSwgdygpLCBoKCkpOwogICAgICBicmVhazsKCiAgICBjYXNlIERhbWFnZWQ6CiAgICAgIG5vU3Ryb2tlKCk7CiAgICAgIGZpbGwoZGFtYWdlZCk7CiAgICAgIHJlY3QoeCgpLCB5KCksIHcoKSwgaCgpKTsKICAgICAgYnJlYWs7CiAgICB9CiAgfQogIHZvaWQgYWxlcnQoKSB7CiAgICBzdGF0ZSA9IFN0YXRlLkRhbWFnZWQ7CiAgICBjb3VudCA9IDA7CiAgfQogIHZvaWQgdXBkYXRlKCkgewogICAgc3dpdGNoKHN0YXRlKSB7CiAgICBjYXNlIE5vcm1hbDoKICAgICAgYnJlYWs7CgogICAgY2FzZSBEYW1hZ2VkOgogICAgICBjb3VudCsrOwogICAgICBpZiAoY291bnQgPiBtYXgpIHsKICAgICAgICBzdGF0ZSA9IFN0YXRlLk5vcm1hbDsKICAgICAgfQogICAgICBicmVhazsKICAgIH0KICB9CiAgYm9vbGVhbiBpc0VuZCgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgdm9pZCBtb3VzZVByZXNzZWQoKSB7CiAgfQp9CmNsYXNzIEZsYWcgZXh0ZW5kcyBTcHJpdGUgewogIGJvb2xlYW4gdG91Y2hlZDsKICAvL2NvbG9yIGJlZm9yZTsKICBjb2xvciBhZnRlcjsKICBQVmVjdG9yIHBzW107Ly9wb2ludHMgZm9yIHRyaWFuZ2xlCgogIEZsYWcoZmxvYXQgeCwgZmxvYXQgeSkgewogICAgcG9zaXRpb24gPSBuZXcgUFZlY3Rvcih4LCB5KTsKICAgIHZlbG9jaXR5ID0gbmV3IFBWZWN0b3IoMCwgMCk7CiAgICB0b3VjaGVkID0gZmFsc2U7CiAgICB3ID0gMzA7CiAgICBoID0gMzA7CiAgICBkID0gdzsKICAgIHIgPSBkLzI7CiAgICBhZnRlciA9IGNvbG9yKDEyMCwgNDAsIDEwMCk7CiAgICAKICAgIHBzID0gbmV3IFBWZWN0b3JbM107CiAgICBwc1swXSA9IG5ldyBQVmVjdG9yKHgoKSwgeSgpKTsKICAgIHBzWzFdID0gbmV3IFBWZWN0b3IoeCgpK3coKSowLjUsIHkoKStoMigpLzIpOwogICAgcHNbMl0gPSBuZXcgUFZlY3Rvcih4KCksIHkoKStoMigpKTsKICB9CiAgdm9pZCBkcmF3UmVjdCgpewogICAgcmVjdCh4KCksIHkoKSwgdygpLCBoKCkpOwogIH0KICB2b2lkIGRyYXdGbGFnKCl7CiAgICB0cmlhbmdsZShwc1swXS54LCBwc1swXS55LCBwc1sxXS54LCBwc1sxXS55LCBwc1syXS54LCBwc1syXS55KTsKICAgICAgbGluZSh4KCksIHkoKStoMigpLCB4KCksIHloKCkpOwogIH0KICB2b2lkIGRyYXcoKSB7CiAgICBpZiAodG91Y2hlZCkgewogICAgICBmaWxsKGFmdGVyKTsKICAgICAgc3Ryb2tlKDAsIDAsIDApOwogICAgICAvL2RyYXdSZWN0KCk7Ly9jaGVjaywgb2sKICAgICAgZHJhd0ZsYWcoKTsKICAgIH0gZWxzZSB7CiAgICAgIG5vRmlsbCgpOwogICAgICBzdHJva2UoMCwgMCwgMCk7CiAgICAgIC8vZHJhd1JlY3QoKTsvL2NoZWNrLCBvawogICAgICBkcmF3RmxhZygpOwogICAgfQogIH0KICB2b2lkIHVwZGF0ZSgpIHsKICB9CiAgYm9vbGVhbiBpc0VuZCgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgdm9pZCB0b3VjaCgpIHsKICAgIHRvdWNoZWQgPSB0cnVlOwogIH0KICB2b2lkIG1vdXNlUHJlc3NlZCgpIHsKICB9CiAgYm9vbGVhbiBpc1RvdWNoZWQoKSB7CiAgICByZXR1cm4gdG91Y2hlZDsKICB9Cn0KaW1wb3J0IGphdmEubGFuZy5JdGVyYWJsZTsKaW1wb3J0IGphdmEudXRpbC5JdGVyYXRvcjsKY2xhc3MgR3JvdXA8VCBleHRlbmRzIFRhc2s+IGltcGxlbWVudHMgVGFzaywgSXRlcmFibGU8VD4gewogIEFycmF5TGlzdDxUPiBzZWxmOwoKICBHcm91cCgpIHsKICAgIHRoaXMuc2VsZiA9IG5ldyBBcnJheUxpc3Q8VD4oKTsKICB9CiAgdm9pZCBkcmF3KCkgewogICAgZm9yIChUIHQgOiBzZWxmKSB7CiAgICAgIHQuZHJhdygpOwogICAgfQogIH0KICB2b2lkIHVwZGF0ZSgpIHsKICAgIGZvciAoaW50IGk9c2VsZi5zaXplKCktMTsgaT49MDsgaS0tKSB7CiAgICAgIHNlbGYuZ2V0KGkpLnVwZGF0ZSgpOwoKICAgICAgaWYgKHNlbGYuZ2V0KGkpLmlzRW5kKCkpIHsKICAgICAgICBzZWxmLnJlbW92ZShpKTsKICAgICAgfQogICAgfQogIH0KICBib29sZWFuIGlzRW5kKCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICB2b2lkIGFkZChUIHQpIHsKICAgIHNlbGYuYWRkKHQpOwogIH0KICBib29sZWFuIGlzRW1wdHkoKSB7CiAgICByZXR1cm4gc2VsZi5pc0VtcHR5KCk7CiAgfQogIEBPdmVycmlkZQogICAgcHVibGljIEl0ZXJhdG9yPFQ+IGl0ZXJhdG9yKCkgewogICAgcmV0dXJuIHNlbGYuaXRlcmF0b3IoKTsKICB9CiAgaW50IHNpemUoKSB7CiAgICByZXR1cm4gc2VsZi5zaXplKCk7CiAgfQogIFQgZ2V0KGludCBpKSB7CiAgICByZXR1cm4gc2VsZi5nZXQoaSk7CiAgfQogIHZvaWQgbW91c2VQcmVzc2VkKCkgewogICAgZm9yIChUIHQgOiBzZWxmKSB7CiAgICAgIHQubW91c2VQcmVzc2VkKCk7CiAgICB9CiAgfQp9CmVudW0gTWFydVN0YXRlIHsKICBOb3JtYWwsIE11dGVraSwKfQpjbGFzcyBNYXJ1IGV4dGVuZHMgU3ByaXRlIHsKICBmbG9hdCBlID0gMC4wOTU7CiAgCiAgaW50IGxpZmU7CiAgaW50IGxpZmVNYXg7CiAgCiAgZmxvYXQgdHMgPSAzNjsKICBmbG9hdCB0eDsKICBmbG9hdCB0eTsKICBmbG9hdCBtYXJnaW4gPSAxMDsKCiAgTWFydVN0YXRlIHN0YXRlOwogIGludCBjb3VudDsKICBmaW5hbCBpbnQgbWF4ID0gODA7CgogIE1hcnUoZmxvYXQgeCwgZmxvYXQgeSkgewogICAgcG9zaXRpb24gPSBuZXcgUFZlY3Rvcih4LCB5KTsKICAgIHZlbG9jaXR5ID0gbmV3IFBWZWN0b3IoMCwgMCk7CiAgICB2ID0gMjsKICAgIGQgPSAyMDsKICAgIHIgPSBkLzI7CiAgICB3ID0gZDsKICAgIGggPSBkOwogICAgbGlmZU1heCA9IDEyOwogICAgbGlmZSA9IGxpZmVNYXg7CiAgICBzdGF0ZSA9IE1hcnVTdGF0ZS5Ob3JtYWw7CiAgICB0eSA9IGhlaWdodCAtIHRzIC0gbWFyZ2luOwogIH0KICB2b2lkIGRyYXdMaWZlKCl7CiAgICBTdHJpbmcgcyA9IGxpZmUrIi8iK2xpZmVNYXg7CiAgICBmbG9hdCB0dyA9IHRleHRXaWR0aChzKTsKICAgIHR4ID0gd2lkdGggLSB0dyAtIG1hcmdpbjsKICAgIHRleHRTaXplKHRzKTsKICAgIHRleHQocywgdHgsIHR5KTsKICB9CiAgdm9pZCBkcmF3KCkgewogICAgc3dpdGNoKHN0YXRlKSB7CiAgICBjYXNlIE5vcm1hbDoKICAgICAgZHJhd0xpZmUoKTsKICAgICAgCiAgICAgIG5vRmlsbCgpOwogICAgICBzdHJva2UoMCk7CiAgICAgIGVsbGlwc2UoeCgpLCB5KCksIGQsIGQpOwogICAgICBicmVhazsKCiAgICBjYXNlIE11dGVraToKICAgICAgZHJhd0xpZmUoKTsKICAgICAgCiAgICAgIGlmIChjb3VudCUxMCA8IDUpIHsKICAgICAgICBub0ZpbGwoKTsKICAgICAgICBzdHJva2UoMCk7CiAgICAgICAgZWxsaXBzZSh4KCksIHkoKSwgZCwgZCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8KICAgICAgfQogICAgICBicmVhazsKICAgIH0KICB9CiAgdm9pZCBtb3ZlX29sZCgpIHsKICAgIGlmICh4KCkgPCBtb3VzZVgpIHsKICAgICAgcG9zaXRpb24ueCArPSB2OwogICAgfSBlbHNlIHsKICAgICAgcG9zaXRpb24ueCAtPSB2OwogICAgfQogICAgaWYgKHkoKSA8IG1vdXNlWSkgewogICAgICBwb3NpdGlvbi55ICs9IHY7CiAgICB9IGVsc2UgewogICAgICBwb3NpdGlvbi55IC09IHY7CiAgICB9CiAgfQogIHZvaWQgbW92ZV9lYXNpbmcoKSB7CiAgICBwb3NpdGlvbi54ICs9IChtb3VzZVgteCgpKSplOwogICAgcG9zaXRpb24ueSArPSAobW91c2VZLXkoKSkqZTsKICB9CiAgdm9pZCB1cGRhdGUoKSB7CiAgICBzd2l0Y2goc3RhdGUpIHsKICAgIGNhc2UgTm9ybWFsOgogICAgICBtb3ZlX2Vhc2luZygpOwogICAgICBicmVhazsKCiAgICBjYXNlIE11dGVraToKICAgICAgbW92ZV9lYXNpbmcoKTsKICAgICAgY291bnQrKzsKICAgICAgaWYgKGNvdW50ID4gbWF4KSB7CiAgICAgICAgc3RhdGUgPSBNYXJ1U3RhdGUuTm9ybWFsOwogICAgICB9CiAgICAgIGJyZWFrOwogICAgfQogIH0KICB2b2lkIGRhbWFnZWQoKSB7CiAgICBsaWZlLS07CiAgICBzdGF0ZSA9IE1hcnVTdGF0ZS5NdXRla2k7CiAgICBjb3VudCA9IDA7CiAgfQogIGJvb2xlYW4gaXNNdXRla2koKXsKICAgIHJldHVybiBzdGF0ZSA9PSBNYXJ1U3RhdGUuTXV0ZWtpOwogIH0KICBib29sZWFuIGlzRW5kKCkgewogICAgcmV0dXJuIGxpZmUgPD0gMDsKICB9CiAgdm9pZCBtb3VzZVByZXNzZWQoKSB7CiAgfQp9CmludGVyZmFjZSBTY2VuZSBleHRlbmRzIFRhc2sgewp9CgppbnRlcmZhY2UgQ2hhbmdlciB7CiAgdm9pZCBjaGFuZ2UoU2NlbmUgbmV4dCk7Cn0KCmNsYXNzIFNjZW5lTWFuYWdlciBpbXBsZW1lbnRzIFRhc2ssIENoYW5nZXIgewogIFNjZW5lIGN1cnJlbnQ7CiAgU2NlbmUgbmV4dDsKCiAgU2NlbmVNYW5hZ2VyKCkgewogICAgY3VycmVudCA9IG5ldyBUaXRsZSh0aGlzKTsKICB9CiAgdm9pZCBkcmF3KCkgewogICAgY3VycmVudC5kcmF3KCk7CiAgfQogIHZvaWQgdXBkYXRlKCkgewogICAgaWYgKG5leHQgIT0gbnVsbCkgewogICAgICBjdXJyZW50ID0gbmV4dDsKICAgICAgbmV4dCA9IG51bGw7CiAgICB9CiAgICBjdXJyZW50LnVwZGF0ZSgpOwogIH0KICBib29sZWFuIGlzRW5kKCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICB2b2lkIGNoYW5nZShTY2VuZSBuZXh0KSB7CiAgICB0aGlzLm5leHQgPSBuZXh0OwogIH0KICB2b2lkIG1vdXNlUHJlc3NlZCgpIHsKICAgIGN1cnJlbnQubW91c2VQcmVzc2VkKCk7CiAgfQp9CgpjbGFzcyBUaXRsZSBpbXBsZW1lbnRzIFNjZW5lIHsKICBDaGFuZ2VyIGNoYW5nZXI7CgogIC8vU3RyaW5nIHMgPSAiYXZvaWRpbmcgZ2FtZSI7CiAgU3RyaW5nIHMgPSAiZmxhZyBlYXRlciI7CiAgZmxvYXQgdHMgPSA0MjsKICBmbG9hdCB4LCB5OwoKICBUaXRsZShDaGFuZ2VyIGNoYW5nZXIpIHsKICAgIHRoaXMuY2hhbmdlciA9IGNoYW5nZXI7CgogICAgdGV4dFNpemUodHMpOwogICAgZmxvYXQgdyA9IHRleHRXaWR0aChzKTsKICAgIHRoaXMueCA9IHdpZHRoLzIgLSB3LzI7CiAgICB0aGlzLnkgPSBoZWlnaHQvMiAtIHRzOwogIH0KICB2b2lkIGRyYXcoKSB7CiAgICBiYWNrZ3JvdW5kKDAsIDAsIDEwMCk7CiAgICBmaWxsKDE0MCwgMTAwLCAxMDApOwogICAgdGV4dFNpemUodHMpOwogICAgdGV4dChzLCB4LCB5KTsKICB9CiAgdm9pZCB1cGRhdGUoKSB7CiAgfQogIGJvb2xlYW4gaXNFbmQoKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIHZvaWQgbW91c2VQcmVzc2VkKCkgewogICAgY2hhbmdlci5jaGFuZ2UobmV3IFN0YWdlKGNoYW5nZXIpKTsKICB9Cn0KCmNsYXNzIEZhaWx1cmUgaW1wbGVtZW50cyBTY2VuZSB7CiAgQ2hhbmdlciBjaGFuZ2VyOwoKICBTdHJpbmcgcyA9ICJmYWlsdXJlIjsKICBmbG9hdCB0cyA9IDQyOwogIGZsb2F0IHgsIHk7CgogIEZhaWx1cmUoQ2hhbmdlciBjaGFuZ2VyKSB7CiAgICB0aGlzLmNoYW5nZXIgPSBjaGFuZ2VyOwoKICAgIHRleHRTaXplKHRzKTsKICAgIGZsb2F0IHcgPSB0ZXh0V2lkdGgocyk7CiAgICB0aGlzLnggPSB3aWR0aC8yIC0gdy8yOwogICAgdGhpcy55ID0gaGVpZ2h0LzIgLSB0czsKICB9CiAgdm9pZCBkcmF3KCkgewogICAgYmFja2dyb3VuZCgwLCAwLCAxMDApOwogICAgZmlsbCgxNDAsIDEwMCwgMTAwKTsKICAgIHRleHRTaXplKHRzKTsKICAgIHRleHQocywgeCwgeSk7CiAgfQogIHZvaWQgdXBkYXRlKCkgewogIH0KICBib29sZWFuIGlzRW5kKCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICB2b2lkIG1vdXNlUHJlc3NlZCgpIHsKICAgIGNoYW5nZXIuY2hhbmdlKG5ldyBUaXRsZShjaGFuZ2VyKSk7CiAgfQp9CgpjbGFzcyBDbGVhciBpbXBsZW1lbnRzIFNjZW5lIHsKICBDaGFuZ2VyIGNoYW5nZXI7CgogIFN0cmluZyBzID0gImNsZWFyIjsKICBmbG9hdCB0cyA9IDQyOwogIGZsb2F0IHgsIHk7CgogIENsZWFyKENoYW5nZXIgY2hhbmdlcikgewogICAgdGhpcy5jaGFuZ2VyID0gY2hhbmdlcjsKCiAgICB0ZXh0U2l6ZSh0cyk7CiAgICBmbG9hdCB3ID0gdGV4dFdpZHRoKHMpOwogICAgdGhpcy54ID0gd2lkdGgvMiAtIHcvMjsKICAgIHRoaXMueSA9IGhlaWdodC8yIC0gdHM7CiAgfQogIHZvaWQgZHJhdygpIHsKICAgIGJhY2tncm91bmQoMCwgMCwgMTAwKTsKICAgIGZpbGwoMTQwLCAxMDAsIDEwMCk7CiAgICB0ZXh0U2l6ZSh0cyk7CiAgICB0ZXh0KHMsIHgsIHkpOwogIH0KICB2b2lkIHVwZGF0ZSgpIHsKICB9CiAgYm9vbGVhbiBpc0VuZCgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgdm9pZCBtb3VzZVByZXNzZWQoKSB7CiAgICBjaGFuZ2VyLmNoYW5nZShuZXcgVGl0bGUoY2hhbmdlcikpOwogIH0KfQppbnRlcmZhY2UgVGFzayB7CiAgdm9pZCBkcmF3KCk7CiAgdm9pZCB1cGRhdGUoKTsKICBib29sZWFuIGlzRW5kKCk7CiAgdm9pZCBtb3VzZVByZXNzZWQoKTsKfQoKYWJzdHJhY3QgY2xhc3MgU3ByaXRlIGltcGxlbWVudHMgVGFzayB7CiAgUFZlY3RvciBwb3NpdGlvbjsKICBQVmVjdG9yIHZlbG9jaXR5OwogIGZsb2F0IHY7CiAgZmxvYXQgdywgaDsKICBmbG9hdCBkLCByOwoKICBmbG9hdCB4KCkgewogICAgcmV0dXJuIHBvc2l0aW9uLng7CiAgfQogIGZsb2F0IHkoKSB7CiAgICByZXR1cm4gcG9zaXRpb24ueTsKICB9CiAgdm9pZCB4KGZsb2F0IHZhbHVlKSB7CiAgICBwb3NpdGlvbi54ID0gdmFsdWU7CiAgfQogIHZvaWQgeShmbG9hdCB2YWx1ZSkgewogICAgcG9zaXRpb24ueSA9IHZhbHVlOwogIH0KICBmbG9hdCB3KCkgewogICAgcmV0dXJuIHc7CiAgfQogIGZsb2F0IGgoKSB7CiAgICByZXR1cm4gaDsKICB9CiAgZmxvYXQgZCgpIHsKICAgIHJldHVybiBkOwogIH0KICBmbG9hdCByKCkgewogICAgcmV0dXJuIHI7CiAgfQogIGZsb2F0IHcyKCkgewogICAgcmV0dXJuIHcoKS8yOwogIH0KICBmbG9hdCBoMigpIHsKICAgIHJldHVybiBoKCkvMjsKICB9CiAgZmxvYXQgY3goKXsKICAgIHJldHVybiB4KCkrdzIoKTsKICB9CiAgZmxvYXQgY3koKXsKICAgIHJldHVybiB5KCkraDIoKTsKICB9CiAgZmxvYXQgeHcoKSB7CiAgICByZXR1cm4geCgpK3coKTsKICB9CiAgZmxvYXQgeWgoKSB7CiAgICByZXR1cm4geSgpK2goKTsKICB9Cn0KY2xhc3MgU3RhZ2UgaW1wbGVtZW50cyBTY2VuZSB7CiAgQ2hhbmdlciBjaGFuZ2VyOwoKICBNYXJ1IG1hcnU7CiAgRmllbGQgZmllbGQ7CgogIEdyb3VwPFRla2k+IHRla2lzOwogIGZpbmFsIGludCB0ZWtpTWF4ID0gMTAwOwoKICBHcm91cDxGbGFnPiBmbGFnczsKICBmaW5hbCBpbnQgZmxhZ1ggPSA4OwogIGZpbmFsIGludCBmbGFnWSA9IDU7CiAgZmluYWwgaW50IGZsYWdzQWxsID0gZmxhZ1ggKiBmbGFnWTsKCiAgQmV0YSBiZXRhOwogIEdyb3VwPFRhc2s+IHRhc2tzOwoKICBTdGFnZShDaGFuZ2VyIGNoYW5nZXIpIHsKICAgIHRoaXMuY2hhbmdlciA9IGNoYW5nZXI7CgogICAgZmllbGQgPSBuZXcgRmllbGQoMCwgMCwgd2lkdGgsIGhlaWdodCk7CgogICAgZmluYWwgZmxvYXQgZCA9IDIwOwogICAgbWFydSA9IG5ldyBNYXJ1KHdpZHRoLzItZC8yLCBoZWlnaHQvMi1kLzIpOwoKICAgIHRla2lzID0gbmV3IEdyb3VwPFRla2k+KCk7CiAgICBpbml0X3Rla2lzKCk7CgogICAgZmxhZ3MgPSBuZXcgR3JvdXA8RmxhZz4oKTsKICAgIGluaXRfZmxhZ3MoKTsKCiAgICBiZXRhID0gbmV3IEJldGEobWFydSwgZmllbGQsIHRla2lzLCBmbGFncyk7CgogICAgdGFza3MgPSBuZXcgR3JvdXA8VGFzaz4oKTsKICAgIHRhc2tzLmFkZChmaWVsZCk7CiAgICB0YXNrcy5hZGQoZmxhZ3MpOwogICAgdGFza3MuYWRkKHRla2lzKTsKICAgIHRhc2tzLmFkZChtYXJ1KTsKICAgIHRhc2tzLmFkZChiZXRhKTsKICB9CiAgdm9pZCBpbml0X3Rla2lzKCkgewogICAgZm9yIChpbnQgaT0wOyBpPHRla2lNYXg7IGkrKykgewogICAgICBmaW5hbCBmbG9hdCB4ID0gcmFuZG9tKHdpZHRoKTsKICAgICAgZmluYWwgZmxvYXQgeSA9IHJhbmRvbShoZWlnaHQpOwogICAgICBmaW5hbCBmbG9hdCB2ID0gMTsKICAgICAgZmluYWwgZmxvYXQgdGhldGEgPSByYW5kb20oVFdPX1BJKTsKICAgICAgdGVraXMuYWRkKG5ldyBUZWtpKHgsIHksIHYsIHRoZXRhKSk7CiAgICB9CiAgfQogIHZvaWQgaW5pdF9mbGFncygpIHsKICAgIGZpbmFsIGZsb2F0IGR4ID0gd2lkdGgvKGZsYWdYKzIpOwogICAgZmluYWwgZmxvYXQgZHkgPSBoZWlnaHQvKGZsYWdZKzIpOwogICAgZm9yIChpbnQgaj0wOyBqPGZsYWdZOyBqKyspIHsKICAgICAgZmluYWwgZmxvYXQgeSA9IChqKzEpICogZHk7CiAgICAgIGZvciAoaW50IGk9MDsgaTxmbGFnWDsgaSsrKSB7CiAgICAgICAgZmluYWwgZmxvYXQgeCA9IChpKzEpICogZHg7CiAgICAgICAgZmxhZ3MuYWRkKG5ldyBGbGFnKHgsIHkpKTsKICAgICAgfQogICAgfQogIH0KICB2b2lkIGRyYXcoKSB7CiAgICB0YXNrcy5kcmF3KCk7CiAgfQogIHZvaWQgdXBkYXRlKCkgewogICAgdGFza3MudXBkYXRlKCk7CiAgICAKICAgIGlmKG1hcnUuaXNFbmQoKSl7CiAgICAgIGNoYW5nZXIuY2hhbmdlKG5ldyBGYWlsdXJlKGNoYW5nZXIpKTsKICAgIH1lbHNlIGlmKGZsYWdzX2FsbF90b3VjaGVkKCkpewogICAgICBjaGFuZ2VyLmNoYW5nZShuZXcgQ2xlYXIoY2hhbmdlcikpOwogICAgfQogIH0KICBib29sZWFuIGZsYWdzX2FsbF90b3VjaGVkKCl7CiAgICBmb3IoRmxhZyBmbGFnOiBmbGFncyl7CiAgICAgIGlmKCFmbGFnLmlzVG91Y2hlZCgpKXJldHVybiBmYWxzZTsKICAgIH0KICAgIHJldHVybiB0cnVlOwogIH0KICBib29sZWFuIGlzRW5kKCkgewogICAgLy9yZXR1cm4gdGFza3MuaXNFbmQoKTsKICAgIHJldHVybiBmYWxzZTsKICAgIC8vcmV0dXJuIG1hcnUuaXNFbmQoKTsKICB9CiAgdm9pZCBtb3VzZVByZXNzZWQoKSB7CiAgICB0YXNrcy5tb3VzZVByZXNzZWQoKTsKICB9Cn0KY2xhc3MgVGVraSBleHRlbmRzIFNwcml0ZSB7CiAgaW50IGxpZmU7CgogIFRla2koZmxvYXQgeCwgZmxvYXQgeSwgZmxvYXQgdiwgZmxvYXQgdGhldGEpIHsKICAgIHBvc2l0aW9uID0gbmV3IFBWZWN0b3IoeCwgeSk7CiAgICB2ZWxvY2l0eSA9IG5ldyBQVmVjdG9yKHYsIDApOwogICAgdmVsb2NpdHkucm90YXRlKHRoZXRhKTsKICAgIHYgPSAxOwogICAgZCA9IDIwOwogICAgciA9IGQvMjsKICAgIHcgPSBkOwogICAgaCA9IGQ7CiAgICBsaWZlID0gMTsKICB9CiAgdm9pZCBkcmF3KCkgewogICAgbm9GaWxsKCk7CiAgICBzdHJva2UoMCwgMTAwLCAxMDApOwogICAgZWxsaXBzZSh4KCksIHkoKSwgZCwgZCk7CiAgfQogIHZvaWQgdXBkYXRlKCkgewogICAgcG9zaXRpb24uYWRkKHZlbG9jaXR5KTsKICB9CiAgdm9pZCBkYW1hZ2VkKCkgewogICAgbGlmZS0tOwogIH0KICBib29sZWFuIGlzRW5kKCkgewogICAgcmV0dXJuIGxpZmUgPD0gMDsKICB9CiAgdm9pZCBtb3VzZVByZXNzZWQoKSB7CiAgfQp9CgoKClNjZW5lTWFuYWdlciBzY2VuZU1hbmFnZXI7Cgp2b2lkIHNldHVwKCkgewogIHNpemUoODAwLCA1MDApOwogIGNvbG9yTW9kZShIU0IsIDM2MCwgMTAwLCAxMDApOwogIHNjZW5lTWFuYWdlciA9IG5ldyBTY2VuZU1hbmFnZXIoKTsKfQp2b2lkIGRyYXcoKSB7CiAgc2NlbmVNYW5hZ2VyLmRyYXcoKTsKICBzY2VuZU1hbmFnZXIudXBkYXRlKCk7Cn0Kdm9pZCBtb3VzZVByZXNzZWQoKSB7CiAgc2NlbmVNYW5hZ2VyLm1vdXNlUHJlc3NlZCgpOwp9Cg==