home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / in4wjcxu / src / como / commlet / scheduler / scheduler.java next >
Encoding:
Java Source  |  1996-08-14  |  12.0 KB  |  557 lines

  1. package como.commlet.scheduler;
  2.  
  3. import java.awt.*;
  4. import java.util.*;
  5. import java.io.*;
  6.  
  7. import como.sys.*;
  8. import como.util.*;
  9. import como.awt.*;
  10. import como.commlet.*;
  11. import como.commlet.*;
  12. import como.commlet.chat.*;
  13. import como.commlet.userlist.*;
  14.  
  15. public class Scheduler extends MetaCommlet
  16. {
  17.     MenuItem miclear;
  18.     MenuItem misuggest;
  19.     MenuItem miallok;
  20.     MenuItem miallno;
  21.     Board board = null;
  22.     TextField statusfield;
  23.     static final int MSG_NEW_SCHEDULE = 13045;
  24.     static final int MSG_NEW_SCHEDULE_PART = 13046;
  25.     static final int MSG_NEW_SCHEDULE_ROW = 13047;
  26.     static final int MSG_NEW_SCHEDULE_COL = 13048;
  27.     UserSchedule myschedule;
  28.     Hashtable schedules;
  29.  
  30.     public Scheduler() {
  31.         return;
  32.     }
  33.  
  34.     public String getCommletName()
  35.     {
  36.         return "Scheduler Commlet, V1.0, (c) Jan Kautz & Ulrich Gall";
  37.     }
  38.  
  39.     public String getCommletInfo()
  40.     {
  41.         return
  42.         "(c) 1996 Ulrich Gall & Jan Kautz\n"+
  43.         "\n";
  44.     }
  45.  
  46.     public void init()
  47.     {
  48.         super.init();
  49.     
  50.         Chat c = new Chat();
  51.         addCommlet(c,"Chat");
  52.  
  53.         UserList ul = new UserList();
  54.         addCommlet(ul,"Users");
  55.     
  56.         Menu men= new Menu("Scheduler");
  57.  
  58.         
  59.         miclear = new MenuItem("Clear");
  60.         miallok = new MenuItem("Set all: OK");
  61.         miallno = new MenuItem("Set all: No");
  62.         misuggest = new MenuItem("Suggest date (see Chat)");
  63.  
  64.         men.add(miclear);
  65.         men.add(miallok);
  66.         men.add(miallno);
  67.         men.add(misuggest);
  68.         getMenuBar().add(men);
  69.     
  70.         statusfield = new TextField();    
  71.         statusfield.setEditable( false );
  72.  
  73.         board = new Board( UserSchedule.WEEK_DAYS, UserSchedule.MIN_HOUR, UserSchedule.MAX_HOUR );
  74.  
  75.         add("Center",board);
  76.         add("South",statusfield);
  77.         pack();
  78.  
  79.         schedules = new Hashtable();
  80.     }
  81.  
  82.     public void addUser(int id)
  83.     {
  84.         status(com.getUserName(id) + " has joined.");
  85.  
  86.         UserSchedule s = new UserSchedule();
  87.  
  88.         if( id == com.getMyID() ) {
  89.             myschedule = s;
  90.         }
  91.         else {
  92.             com.sendTo( new Msg( MSG_NEW_SCHEDULE, id, myschedule ) );
  93.         }
  94.  
  95.         schedules.put( new Integer(id), s );
  96.     }
  97.  
  98.     public void userLeft(int id)
  99.     {
  100.         schedules.remove(new Integer(id));
  101.         status(com.getUserName(id) + " has left.");
  102.  
  103.         recalculateAll();
  104.     }
  105.  
  106.     public void stop()
  107.     {
  108.         super.stop();
  109.     }
  110.  
  111.     void status(String s)
  112.     {
  113.         statusfield.setText(s);
  114.     }
  115.  
  116.     public boolean handleMsg(Msg msg)
  117.     {
  118.         if( msg.type == Msg.NEW_USER_INFO ) {
  119.             User olduser = (User)msg.arg;
  120.             status( "User "+olduser.getName()+" is now known as "+com.getUserName(msg.from) );
  121.         }
  122.  
  123.         if( msg.type == MSG_NEW_SCHEDULE ) {
  124.             if( msg.from == com.getMyID() ) return true;        // This can't happen...
  125.  
  126.             if( msg.arg == null )
  127.             {
  128.                 Debug.msg( 30, "Scheduler().handleMsg(): NEW_SCHEDULE: no schedule sent!" );
  129.                 return true;
  130.             }
  131.  
  132.             schedules.put(new Integer(msg.from), (UserSchedule)msg.arg );
  133.             recalculateAll();
  134.  
  135.             return true;
  136.         }
  137.  
  138.         if( msg.type == MSG_NEW_SCHEDULE_ROW || msg.type == MSG_NEW_SCHEDULE_COL ) {
  139.             int array[];
  140.  
  141.             array = (int[])msg.arg;
  142.  
  143.             UserSchedule s = (UserSchedule)schedules.get( new Integer(msg.from) );
  144.  
  145.             if( s != null )
  146.             {
  147.                 if( msg.type == MSG_NEW_SCHEDULE_COL )
  148.                 {
  149.                     s.setCol( array[0], (byte)array[1] );
  150.                     recalculateCol( array[0] );
  151.                 }
  152.                 else
  153.                 {
  154.                     s.setRow( array[0], (byte)array[1] );
  155.                     recalculateRow( array[0] );
  156.                 }
  157.             }
  158.             
  159.             return true;
  160.         }
  161.         if( msg.type == MSG_NEW_SCHEDULE_PART ) {
  162.             int array[];
  163.  
  164.             array = (int[])msg.arg;
  165.  
  166.             UserSchedule s = (UserSchedule)schedules.get( new Integer(msg.from) );
  167.  
  168.             if( s != null )
  169.             {
  170.                 s.set( array[0], array[1], (byte)array[2] );
  171.                 recalculateSumAndMe( array[0], array[1] );
  172.             }
  173.             
  174.             return true;
  175.         }
  176.  
  177.         return super.handleMsg(msg);
  178.     }
  179.  
  180.     int scaleToRange( double how ) {
  181.         int maxf = myschedule.getMaxFitness();
  182.         double scale = 100.0/(double)maxf;
  183.  
  184.         int scaled = (int)(scale*how);
  185.  
  186.         if( scaled < -100 ) scaled = -100;
  187.         if( scaled >  100 ) scaled =  100;
  188.  
  189.         return scaled;
  190.     }
  191.  
  192.     String makeSuggestion() {
  193.         StringBuffer suggestion = new StringBuffer( "The best dates are: " );
  194.         boolean first = true;
  195.         int max = -1000;
  196.         int test;
  197.         int x, y;
  198.  
  199.         for( x = 1; x <= UserSchedule.WEEK_DAYS; x++ ) {
  200.             for( y = 1; y <= UserSchedule.NR_HOURS; y++ ) {
  201.                 test = board.getSum( x, y );
  202.                 if( test > max ) {
  203.                     max = test;
  204.                 }
  205.             }
  206.         }
  207.  
  208.         for( x = 1; x <= UserSchedule.WEEK_DAYS; x++ ) {
  209.             for( y = 1; y <= UserSchedule.NR_HOURS; y++ ) {
  210.                 test = board.getSum( x, y );
  211.                 if( test == max ) {
  212.                     if( first )
  213.                     {
  214.                         suggestion.append( board.getDate( x, y ) );
  215.                         first = false;
  216.                     }
  217.                     else
  218.                         suggestion.append( ", "+board.getDate( x, y ) );
  219.                 }
  220.             }
  221.         }
  222.  
  223.         suggestion.append( "." );
  224.         return suggestion.toString();
  225.     }
  226.  
  227.     void recalculateSumAndMe( int x, int y ) {
  228.         double sum = 0;
  229.         Enumeration e = schedules.elements();
  230.  
  231.         while( e.hasMoreElements() ) {
  232.             UserSchedule sch = (UserSchedule)e.nextElement();
  233.  
  234.             sum += (double)sch.fitness( x, y );
  235.         }
  236.  
  237.         if( schedules.size() > 0 )
  238.             sum /= (double)schedules.size();
  239.  
  240.         board.set( x, y, scaleToRange( myschedule.get( x, y ) ), scaleToRange( sum ) );
  241.     }
  242.  
  243.     void recalculateCol( int x ) {
  244.         for( int y = 0; y <= UserSchedule.NR_HOURS; y++ ) {
  245.             recalculateSumAndMe( x, y );
  246.         }
  247.     }
  248.  
  249.     void recalculateRow( int y ) {
  250.         for( int x = 0; x <= UserSchedule.WEEK_DAYS; x++ ) {
  251.             recalculateSumAndMe( x, y );
  252.         }
  253.     }
  254.  
  255.     void recalculateAll() {
  256.         for( int x = 0; x <= UserSchedule.WEEK_DAYS; x++ ) {
  257.             for( int y = 0; y <= UserSchedule.NR_HOURS; y++ ) {
  258.                 recalculateSumAndMe( x, y );
  259.             }
  260.         }
  261.     }
  262.  
  263.     public boolean mouseDown( Event evt, int x, int y ) {
  264.         int array[] = new int[3];
  265.         byte how;
  266.  
  267.         if( myschedule == null ) return false;
  268.  
  269.         status( schedules.size()+" users." );
  270.  
  271.         if( evt.target == board ) {
  272.             if( x > 0 && y > 0 ) {
  273.                 myschedule.clickThrough( x, y );
  274.                 how = myschedule.get( x, y );
  275.  
  276.                 recalculateSumAndMe( x, y );
  277.  
  278.                 array[0] = x;
  279.                 array[1] = y;
  280.                 array[2] = (int)how;
  281.                 com.sendToOthers( new Msg( MSG_NEW_SCHEDULE_PART, array ) );
  282.             }
  283.             else {
  284.                 if( x == 0 && y > 0 ) {
  285.                     // take the first one and take it as a start...
  286.                     myschedule.clickThrough( 1, y );    
  287.                     how = myschedule.get( 1, y );
  288.  
  289.                     myschedule.setRow( y, how );
  290.                     recalculateRow( y );
  291.                     array[0] = y;
  292.                     array[1] = (int)how;
  293.                     com.sendToOthers( new Msg( MSG_NEW_SCHEDULE_ROW, array ) );
  294.                 }
  295.                 if( y == 0 && x > 0 ) {
  296.                     // take the first one and take it as a start...
  297.                     myschedule.clickThrough( x, 1 );    
  298.                     how = myschedule.get( x, 1 );
  299.  
  300.                     myschedule.setCol( x, how );
  301.                     recalculateCol( x );
  302.                     array[0] = x;
  303.                     array[1] = (int)how;
  304.                     com.sendToOthers( new Msg( MSG_NEW_SCHEDULE_COL, array ) );
  305.                 }
  306.             }
  307.  
  308.             return true;
  309.         }
  310.  
  311.         return false;
  312.     }
  313.  
  314.     public boolean action(Event evt,Object what)
  315.     {
  316.         if( evt.target == miclear || evt.target == miallok || evt.target == miallno ) {
  317.             if( evt.target == miclear ) myschedule.clear();
  318.             else if( evt.target == miallok ) myschedule.set( UserSchedule.ME_OK );
  319.             else if( evt.target == miallno ) myschedule.set( UserSchedule.ME_NO );
  320.  
  321.             recalculateAll();
  322.             com.sendToOthers( new Msg( MSG_NEW_SCHEDULE, myschedule ) );
  323.  
  324.             return true;
  325.         }
  326.         if( evt.target == misuggest ) {
  327.             String suggestion = makeSuggestion();
  328.             com.sendToAll( new Msg( Msg.CHAT_DIALOG_STRING, suggestion ) );
  329.  
  330.             return true;
  331.         }
  332.         return false;
  333.     }
  334. }
  335.  
  336. class Board extends Canvas {
  337.     int week_days, min_hour, max_hour, nr_hours;
  338.     int xs, ys;    // xsize and ysize
  339.     
  340.     int board[][];
  341.  
  342.     String weekdays[] = { "Sunday", "Monday", "Tuesday", "Wednesday",
  343.                                  "Thursday", "Friday", "Saturday" };
  344.  
  345.     public Board( int week_days, int min_hour, int max_hour ) {
  346.         super();
  347.  
  348.         this.week_days = week_days;
  349.         this.min_hour = min_hour;
  350.         this.max_hour = max_hour;
  351.         this.nr_hours = max_hour-min_hour+1;
  352.         this.xs = week_days * 2 + 2;
  353.         this.ys = nr_hours + 1;
  354.  
  355.         board = new int[xs][ys];
  356.         clear();
  357.     }
  358.  
  359.     synchronized public void clear() {
  360.         for( int x = 0; x < xs; x++ ) {
  361.             for( int y = 0; y < ys; y++ ) {
  362.                 board[x][y] = 0;
  363.             }
  364.         }
  365.     }
  366.  
  367.     // the range from the others go from -100 to 100!
  368.     // -100: does not fit at all
  369.     //  100: fits very well
  370.     synchronized public void setMe( int x, int y, int me ) {
  371.         board[x*2][y] = me;
  372.         drawCell( x*2, y );
  373.     }
  374.  
  375.     synchronized public void setSum( int x, int y, int sum ) {
  376.         board[x*2+1][y] = sum;
  377.         drawCell( x*2+1, y );
  378.     }
  379.  
  380.     synchronized public int getSum( int x, int y ) {
  381.         return board[x*2+1][y];
  382.     }
  383.  
  384.     public void set( int x, int y, int me, int sums ) {
  385.         setMe( x, y, me );
  386.         setSum( x, y, sums );
  387.     }
  388.  
  389.     /**
  390.       * returns to the cell (internal numbers) the corresponding realcoords.
  391.       */
  392.     public Rectangle getRect(int x, int y) {
  393.         int xsize = size().width;
  394.         int ysize = size().height;
  395.         int csx = xsize/xs;
  396.         int csy = ysize/ys;
  397.         int bx = (xsize-csx*xs)/2;
  398.         int by = (ysize-csy*ys)/2;
  399.  
  400.         return new Rectangle(bx+csx*x+1,by+csy*y+1,csx-2,csy-2);        
  401.     }
  402.  
  403.     /**
  404.       * returns the cell (internal numbers) of the corresponding readlcoords.
  405.       */
  406.     public Point whichRect(int x, int y) {
  407.         if ((xs!=0)&&(ys!=0)) {
  408.             int xsize = size().width;
  409.             int ysize = size().height;
  410.             int csx = xsize/xs;
  411.             int csy = ysize/ys;
  412.             int bx = (xsize-csx*xs)/2;
  413.             int by = (ysize-csy*ys)/2;
  414.  
  415.             return new Point((x-bx)/csx,(y-by)/csy);
  416.         }
  417.         else return null;
  418.     }
  419.  
  420.     public void paint(Graphics g) {
  421.       g.clearRect(0,0,size().width,size().height);
  422.       int x,y;
  423.       int xmin = getRect(0,0).x;
  424.       int xmax = getRect(xs,0).x;
  425.       int ymin = getRect(0,0).y;
  426.       int ymax = getRect(0,ys).y;
  427.  
  428.       for (x=0;x<=xs;x+=2) {
  429.          Rectangle r = getRect(x,x);
  430.          g.drawLine(r.x-1,ymin-1,r.x-1,ymax-1);
  431.       }
  432.  
  433.       for (y=0;y<=ys;y++) {
  434.          Rectangle r = getRect(y,y);
  435.          g.drawLine(xmin-1,r.y-1,xmax-1,r.y-1);
  436.       }
  437.  
  438.       for( x=0; x<xs; x++ ) {
  439.          for( y=0; y<ys; y++ ) {
  440.            drawCell(x,y);
  441.          }
  442.        }
  443.     }
  444.  
  445.     public void drawCell(int x, int y) {
  446.         Rectangle r = getRect(x,y);
  447.         Graphics g = getGraphics();
  448.         if (g != null) {
  449.  
  450.             if( x > 1 && y > 0 ) {
  451.                 g.clearRect(r.x,r.y,r.width,r.height);
  452.  
  453.                 if( board[x][y] < 0 ) 
  454.                     g.setColor(Color.red);
  455.                 else
  456.                     g.setColor(Color.green);
  457.  
  458.  
  459.                 if( x % 2 == 0 ) // me
  460.                 {
  461.                     FontMetrics fm = g.getFontMetrics();
  462.  
  463.                     int nr = 1;
  464.                     String type[] = { "No", " ", "OK" };
  465.  
  466.                     if( board[x][y] < -33 ) nr = 0;
  467.                     else if( board[x][y] < 33 ) nr = 1;
  468.                     else nr = 2;
  469.  
  470.                     int baseline = (r.height-fm.getHeight())/2+fm.getAscent();
  471.                     g.drawString( type[nr], r.x+2, r.y+baseline );
  472.                 }
  473.                 else
  474.                 {
  475.                     int val = Math.abs(board[x][y]);
  476.                     g.fillRect(r.x,r.y,r.width*val/100,r.height);
  477.                 }
  478.             }
  479.             else {
  480.                 if( x == 0 && y > 0 ) {
  481.                     printInCell( g, x, y, String.valueOf(min_hour+y-1)+":00", Color.black );
  482.                 }
  483.                 if( y == 0 && x > 0 && (x % 2) == 0 ) {
  484.                     Color color = Color.black;
  485.                     int day = x/2 - 1;
  486.  
  487.                     if( day == (new Date()).getDay() )
  488.                         color = Color.red;
  489.  
  490.                     printInCell( g, x, y, weekdays[day], color );
  491.                 }
  492.             }
  493.         }
  494.     }
  495.  
  496.     private void printInCell( Graphics g, int x, int y, String text, Color color ) {
  497.         FontMetrics fm = g.getFontMetrics();
  498.         Rectangle r = getRect(x,y);
  499.         Rectangle r2 = getRect(x+1,y);
  500.         int height = fm.getHeight();
  501.         int width = fm.stringWidth( text );
  502.  
  503.         if( width > 2*r.width && !(text.charAt(0) >= '0' && text.charAt(0) <= '9') ) {
  504.             text = text.substring( 0, 3 );
  505.             width = fm.stringWidth( text );
  506.         }
  507.  
  508.         int baseline = (r.height-height)/2+fm.getAscent();
  509.         int leading = r.width-width/2;
  510.  
  511.         g.setColor(color);
  512.  
  513.         g.clearRect(r.x,r.y,r.width,r.height);
  514.         g.clearRect(r2.x,r2.y,r2.width,r2.height);
  515.  
  516.         g.drawString( text, r.x+leading, r.y+baseline );
  517.     }
  518.  
  519.     String getDate( int x, int y ) {
  520.         return weekdays[x - 1]+" at "+String.valueOf(min_hour+y-1)+":00";
  521.     }
  522.  
  523.  
  524.     public boolean handleEvent(Event evt) {
  525.         int x = evt.x;
  526.         int y = evt.y;
  527.         evt.target = this;
  528.  
  529.         evt.x = whichRect(x,y).x/2;
  530.         evt.y = whichRect(x,y).y;
  531.  
  532.         // only send the event, if it was inside me (where else??)
  533.         if ((evt.x >= 0) && (evt.x < xs) && (evt.y >= 0) && (evt.y <ys))
  534.         {
  535.             if( getParent() != null )
  536.                 getParent().postEvent(evt);
  537.  
  538.         }
  539.  
  540.         return true;
  541.     }
  542.  
  543.     public Dimension preferredSize() {
  544.         if( getGraphics() != null ) {
  545.             // this is just a rough calculation...
  546.         
  547.             FontMetrics f = getGraphics().getFontMetrics();
  548.  
  549.             int h = f.getHeight() * (ys+3);
  550.             int w = f.stringWidth( "Wednesdaym" ) * (xs/2);
  551.  
  552.             return new Dimension( w, h );
  553.         }
  554.         else return super.preferredSize();
  555.     }
  556. }
  557.