------Actor
package meetFinder;import java.awt.event.*;
abstract public class Actor implements ActionListener {
public void actionPerformed(ActionEvent ev) {
run();
}
abstract public void run();
}
------AllOfUs
package meetFinder;
import java.util.*;import java.awt.*;import javax.swing.*;
class AllOfUs extends Person {
AllOfUs(String nm,Committee cmte) {
super(nm);
committee = cmte;
}
/////////////////////////////
Committee committee;
/////////////////////////////
void recompute() {
committee.recomputeTotal(this);
}
boolean isComposite() { return true; }
void showMembers(MFDate dt,int slt,int sltPR,
Container mom,int x,int y)
{
Vector victims = committee.allHitBy(dt,slt,sltPR);
if(victims.size()==0) return;
JPopupMenu pop = new JPopupMenu();
Iterator iter = victims.iterator();
while(iter.hasNext())
pop.add(iter.next().toString());
pop.show(mom,x,y);
}
}
------Committee
package meetFinder;
import javax.swing.*;import java.util.*;import java.io.*;
class Committee extends Saveable {
Committee(String nm,File f,Main mn) {
super(nm,f);
main = mn;
members = new Vector();
}
Committee(Main mn) {
main = mn;
members = new Vector();
}
////////////////////////
Main main;
Vector members;
Person allOfUs;
////////////////////////
void add(Person p) {
members.add(p);
}
Person addSummaryMember() {
allOfUs = new AllOfUs("ALL",this);
members.add(allOfUs);
return allOfUs;
}
// tp had been allOfUs
void recomputeTotal(Person tp) {
tp.clear();
Iterator iter = members.iterator();
while(iter.hasNext()) {
Person p = (Person)iter.next();
tp.add(p);
}
}
void fillComboBox(JComboBox cbx) {
cbx.removeAllItems();
Iterator iter = members.iterator();
while(iter.hasNext())
cbx.addItem(iter.next());
}
Person addMember() {
JFileChooser dlg = new JFileChooser();
//fixFileChooser(dlg,chs,'e',main);
setDefault(dlg,"cmbr","Member");
if(dlg.showOpenDialog(main)!=JFileChooser.APPROVE_OPTION)
return null;
File file = dlg.getSelectedFile();
file = Util.forceAnExtension(file,"cmbr");
Person p = new Person(file);
if(file.exists()) try {
p.load();
} catch(Exception ex) {
main.showWarning("CANNOT LOAD: "+file,ex.toString());
return null;
} else {
int res = JOptionPane.showConfirmDialog(
main,"This will be a NEW blank Member",
"Please NOTE:",
JOptionPane.OK_CANCEL_OPTION);
if(res!=JOptionPane.OK_OPTION) return null;
}
add(p);
return p;
}
void removeMember(Person p) {
members.remove(p);
}
void writeTo(BufferedWriter bwr) throws Exception {
bwr.write("name="+name); bwr.newLine();
bwr.write("begins="+DaySchedule.dayBegins); bwr.newLine();
main.writeDateRange(bwr);
Iterator iter = members.iterator();
while(iter.hasNext()) {
Person p = (Person)iter.next();
if(p.file==null) continue;
// Not a saveable person
bwr.write("member="+p.file);
bwr.newLine();
}
}
void saveAll() throws Exception {
Iterator iter = members.iterator();
while(iter.hasNext()) {
Person p = (Person)iter.next();
if(p.file==null) continue;
// Not a saveable person
p.save();
}
}
static String defaultExten() { return "cmte"; }
void loadFrom(BufferedReader brd) throws Exception {
Pair pr;
MFDate[] dtRng = null;
int dtCnt = 0, dtX = 0;
while(true) {
pr = Pair.readFrom(brd);
if(pr==null) break;
Object k = pr.key;
String v = (String)pr.value;
if(k.equals("begins")) {
DaySchedule.dayBegins = Integer.parseInt(v);
continue;
}
if(k.equals("name")) { name = v; continue; }
if(k.equals("file")) { file = new File(v);
continue; }
if(k.equals("date count")) {
dtCnt = Integer.parseInt(v);
dtRng = new MFDate[dtCnt];
continue;
}
if(k.equals("date")) {
if(dtRng==null)
throw new Exception(
"date without date count");
if(dtX>=dtCnt) throw new Exception(
"too many date");
dtRng[dtX++] = new MFDate(v); continue;
}
if(k.equals("member")) {
File mf = new File(v);
Person p = new Person(mf);
if(mf.exists()) try {
p.load();
} catch(Exception ex) {
main.showWarning(
"CANNOT LOAD: "+mf,ex.toString());
continue;
}
add(p); continue;
}
throw new Exception("Unknown Committee key="+k);
}// of the while(true)
main.setRange(dtRng);
}
void setDefault(JFileChooser dlg,String ext,String kind) {
dlg.setCurrentDirectory(main.getDefaultDirectory());
Util.fixFileChooser(dlg,ext,kind,main);
}
void saveas() throws Exception {
JFileChooser dlg = new JFileChooser();
if(file!=null) dlg.setSelectedFile(file);
else dlg.setSelectedFile(
new File(name+'.'+defaultExten()));
setDefault(dlg,"cmte","Committee");
if(dlg.showSaveDialog(null)!=JFileChooser.APPROVE_OPTION)
return;
File f = dlg.getSelectedFile();
f = Util.forceAnExtension(f,"cmte");
writeTo(f);
file = f;
name = Util.nameWOExten(file);
main.setGoodTitle();
}
void open() throws Exception {
members = new Vector();
addSummaryMember();
JFileChooser dlg = new JFileChooser();
setDefault(dlg,"cmte","Committee");
if(dlg.showOpenDialog(main)!=JFileChooser.APPROVE_OPTION)
return;
File file = dlg.getSelectedFile();
file = Util.forceAnExtension(file,"cmte");
if(file.exists()) try {
loadFrom(file);
} catch(Exception ex) {
ex.printStackTrace();
main.showWarning("CANNOT LOAD",
file.toString()+" : "+ex.toString());
return;
}
}
Vector allHitBy(MFDate dt,int slt,int sltPR) {
Vector lst = new Vector();// Of persons
Iterator iter = members.iterator();
while(iter.hasNext()) {
Person p = (Person)iter.next();
if(p.isComposite()) continue;
if(p.isHitBy(dt,slt,sltPR))
lst.add(p);
}
return lst;
}
}
------ControlPane
package meetFinder;
import javax.swing.*;import javax.swing.border.*;import java.awt.*;
class ControlPane extends JPanel {
ControlPane(Main mn) {
main = mn;
layout = new DividerLayout();
setLayout(layout);
//------begin date selector
JButton ok = new JButton("OK");
beginDS = MFDate.makeSelector("First Day:",2003,ok);
ok.addActionListener(new Actor() {
public void run() { setRange();
}});
dayCountTF = new JTextField(3);
beginDS.addCell(0,2,3,new JLabel("For:"),"L");
beginDS.addCell(1,2,3,dayCountTF,"L");
beginDS.setBorder(new EtchedBorder());
layout.setNextCell(0,2,0,1);
add(beginDS,"");
//------Person selection
layout.setNextCell(0,1,1,2);
add(new JLabel("Member:"),"");
layout.setNextCell(1,2,1,2);
addPersonSel("LR");
//------time step selection
layout.setNextCell(0,1,2,3);
add(new JLabel("Time Step:"),"");
layout.setNextCell(1,2,2,3);
addIncrSel("");
}
//////////////////////////////////
Main main;
MFDate.Selector beginDS;
DividerLayout layout;
JComboBox incrCB;
JComboBox groupCB;
JTextField dayCountTF;
//////////////////////////////////
void setRange() {
MFDate dt = beginDS.getSelectedDate();
if(dt==null) return;
int nd = 0;
if(dt.isWeekday()) {
nd = 7;
dt = new MFDate(1,1);
dayCountTF.setText("7");
} else try {
nd = Integer.parseInt(dayCountTF.getText());
} catch(Exception ex) {
nd = 7;
dayCountTF.setText("7");
}
main.setRange(dt,nd);
}
void setSelectedDate(MFDate dt) {
beginDS.setSelectedDate(dt);
}
void remakeGroup() {
main.committee.fillComboBox(groupCB);
}
void addPersonSel(String jst) {
groupCB = new JComboBox();
main.committee.fillComboBox(groupCB);
groupCB.addActionListener(new Actor() {
public void run() {
Person p = (Person)groupCB.getSelectedItem();
main.schedulePane.setPerson(p);
}});
add(groupCB,"LR");
}
void setPerson(Person p) {
groupCB.setSelectedItem(p);
}
Person getPerson() {
return (Person) groupCB.getSelectedItem();
}
void addIncrSel(String jst) {
Object defIS = main.newIncrSelector("1 hour",4);
incrCB = new JComboBox(
new Object[] {
main.newIncrSelector("15 min",1),
main.newIncrSelector("30 min",2),
defIS
}
);
incrCB.setSelectedItem(defIS);
incrCB.addActionListener(new Actor() {
public void run() {
Runnable sel = (Runnable)
incrCB.getSelectedItem();
if(sel!=null) sel.run();
}});
add(incrCB,jst);
}
}
------DayHeader
package meetFinder;import javax.swing.*;import java.awt.*;
class DayHeader extends JPanel {
DayHeader(MFDate[] rng,FontMetrics fm) {
dateRange = rng;
fixSize(fm);
}
/////////////////////
MFDate[] dateRange;
/////////////////////
static Dimension prefSize;
static int charHgt;
static int charWid;
/////////////////////
void fixSize(FontMetrics fm) {
charHgt = fm.getHeight();
charWid = fm.charWidth(' ');
fixSize();
}
void fixSize() {
prefSize = new Dimension(
dateRange.length*DayPane.dayWidth,
2*charHgt+9);
}
void setRange(MFDate[] rng) {
dateRange = rng;
fixSize();
}
public Dimension getPreferredSize() { return prefSize; }
public void paintComponent(Graphics g) {
super.paintComponent(g);
//g.setColor(Color.white);
//g.drawLine(0,0,prefSize.width,prefSize.height);
int x=0, dx=0;
int ht = prefSize.height;
int wd = DayPane.prefSize.width;
int cnt = dateRange.length;
int offs = 2*charWid+3;
g.setFont(Main.font);
while(dx<cnt) {
g.setColor(Color.black);
MFDate dt = dateRange[dx];
g.drawString(dt.toStringMD(),
x+5,
charHgt+3);
g.drawString(dt.toStringW(),
x+offs,
ht-3);
g.drawLine(x,0,x,ht);
x += wd;
++dx;
}
g.drawLine(x,0,x,ht);
}
}
------DayPane
package meetFinder;
import javax.swing.*;import java.awt.*;import java.awt.event.*;
class DayPane extends JPanel {
DayPane(DaySchedule ds,Person p) {
day = ds;
person = p;
weekday = p.getDay(day.date.getWeekdayFor());
setBackground(Color.white);
addMouseListener();
}
/////////////////////
DaySchedule day;
DaySchedule weekday;
Person person;
/////////////////////
static boolean includeWeekly;// usually cached from Main
static protected int slotPerRow;
static int dayHeight, dayWidth;
static Dimension prefSize;
final static int MAXOCCUCOLOR =4;
static Color[] occuColor;
/////////////////////
static {
occuColor = new Color[MAXOCCUCOLOR+1];
for(int k=0;k<MAXOCCUCOLOR+1;++k) {
int v = 255 - 255*k/MAXOCCUCOLOR;
occuColor[k] = new Color(v,v,v);
}
}
static void setDaySize(int wid,int hgt,int nspr) {
// call AFTER DaySchedule.setDivision
slotPerRow = nspr;
dayHeight = hgt; dayWidth = wid;
prefSize = new Dimension(dayWidth,
dayHeight*DaySchedule.slotCount/slotPerRow);
}
static void setSlotPR(int nspr) {
slotPerRow = nspr;
prefSize = new Dimension(dayWidth,
dayHeight*DaySchedule.slotCount/slotPerRow);
TimeSider.fixSize();
}
void addMouseListener() {
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent ev) {
java.awt.Point p = ev.getPoint();
int row = ev.getY()/dayHeight;
if(person.isComposite())
showVictims(p,row);
else toggleRow(row);
}});
}
void showVictims(java.awt.Point p,int row) {
Container tlanc = getTopLevelAncestor();
SwingUtilities.convertPointToScreen(p,this);
SwingUtilities.convertPointFromScreen(p,tlanc);
person.showMembers(day.date,row*slotPerRow,slotPerRow,
tlanc,p.x,p.y);
}
void toggleRow(int row) {
int usg = day.occupancy(row*slotPerRow,slotPerRow);
int tog = (usg==0)?1:0;
day.setOccupancy(row*slotPerRow,slotPerRow,tog);
repaint();
}
public Dimension getPreferredSize() { return prefSize; }
public void paintComponent(Graphics g) {
super.paintComponent(g);
//g.setColor(Color.red);
//g.drawLine(0,0,prefSize.width,prefSize.height);
g.setColor(Color.blue);
g.drawRect(0,0,prefSize.width,prefSize.height-1);
int x=0, y=0, slot=0;
while(slot<DaySchedule.slotCount) {
int usg = day.occupancy(slot,slotPerRow);
if(includeWeekly) {
int wku = weekday.occupancy(slot,slotPerRow);
if(wku>usg) usg=wku;
}
if(usg>0) {
if(usg>MAXOCCUCOLOR) usg=MAXOCCUCOLOR;
g.setColor(occuColor[usg]);
g.fillRect(1,y+1,dayWidth-1,dayHeight-1);
}
slot += slotPerRow;
y = y+dayHeight;
g.setColor(Color.blue);
g.drawLine(0,y,dayWidth,y);
}
}
}
------DaySchedule
package meetFinder;import java.io.*;
class DaySchedule {
DaySchedule(MFDate d) {
date = d;
used = new byte[slotCount];
}
DaySchedule(DaySchedule ds,MFDate d) {
date = d;
used = ds.used;
}
///////////////////////
MFDate date;
byte[] used;// in increments of
///////////////////////
static int dayBegins;// minutes since midnight
static int dayEnds;// same.
final static int slotInterval=15;// in minutes
static int slotCount;
static String[] hours = {
" 12:"," 1:"," 2:"," 3:"," 4:"," 5:",
" 6:"," 7:"," 8:"," 9:"," 10:"," 11:","p12:",
"p 1:","p 2:","p 3:","p 4:","p 5:","p 6:","p 7:","p 8:",
"p 9:","p10:","p11:" };
static char[] minWork = new char[2];
///////////////////////
static void setDivision(int hB,int mB,int hE,int mE) {
dayBegins = minutes(hB,mB);
dayEnds = minutes(hE,mE);
slotCount = (dayEnds-dayBegins+
slotInterval-1)/slotInterval;
}
static int minutes(int hr,int m) { return 60*hr+m; }
static String slotName(int k) {
int tm = dayBegins+k*slotInterval;
int m = tm%60;
return hours[tm/60]+(char)('0'+m/10)+(char)('0'+m%10);
}
static DaySchedule[] makeRange(MFDate[] rng) {
int nd = rng.length;
DaySchedule[] days = new DaySchedule[nd];
for(int k=0;k<nd;++k)
days[k] = new DaySchedule(rng[k]);
return days;
}
String dayName() {
return date.toStringMD();
}
void setUsed(String d) {
// Ignored parts of d too long.
// Fills missing parts of d as zeros.
int mx = d.length();
if(mx>slotCount) mx=slotCount;
else if(mx<slotCount) {
for(int k=mx;k<slotCount;++k) used[k] = 0;
}
for(int k=0;k<mx;++k)
used[k] = (byte)Character.digit(d.charAt(k),10);
}
void dump() {
System.err.println("DaySchedule for "+date);
for(int k=0;k<used.length;++k) System.err.print((used[k]==0)?"0":"1");
System.err.println(" ");
}
int occupancy(int slot,int cnt) {
// cnt many slots starting at slot
int res = 0;
for(int k=0;k<cnt;++k) {
int us = used[slot+k];
if(us>res) res = us;
}
return res;
}
void setOccupancy(int slot,int cnt,int occ) {
// cnt many slots starting at slot
for(int k=0;k<cnt;++k)
used[slot+k] = (byte)occ;
}
void clear() {
for(int k=0;k<slotCount;++k)
used[k] =0;
}
void add(DaySchedule ds) {
for(int k=0;k<slotCount;++k)
used[k] += ds.used[k];
}
void writeTo(BufferedWriter bwr) throws Exception {
boolean any=false;
for(int k=0;k<used.length;++k)
if(used[k]>0) { any=true; break; }
if(!any) return;
bwr.write("date="+date); bwr.newLine();
bwr.write("used=");
for(int k=0;k<used.length;++k)
bwr.write((used[k]==0)?'0':'1');
bwr.newLine();
}
static void writeConfigTo(BufferedWriter bwr) throws Exception {
bwr.write("begins="+dayBegins); bwr.newLine();
}
}
------EMFrame
package meetFinder;import javax.swing.*;import java.awt.*;
import java.awt.event.*;import java.util.*;import java.io.*;
public class EMFrame extends JFrame
{
public EMFrame(String ttl,File dfdr) {
super(ttl);
defaultDirectory = dfdr;
makeMenuBar();
mainPane = getContentPane();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent ev) {
closing();
}});
}
///////////////////////////////////////
protected Container mainPane;
protected File defaultDirectory;
protected JMenu fileMenu;
///////////////////////////////////////
protected JMenu addMenu(String lbl) {
JMenu men = new JMenu(lbl);
getJMenuBar().add(men);
return men;
}
protected JMenuItem addMenuItem(
String name,Actor act,JComponent mom) {
JMenuItem mit = new JMenuItem(name);
mit.addActionListener(act);
mom.add(mit);
return mit;
}
protected JMenuItem addMenuItem(String name,char mne,boolean en,
Actor act,JComponent mom)
{
JMenuItem mit = addMenuItem(name,act,mom);
mit.setMnemonic(mne);
mit.setEnabled(en);
return mit;
}
protected void makeMenuBar() {
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
}
protected void makeFileMenu() {
fileMenu = addMenu("File"); fileMenu.setMnemonic('f');
}
public void showWarning(String ttl,String msg) {
JOptionPane.showMessageDialog(this,msg,ttl,
JOptionPane.WARNING_MESSAGE);
}
protected void closing() {
System.exit(0);
}
public void losing(JComponent vwr) {
}
public File getDefaultDirectory() { return defaultDirectory; }
public void setDefaultDirectory(File dd) { defaultDirectory=dd; }
public void makeViewable() {
show();
}
public void showMessage(String ttl,String msg) {
JOptionPane.showMessageDialog(this,msg,ttl,
JOptionPane.INFORMATION_MESSAGE);
}
}
------ExtensionFileFilter
package meetFinder;
import javax.swing.filechooser.*;import java.io.*;
public class ExtensionFileFilter
extends javax.swing.filechooser.FileFilter
{
String extension, description;
public ExtensionFileFilter(String exten,String descr) {
extension = exten;
description = descr;
}
public boolean accept(File f) {
boolean ok = f.isDirectory() ||
f.getName().toLowerCase().endsWith(extension);
//System.out.println("file "+f+"="+f.getName()+" is "+ok);
return ok;
}
public String getDescription() { return description+"%"; }
}
------Main
package meetFinder;import java.io.*;import javax.swing.*;
import java.awt.*;import java.awt.event.*;
public class Main extends EMFrame {
Main(File dfdr) {
super("Meeting Scheduler",dfdr);
makeFileMenu();
extendFileMenu();
makeMemberMenu();
setVisible(true);
font = new Font("courier",Font.PLAIN,12);
Graphics g = getGraphics();
System.err.println("g="+g);
fontMetrics = g.getFontMetrics(font);
System.err.println("fm="+fontMetrics);
charHgt = fontMetrics.getHeight();
setVisible(false);
DayPane.includeWeekly = includeWeekly;// Breaks RULE#1
dummyUp();
setVisible(true);
pack();
}
////////////////////////////////////
Committee committee;
MFDate[] dateRange;// also set into schedulePane
// and dayHeader
boolean includeWeekly = true;
////////////////////////////////////
ControlPane control;
SchedulePane schedulePane;
TimeSider timeSider;
DayHeader dayHeader;
JMenu memberMenu;
////////////////////////////////////
static Font font;
static FontMetrics fontMetrics;
static int charHgt;
////////////////////////////////////
void setGoodTitle() {
setTitle(committee.toString()+" Meet Finder");
}
void extendFileMenu() {
addMenuItem("open",new Actor() {
public void run() {
try {
committee = new Committee(Main.this);
committee.open();
control.remakeGroup();
setPerson(committee.allOfUs);
setGoodTitle();
} catch(Exception ex) {
showWarning(
"CAN’T open Committee: "
+committee.name,
ex.toString());
}
}},fileMenu);
addSaverItem("save",false);
addSaverItem("save as",true);
}
void addSaverItem(String lbl,final boolean as) {
addMenuItem(lbl,new Actor() {
public void run() {
try {
if(as) committee.saveas();
else committee.save();
committee.saveAll();
} catch(Exception ex) {
ex.printStackTrace();
showWarning(
"CANNOT save Committee: "
+committee.name,
ex.toString());
}
}},fileMenu);
}
void setPerson(Person p) {
schedulePane.setPerson(p);
control.setPerson(p);
}
void makeMemberMenu() {
memberMenu = addMenu("Member");
addMenuItem("add",new Actor() {
public void run() {
Person p = committee.addMember();
if(p==null) return;
//p.dump();
control.remakeGroup();
setPerson(p);
//System.err.print("AGAIN> "); p.dump();
}
},memberMenu);
addMenuItem("remove",new Actor() {
public void run() {
Person p = control.getPerson();
committee.removeMember(p);
control.remakeGroup();
}
},memberMenu);
addMemberSaver("save",false);
addMemberSaver("save as",true);
addMenuItem("Summary",new Actor() {
public void run() {
setPerson(committee.allOfUs);
}},memberMenu);
}
void addMemberSaver(String lbl,final boolean as) {
addMenuItem(lbl,new Actor() {
public void run() {
try {
Person p = control.getPerson();
if(p==null) return;
if(as) {
p.saveas(Main.this);
control.remakeGroup();
setPerson(p);
} else p.save();
} catch(Exception ex) {
ex.printStackTrace();
showWarning(
"CANNOT SAVE MEMBER",
ex.toString());
}
}},memberMenu);
}
void dummyUp() {
committee = new Committee("UN-NAMED",null,this);
setGoodTitle();
Person p = committee.addSummaryMember();
DaySchedule.setDivision(9,0,17,0);
DayPane.setDaySize(fontMetrics.stringWidth(
" May 31 "),20,4);
TimeSider.fixSize(fontMetrics);
dateRange = MFDate.makeRange(new MFDate(2003,1,7),1);
mainPane.setLayout(new BorderLayout());
schedulePane = new SchedulePane(p,dateRange);
JScrollPane scrp = new JScrollPane(schedulePane);
timeSider = new TimeSider();
scrp.setRowHeaderView(timeSider);
dayHeader = new DayHeader(dateRange,fontMetrics);
scrp.setColumnHeaderView(dayHeader);
mainPane.add(scrp,BorderLayout.CENTER);
control = new ControlPane(this);
mainPane.add(control,BorderLayout.NORTH);
}
Runnable newIncrSelector(String nm,int v) {
IncrSelector is = new IncrSelector();
is.name = nm; is.value = v;
return is;
}
class IncrSelector implements Runnable {
////////////////////////////////
String name; int value;
////////////////////////////////
public String toString() { return name; }
public void run() {
DayPane.setSlotPR(value);
schedulePane.fixSize();
setPerson(control.getPerson());
repaint();
}
}
void setRange(MFDate[] dtRng) {
dateRange = dtRng;
control.setSelectedDate(dtRng[0]);
schedulePane.setRange(dtRng);
dayHeader.setRange(dtRng);
dayHeader.fixSize();
pack();
repaint();
}
void setRange(MFDate dt,int nd) {
MFDate[] dtRng = MFDate.makeRange(dt,nd);
setRange(dtRng);
}
void writeDateRange(BufferedWriter bwr) throws Exception {
int nd = dateRange.length;
bwr.write("date count="+nd); bwr.newLine();
for(int k=0;k<nd;++k) {
bwr.write("date="+dateRange[k]); bwr.newLine();
}
}
static public void main(String[]args) {
//File dfdr = new File(
//System.getProperty("user.home"));
JFileChooser fch = new JFileChooser();// NEVER displayed
File dfdr = fch.getCurrentDirectory();
dfdr = new File(dfdr,"My-Committees");
System.err.println("dfdr="+dfdr);
dfdr.mkdirs();
new Main(dfdr);
}
}
------Pair
package meetFinder;import java.io.*;
class Pair {
Pair(Object k,Object v) {
key = k; value = v;
}
///////////////////////
public Object key,value;
///////////////////////
static Pair readFrom(BufferedReader brd) throws Exception {
String line = brd.readLine();
if(line==null) return null;
int edot = line.indexOf('=');
if(edot<0)
return new Pair(line,null);
return new Pair(
line.substring(0,edot),
line.substring(edot+1)
);
}
}
------Person
package meetFinder;import java.util.*;import java.io.*;
import java.awt.*;import javax.swing.*;
class Person extends Saveable {
Person(String nm) {
super(nm,null);
schedule = new Hashtable();
}
Person(File f) {