Revision 35
revised colonet style
Colonet.java | ||
---|---|---|
80 | 80 |
Thread drawThread; |
81 | 81 |
SelectionIndicator indicator; |
82 | 82 |
PacketMonitor packetMonitor; |
83 |
ColonetServerInterface csi; |
|
83 | 84 |
|
84 | 85 |
|
85 | 86 |
public void init () { |
... | ... | |
277 | 278 |
indicator.setRadius(RADIUS+3, 15); //a tad more than the bot radius |
278 | 279 |
packetMonitor = new PacketMonitor(); |
279 | 280 |
datalistener = new DataListener(); |
281 |
|
|
282 |
csi = new ColonetServerInterface(log); |
|
280 | 283 |
|
281 | 284 |
} |
282 | 285 |
|
283 |
public synchronized void paint (Graphics g) |
|
284 |
{ |
|
286 |
public synchronized void paint (Graphics g) { |
|
285 | 287 |
/* First, redraw the graphical components in the applet. |
286 | 288 |
This paint method overrides the built-in paint of the |
287 | 289 |
JApplet, and we don't want to deal with redrawing the |
... | ... | |
293 | 295 |
|
294 | 296 |
} |
295 | 297 |
|
296 |
public synchronized void update (Graphics g) |
|
297 |
{ |
|
298 |
public synchronized void update (Graphics g) { |
|
298 | 299 |
paint(g); |
299 | 300 |
} |
300 | 301 |
|
301 |
public void actionPerformed (ActionEvent e) |
|
302 |
{ |
|
302 |
public void actionPerformed (ActionEvent e) { |
|
303 | 303 |
Object source = e.getSource(); |
304 | 304 |
if (source == btnGraph) { |
305 | 305 |
btnGraph.setEnabled(false); |
... | ... | |
320 | 320 |
} |
321 | 321 |
} |
322 | 322 |
|
323 |
private void randomize () |
|
324 |
{ |
|
323 |
private void randomize () { |
|
325 | 324 |
Random r = new Random(); |
326 | 325 |
StringBuilder s = new StringBuilder(); |
327 | 326 |
|
328 | 327 |
int count = r.nextInt(8) + 1; |
329 |
for (int i = 0; i < count; i++) |
|
330 |
{ |
|
331 |
for (int j = 0; j < count; j++) |
|
332 |
{ |
|
328 |
for (int i = 0; i < count; i++) { |
|
329 |
for (int j = 0; j < count; j++) { |
|
333 | 330 |
if (r.nextBoolean()) |
334 | 331 |
s.append("" + (r.nextInt(16) + 1)); |
335 | 332 |
else |
... | ... | |
343 | 340 |
txtInput.setText(s.toString()); |
344 | 341 |
} |
345 | 342 |
|
346 |
private void doSocket () |
|
347 |
{ |
|
348 |
//make sure hostname and port are valid |
|
349 |
if (txtHost.getText().equals("") || txtPort.getText().equals("")) { |
|
350 |
err("Please enter a hostname and port."); |
|
351 |
return; |
|
352 |
} |
|
353 |
int port = 0; |
|
354 |
try { |
|
355 |
port = Integer.parseInt(txtPort.getText()); |
|
356 |
} catch (Exception e) { |
|
357 |
err("Invalid port"); |
|
358 |
return; |
|
359 |
} |
|
360 |
|
|
361 |
//make sure we aren't already connected. if so, disconnect first. |
|
362 |
if (socket != null && socket.isConnected()) { |
|
363 |
try { |
|
364 |
out.close(); |
|
365 |
socket.close(); |
|
366 |
} catch (IOException e) {} |
|
367 |
} |
|
368 |
|
|
369 |
try { |
|
370 |
socket = new Socket(txtHost.getText(), port); |
|
371 |
} catch (UnknownHostException e) { |
|
372 |
err("Unknown Host Exception"); |
|
373 |
return; |
|
374 |
} catch (IOException e) { |
|
375 |
err("IO Exception\n\n" + e); |
|
376 |
return; |
|
377 |
} catch (java.security.AccessControlException e) { |
|
378 |
err("Permission denied by java.security.AccessControlException." |
|
379 |
+"\n\nYou may only connect to the server from which this applet was loaded."); |
|
380 |
return; |
|
381 |
} |
|
382 |
if (socket == null || !socket.isConnected()) { |
|
383 |
err("Connection failed. Try connecting again."); |
|
384 |
return; |
|
385 |
} |
|
386 |
msg("Connected to " + txtHost.getText() + " on port " + port + "\n"); |
|
387 |
lblConnectionStatus.setText("Online"); |
|
388 |
try { |
|
389 |
out = new OutputStreamWriter(socket.getOutputStream()); |
|
390 |
} catch (IOException e) { |
|
391 |
warn("Could not get OutputStream from socket connection."); |
|
392 |
} |
|
393 |
|
|
343 |
private void doSocket () { |
|
344 |
csi.connect(txtHost.getText(), txtPort.getText()); |
|
394 | 345 |
} |
395 | 346 |
|
396 |
public void drawRobot (int id, int x, int y) |
|
397 |
{ |
|
347 |
public void drawRobot (int id, int x, int y) { |
|
398 | 348 |
//save the bot in memory, so we can tell if we click on it later |
399 | 349 |
botRect[id] = new Rectangle(x-RADIUS, y-RADIUS, 2*RADIUS, 2*RADIUS); |
400 | 350 |
|
... | ... | |
407 | 357 |
canvas.drawString("" + id, x-10, y+10); |
408 | 358 |
} |
409 | 359 |
|
410 |
public void drawConnection (int start, int end, int radius, Color color) |
|
411 |
{ |
|
360 |
public void drawConnection (int start, int end, int radius, Color color) { |
|
412 | 361 |
final int ARROW_LENGTH = 18; |
413 | 362 |
|
414 | 363 |
double angle = 2.0 * Math.PI / numBots; |
... | ... | |
444 | 393 |
int dx_half = (int)(ARROW_LENGTH/2 * Math.sin(theta)); |
445 | 394 |
int rx = (big_dx > 0) ? endx - dx_arrow : endx + dx_arrow; |
446 | 395 |
int ry = (big_dy > 0) ? endy + dy_arrow : endy - dy_arrow; |
447 |
//System.out.println("" + start + "->" + end + " : dx=" + big_dx + ",dy=" + big_dy + ",dy_arrow=" + dy_arrow + ",dx_arrow=" + dx_arrow + ",theta=" + theta + ",endx=" + endx + ",endy=" + endy + ",rx=" + rx + ",ry=" + ry); |
|
448 | 396 |
poly.addPoint(endx, endy); |
449 | 397 |
poly.addPoint(rx - dx_half, ry - dy_half); |
450 | 398 |
poly.addPoint(rx + dx_half, ry + dy_half); |
451 | 399 |
canvas.fillPolygon(poly); |
452 | 400 |
} |
453 | 401 |
|
454 |
public void run () |
|
455 |
{ |
|
456 |
while (true) |
|
457 |
{ |
|
402 |
public void run () { |
|
403 |
while (true) { |
|
458 | 404 |
step(); |
459 | 405 |
repaint(); |
460 |
try { Thread.sleep(90); } |
|
461 |
catch (InterruptedException e) { return; } |
|
406 |
try { |
|
407 |
Thread.sleep(90); |
|
408 |
} catch (InterruptedException e) { |
|
409 |
return; |
|
410 |
} |
|
462 | 411 |
} |
463 | 412 |
} |
464 | 413 |
|
465 |
public void step () |
|
466 |
{ |
|
414 |
public void step () { |
|
467 | 415 |
final int DIAMETER = image.getWidth() - 2*BUFFER; |
468 | 416 |
final int BIGRADIUS = DIAMETER / 2; |
469 | 417 |
final int TOKENRADIUS = 40; |
... | ... | |
478 | 426 |
numBots = rows.length; |
479 | 427 |
String [][] entries = new String[numBots][numBots]; |
480 | 428 |
valid = true; |
481 |
for (int i = 0; i < numBots; i++) |
|
482 |
{ |
|
429 |
for (int i = 0; i < numBots; i++) { |
|
483 | 430 |
entries[i] = rows[i].split(" "); |
484 | 431 |
if (entries[i].length != rows.length) valid = false; |
485 | 432 |
} |
486 | 433 |
|
487 |
if (valid) |
|
488 |
{ |
|
434 |
if (valid) { |
|
489 | 435 |
this.showStatus("Matrix OK"); |
490 | 436 |
|
491 | 437 |
// draw robots and find which one is seleced |
... | ... | |
494 | 440 |
botRect = new Rectangle[numBots]; |
495 | 441 |
int x, y; |
496 | 442 |
if (selectedBot >= numBots) selectedBot = 0; |
497 |
for (int i = 0; i < numBots; i++) |
|
498 |
{ |
|
443 |
for (int i = 0; i < numBots; i++) { |
|
499 | 444 |
x = cx - (int)(BIGRADIUS * Math.cos(i * angle)); |
500 | 445 |
y = cy - (int)(BIGRADIUS * Math.sin(i * angle)); |
501 | 446 |
drawRobot(i, x, y); |
... | ... | |
513 | 458 |
// create an inner circle along which the connections are made. |
514 | 459 |
// let the diameter of this circle be 2*RADIUS less than the outerDiameter. |
515 | 460 |
// see what connections exist |
516 |
for (int row = 0; row < numBots; row++) |
|
517 |
{ |
|
518 |
for(int col = 0; col < numBots; col++) |
|
519 |
{ |
|
520 |
if (! entries[row][col].equals("-") && entries[col][row].equals("-") && row != col) //one-way |
|
521 |
{ |
|
522 |
//drawConnection(row, col, BIGRADIUS-RADIUS, Color.GRAY); |
|
461 |
for (int row = 0; row < numBots; row++) { |
|
462 |
for(int col = 0; col < numBots; col++) { |
|
463 |
if (!entries[row][col].equals("-") && entries[col][row].equals("-") && row != col) { |
|
464 |
//TODO: Make a standard gray |
|
523 | 465 |
drawConnection(row, col, BIGRADIUS-RADIUS, new Color(200,200,200)); |
524 | 466 |
} |
525 |
else if (! entries[row][col].equals("-") && ! entries[col][row].equals("-") && row != col) //two-way |
|
526 |
{ |
|
467 |
else if (!entries[row][col].equals("-") && ! entries[col][row].equals("-") && row != col) { |
|
527 | 468 |
drawConnection(row, col, BIGRADIUS-RADIUS, Color.BLACK); |
528 | 469 |
} |
529 | 470 |
} |
... | ... | |
533 | 474 |
indicator.draw(); |
534 | 475 |
txtInfo.setText("Packet statistics: ???"); |
535 | 476 |
|
536 |
} |
|
537 |
else // if matrix is not valid |
|
538 |
{ |
|
477 |
} else {// if matrix is not valid |
|
539 | 478 |
this.showStatus("Error: Invalid matrix"); |
540 | 479 |
} |
541 | 480 |
|
... | ... | |
546 | 485 |
* token passing or deleted if the information can be retrieved |
547 | 486 |
* directly from the Colonet server instead. |
548 | 487 |
*/ |
549 |
public void moveToken () |
|
550 |
{ |
|
551 |
try { tokenLoc = (tokenLoc+1)%numBots; } |
|
552 |
catch (ArithmeticException e) { } // in case numRobots is zero |
|
488 |
public void moveToken () { |
|
489 |
try { |
|
490 |
tokenLoc = (tokenLoc+1)%numBots; |
|
491 |
} catch (ArithmeticException e) { // in case numRobots is zero |
|
492 |
} |
|
553 | 493 |
|
554 | 494 |
packetMonitor.addTokenPass(); |
555 | 495 |
} |
... | ... | |
561 | 501 |
public void mouseEntered(MouseEvent e) {} |
562 | 502 |
public void mouseReleased(MouseEvent e) {} |
563 | 503 |
public void mouseClicked(MouseEvent e) {} |
564 |
public void mousePressed(MouseEvent e) |
|
565 |
{ |
|
504 |
public void mousePressed(MouseEvent e) { |
|
566 | 505 |
try { |
567 |
for (int i = 0; i < numBots; i++) |
|
568 |
{ |
|
506 |
for (int i = 0; i < numBots; i++) { |
|
569 | 507 |
if (botRect[i].contains(e.getPoint())) |
570 | 508 |
selectedBot = i; |
571 | 509 |
} |
... | ... | |
575 | 513 |
|
576 | 514 |
} |
577 | 515 |
|
578 |
private void msg (String text) {JOptionPane.showMessageDialog(null, text, "Colonet", JOptionPane.INFORMATION_MESSAGE);} |
|
579 |
private void warn (String text) {JOptionPane.showMessageDialog(null, text, "Colonet", JOptionPane.WARNING_MESSAGE);} |
|
580 |
private void err (String text) {JOptionPane.showMessageDialog(null, text, "Colonet", JOptionPane.ERROR_MESSAGE);} |
|
581 |
|
|
582 |
|
|
583 | 516 |
/* |
584 | 517 |
* SelectionIndicator thread. |
585 | 518 |
* Graphical representation of the selection marker |
... | ... | |
589 | 522 |
* externally and should only run if all calculations in step() have |
590 | 523 |
* been completed. |
591 | 524 |
*/ |
592 |
private class SelectionIndicator extends Thread |
|
593 |
{ |
|
525 |
private class SelectionIndicator extends Thread { |
|
594 | 526 |
|
595 | 527 |
final int INDICATOR_DELAY = 100; |
596 | 528 |
final double DTHETA = 0.3; //larger values make the marker rotate faster |
... | ... | |
614 | 546 |
|
615 | 547 |
int steps; |
616 | 548 |
|
617 |
public SelectionIndicator (Graphics2D g) |
|
618 |
{ |
|
549 |
public SelectionIndicator (Graphics2D g) { |
|
619 | 550 |
super("SelectionIndicator"); |
620 | 551 |
this.g = g; |
621 | 552 |
running = false; |
... | ... | |
632 | 563 |
px4 = 0; py4 = 0; |
633 | 564 |
} |
634 | 565 |
|
635 |
public synchronized void setCenter (int sx, int sy) |
|
636 |
{ |
|
566 |
public synchronized void setCenter (int sx, int sy) { |
|
637 | 567 |
if (sx == this.sx && sy == this.sy) return; |
638 | 568 |
this.sx = sx; |
639 | 569 |
this.sy = sy; |
640 | 570 |
steps = 0; |
641 | 571 |
} |
642 | 572 |
|
643 |
public synchronized void setRadius (int r, int dr) |
|
644 |
{ |
|
573 |
public synchronized void setRadius (int r, int dr) { |
|
645 | 574 |
this.r = r; |
646 | 575 |
this.dr = dr; |
647 | 576 |
steps = 0; |
648 | 577 |
} |
649 | 578 |
|
650 |
public void run () |
|
651 |
{ |
|
579 |
public void run () { |
|
652 | 580 |
running = true; |
653 |
while (running) |
|
654 |
{ |
|
581 |
while (running) { |
|
655 | 582 |
step(); |
656 |
try { Thread.sleep(INDICATOR_DELAY); } |
|
657 |
catch (InterruptedException e) { running = false; return; } |
|
583 |
try { |
|
584 |
Thread.sleep(INDICATOR_DELAY); |
|
585 |
} catch (InterruptedException e) { |
|
586 |
running = false; |
|
587 |
return; |
|
588 |
} |
|
658 | 589 |
} |
659 | 590 |
} |
660 | 591 |
|
661 |
private synchronized void step () |
|
662 |
{ |
|
592 |
private synchronized void step () { |
|
663 | 593 |
Polygon poly1_new = new Polygon(); |
664 | 594 |
Polygon poly2_new = new Polygon(); |
665 | 595 |
Polygon poly3_new = new Polygon(); |
... | ... | |
687 | 617 |
int dx_poly = (int)(dr/2 * Math.sin(theta)); |
688 | 618 |
|
689 | 619 |
//determine critical points |
620 |
//kansas city shuffle! |
|
690 | 621 |
px1 = sx + dx_inner; |
691 | 622 |
py1 = sy - dy_inner; |
692 | 623 |
rx1 = sx + dx_outer; |
... | ... | |
727 | 658 |
if (steps < 300) steps++; |
728 | 659 |
} |
729 | 660 |
|
730 |
public synchronized void draw () |
|
731 |
{ |
|
661 |
public synchronized void draw () { |
|
732 | 662 |
if (!running) return; |
733 | 663 |
g.setColor(Color.GRAY); |
734 | 664 |
//draw polygons |
... | ... | |
744 | 674 |
* Simulator thread. |
745 | 675 |
* |
746 | 676 |
*/ |
747 |
private class Simulator extends Thread |
|
748 |
{ |
|
677 |
private class Simulator extends Thread { |
|
749 | 678 |
final int SIMULATOR_DELAY = 300; |
750 |
|
|
751 | 679 |
boolean running; |
752 | 680 |
|
753 |
public Simulator () |
|
754 |
{ |
|
681 |
public Simulator () { |
|
755 | 682 |
super("Simulator"); |
756 | 683 |
running = false; |
757 | 684 |
} |
758 | 685 |
|
759 |
public void run () |
|
760 |
{ |
|
686 |
public void run () { |
|
761 | 687 |
running = true; |
762 |
while (running) |
|
763 |
{ |
|
688 |
while (running) { |
|
764 | 689 |
step(); |
765 |
try { Thread.sleep(SIMULATOR_DELAY); } |
|
766 |
catch (InterruptedException e) { running = false; return; } |
|
690 |
try { |
|
691 |
Thread.sleep(SIMULATOR_DELAY); |
|
692 |
} catch (InterruptedException e) { |
|
693 |
running = false; |
|
694 |
return; |
|
695 |
} |
|
767 | 696 |
} |
768 | 697 |
} |
769 | 698 |
|
770 |
private void step () |
|
771 |
{ |
|
699 |
private void step () { |
|
772 | 700 |
// simulate passing the token |
773 | 701 |
moveToken(); |
774 |
|
|
775 | 702 |
} |
776 | 703 |
|
777 | 704 |
} |
... | ... | |
782 | 709 |
* Currently, this counts the rate of token passes but will eventually |
783 | 710 |
* be modified to keep more important statistics. |
784 | 711 |
*/ |
785 |
private class PacketMonitor extends Thread |
|
786 |
{ |
|
712 |
private class PacketMonitor extends Thread { |
|
787 | 713 |
final int PACKETMONITOR_DELAY = 1000; |
788 | 714 |
|
789 | 715 |
boolean running; |
790 | 716 |
int tokenPasses; |
791 | 717 |
|
792 |
public PacketMonitor () |
|
793 |
{ |
|
718 |
public PacketMonitor () { |
|
794 | 719 |
super("PacketMonitor"); |
795 | 720 |
running = false; |
796 | 721 |
tokenPasses = 0; |
797 | 722 |
} |
798 | 723 |
|
799 |
public void run () |
|
800 |
{ |
|
724 |
public void run () { |
|
801 | 725 |
running = true; |
802 |
while (running) |
|
803 |
{ |
|
726 |
while (running) { |
|
804 | 727 |
displayTokenPasses(); |
805 |
try { Thread.sleep(PACKETMONITOR_DELAY); } |
|
806 |
catch (InterruptedException e) { running = false; return; } |
|
728 |
try { |
|
729 |
Thread.sleep(PACKETMONITOR_DELAY); |
|
730 |
} catch (InterruptedException e) { |
|
731 |
running = false; |
|
732 |
return; |
|
733 |
} |
|
807 | 734 |
} |
808 | 735 |
} |
809 | 736 |
|
810 |
public synchronized void addTokenPass () |
|
811 |
{ |
|
737 |
public synchronized void addTokenPass () { |
|
812 | 738 |
tokenPasses++; |
813 | 739 |
} |
814 | 740 |
|
815 |
public synchronized void displayTokenPasses () |
|
816 |
{ |
|
741 |
public synchronized void displayTokenPasses () { |
|
817 | 742 |
lblTokenPasses.setText("" + tokenPasses); |
818 | 743 |
tokenPasses = 0; |
819 | 744 |
} |
... | ... | |
824 | 749 |
* DataListener thread. |
825 | 750 |
* |
826 | 751 |
*/ |
827 |
class DataListener extends Thread |
|
828 |
{ |
|
752 |
class DataListener extends Thread { |
|
829 | 753 |
final int DATALISTENER_DELAY = 1000; |
830 | 754 |
BufferedReader reader; |
831 | 755 |
|
832 |
public DataListener () |
|
833 |
{ |
|
756 |
public DataListener () { |
|
834 | 757 |
super("Colonet DataListener"); |
835 | 758 |
} |
836 | 759 |
|
837 |
public void run () |
|
838 |
{ |
|
760 |
public void run () { |
|
839 | 761 |
String line; |
840 |
try { |
|
841 |
reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); |
|
842 |
} catch (IOException e) { |
|
843 |
warn("Could not open input stream from socket.\nTry relooding the applet."); |
|
844 |
} |
|
845 |
while (true) |
|
846 |
{ |
|
762 |
reader = csi.getBufferedReader(); |
|
763 |
while (true) { |
|
847 | 764 |
try { |
848 |
if (reader.ready()) |
|
849 |
{ |
|
765 |
if (csi.isReady()) { |
|
850 | 766 |
line = reader.readLine(); |
851 |
if (line != null) |
|
852 |
{
|
|
853 |
msg("Incoming data: [" + line + "]");
|
|
767 |
if (line != null) {
|
|
768 |
csi.msg("Incoming data: [" + line + "]");
|
|
769 |
//TODO: parse incoming data here
|
|
854 | 770 |
} |
855 | 771 |
} |
856 | 772 |
Thread.sleep(DATALISTENER_DELAY); |
857 | 773 |
} catch (InterruptedException e) { |
858 | 774 |
return; |
859 | 775 |
} catch (IOException e) { |
860 |
warn("IOException while reading incoming data."); |
|
776 |
csi.warn("IOException while reading incoming data.");
|
|
861 | 777 |
} |
862 | 778 |
} |
863 | 779 |
} |
864 | 780 |
|
865 | 781 |
} |
866 | 782 |
|
867 |
|
|
868 |
|
|
869 |
|
|
870 | 783 |
} |
Also available in: Unified diff