/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.nGqNBV1H45v/rev.6288
*
* authors:
* Glen Oakley
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
//CURRENTLY CONFIGURED FOR SOROBAN
public static final int HEAVENS = 1;
public static final int EARTHS = 4;
public static final int HEAVEN_VALUE = EARTHS+1;
public static final int EARTH_VALUE = 1;
public static final int ROWS = 3;
public static final int BEAD_SPACE = 2;
public static final int BEAD_HEIGHT = 16;
public static final int BEAD_WIDTH = 32;
public static final int BAR_THICKNESS = 8;
Bead[][] abacusArray;
int unitRow;
void setup() {
size(BAR_THICKNESS + ROWS*BEAD_WIDTH + (ROWS+1)*(BEAD_WIDTH/2) + BAR_THICKNESS,
BAR_THICKNESS + (EARTHS+BEAD_SPACE)*BEAD_HEIGHT + BAR_THICKNESS + (HEAVENS+BEAD_SPACE)*BEAD_HEIGHT + BAR_THICKNESS);
abacusArray = new Bead[HEAVENS+EARTHS][ROWS];
for (int x = 0; x < HEAVENS+EARTHS; x++) {
for (int y = 0; y < ROWS; y++) {
boolean isHeaven = (x < HEAVENS);
int posX = rowToPos(y);
int padding = (isHeaven ?
BAR_THICKNESS :
BAR_THICKNESS*2+(HEAVENS+BEAD_SPACE)*BEAD_HEIGHT);
int posYStart = padding+(((isHeaven ? x : x-HEAVENS)))*BEAD_HEIGHT;
int posYEnd =
padding+((((isHeaven ? x : x-HEAVENS)))+BEAD_SPACE)*BEAD_HEIGHT;
abacusArray[x][y] = new Bead(posX-BEAD_WIDTH/2, posYStart, posYEnd,
isHeaven);
}
}
unitRow = (int)(ROWS/2);
}
void draw() {
background(255);
fill(0);
stroke(0);
// draw the frame
rect(0, 0, BAR_THICKNESS, height);
rect(width-BAR_THICKNESS, 0, BAR_THICKNESS, height);
rect(0, 0, width, BAR_THICKNESS);
rect(0, height-BAR_THICKNESS, width, BAR_THICKNESS);
rect(0, BAR_THICKNESS + (HEAVENS+BEAD_SPACE)*BEAD_HEIGHT, width, BAR_THICKNESS);
// draw the rods
strokeWeight(BEAD_WIDTH/8);
for (int i = 0; i < ROWS; i++) {
int posX = rowToPos(i);
line(posX, 0, posX, height);
}
// draw the unit rod marker
stroke(255);
strokeWeight(BAR_THICKNESS/2);
int unitX = rowToPos(unitRow);
int unitY = BAR_THICKNESS*(3/2)+(HEAVENS+BEAD_SPACE)*BEAD_HEIGHT;
line(unitX, unitY, unitX, unitY);
// draw the beads
stroke(0);
ellipseMode(CORNER);
strokeWeight(1);
for (int x = 0; x < abacusArray.length; x++) {
for (int y = 0; y < abacusArray[x].length; y++) {
PVector p = abacusArray[x][y].getPos();
ellipse(p.x, p.y, BEAD_WIDTH, BEAD_HEIGHT);
}
}
}
public void mouseDragged() {
if (mouseButton == LEFT) {
// [try to] move (a) bead(s)
parseMovement();
}
}
public void mousePressed() {
if (mouseButton == RIGHT) {
// set the unit rod for the abacus
int rowNum = posToRow(mouseX);
if (rowNum >= 0)
unitRow = rowNum;
}
}
// will return a negative if the row is out of range
public int posToRow(int xPos) {
double rowWidth = (width-BAR_THICKNESS*2)/ROWS;
int rowNumber = (int)((xPos-BAR_THICKNESS)/rowWidth);
if (xPos <= BAR_THICKNESS || xPos >= width-BAR_THICKNESS)
rowNumber = -1;
return rowNumber;
}
public int rowToPos(int row) {
int xPos = (BEAD_WIDTH/4 + BAR_THICKNESS+(3*BEAD_WIDTH)/4+row*((3*BEAD_WIDTH)/2));
return xPos;
}
public long getNumber() {
long number = 0;
for (int y = 0; y < abacusArray[0].length; y++) {
localNumber = 0;
for (int a = 0; a < HEAVENS; a++) {
localNumber += (abacusArray[a][y].isReconed() ? 1 : 0)*HEAVEN_VALUE;
}
for (int b = HEAVENS; b < HEAVENS+EARTHS; b++) {
localNumber += (abacusArray[b][y].isReconed() ? 1 : 0)*EARTH_VALUE;
}
number += localNumber * pow(10, unitRod-y);
}
return number;
}
private void parseMovement() {
double lineSlope = (mouseY-pmouseY)/(mouseX-pmouseX);
int yInt = mouseY-lineSlope*mouseX;
if (pmouseY == mouseY) return;
if (pmouseX < mouseX) {
int startRow = posToRow(pmouseX);
int endRow = posToRow(mouseX);
for (int i = startRow; i < endRow; i++) {
int startX = rowToPos(i) -
(i==0 ? BAR_THICKNESS : rowToPos(i-1));
if (pmouseX > startX) startX = pmouseX;
int endX = -rowToPos(i) +
(i==(ROWS-1) ? width-BAR_THICKNESS : rowToPos(i+1));
if (mouseX < endX) endX = mouseX;
endX = (mouseX < endX ? mouseX : endX);
if (int(lineSlope*startX+yInt) > int(lineSlope*endX+yInt)) {
} else {
}
}
}
println("ASDF");
}
public class Bead {
// the x, upper, and lower positions do not change
private int xPos, upperPos, lowerPos, currentPos;
//whether or not the bead is in the reconed position
boolean reconed;
boolean heaven;
public Bead(int xPosition, int uPos, int lPos, boolean heaven) {
xPos = xPosition;
upperPos = uPos;
lowerPos = lPos;
currentPos = (heaven ? uPos : lPos);
reconed = false;
this.heaven = heaven;
}
public PVector getPos() { return new PVector(xPos, currentPos); }
public void setPos(int y) {
currentPos = y;
if (currentPos < lowerPos) currentPos = lowerPos;
else if (currentPos > upperPos) currentPos = upperPos;
if ((upperPos-currentPos) > ((upperPos-lowerPos)/2)) {
if (heaven) reconed = false;
else reconed = true;
}
else {
if (heaven) reconed = true;
else reconed = false;
}
}
public boolean isReconed() { return reconed; }
public boolean isHeaven() { return isHeaven; }
}