斯坦福CS106A作业6

这次的作业是做一个姓名使用趋势的展示作业,综合了很多知识,收获很大。

NameSurfer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
* File: NameSurfer.java
* ---------------------
* When it is finished, this program will implements the viewer for
* the baby-name database described in the assignment handout.
*/

import acm.program.*;
import java.awt.event.*;
import javax.swing.*;

public class NameSurfer extends Program implements NameSurferConstants {

/* Method: init() */
/**
* This method has the responsibility for reading in the data base
* and initializing the interactors at the top of the window.
*/
public void init() {
// You fill this in, along with any helper methods //
label=new JLabel("Name");
text=new JTextField(20);
graph=new JButton("Graph");
clear=new JButton("Clear");
deletion=new JButton("Deletion");
add(label,NORTH);
add(text,NORTH);
add(graph,NORTH);
add(clear,NORTH);
add(deletion,NORTH);
text.addActionListener(this);
addActionListeners();

//读取数据
database=new NameSurferDataBase(NAMES_DATA_FILE);

Graph = new NameSurferGraph();
add(Graph);
Graph.update();

}

/* Method: actionPerformed(e) */
/**
* This class is responsible for detecting when the buttons are
* clicked, so you will have to define a method to respond to
* button actions.
*/
public void actionPerformed(ActionEvent e) {
// You fill this in //
if(e.getSource()==text) {
String name=text.getText();
NameSurferEntry entry=database.findEntry(name.toUpperCase());
if(entry!=null) {
Graph.addEntry(entry);
Graph.update();
}
//println("Graph: \""+text.getText()+'"');
//println("Graph: \""+database.findEntry(name.toUpperCase())+'"');
}else if(e.getSource()==graph) {
String name=text.getText();
NameSurferEntry entry=database.findEntry(name.toUpperCase());
if(entry!=null) {
Graph.addEntry(entry);
Graph.update();
}
//println("Graph: \""+text.getText()+'"');
//println("Graph: \""+database.findEntry(name.toUpperCase())+'"');
}else if(e.getSource()==clear){
Graph.clear();
Graph.update();
}else {
String name=text.getText();
NameSurferEntry entry=database.findEntry(name.toUpperCase());
Graph.deletion(entry);
Graph.update();
}
}

private JLabel label;
private JTextField text;
private JButton graph;
private JButton clear;
private JButton deletion;
private NameSurferDataBase database;
private NameSurferGraph Graph;
}

NameSurferDataBase

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/*
* File: NameSurferDataBase.java
* -----------------------------
* This class keeps track of the complete database of names.
* The constructor reads in the database from a file, and
* the only public method makes it possible to look up a
* name and get back the corresponding NameSurferEntry.
* Names are matched independent of case, so that "Eric"
* and "ERIC" are the same names.
*/

import acm.util.*;
import java.io.*;
import java.util.*;

public class NameSurferDataBase implements NameSurferConstants {

/* Constructor: NameSurferDataBase(filename) */
/**
* Creates a new NameSurferDataBase and initializes it using the
* data in the specified file. The constructor throws an error
* exception if the requested file does not exist or if an error
* occurs as the file is being read.
*/
public NameSurferDataBase(String filename) {
// You fill this in //

database=new HashMap<String,NameSurferEntry>();

//打开文件
BufferedReader rd = null;
try {
rd=new BufferedReader(new FileReader(filename));
}catch(IOException ex) {
System.out.println("Can't open that file.");
}

//读取数据
try {
while(true) {
String line=rd.readLine();
if(line==null) {
break;
}
NameSurferEntry text=new NameSurferEntry(line);
database.put(text.getName().toUpperCase(), text);
}
rd.close();
}catch(IOException ex) {
throw new ErrorException(ex);
}

}

/* Method: findEntry(name) */
/**
* Returns the NameSurferEntry associated with this name, if one
* exists. If the name does not appear in the database, this
* method returns null.
*/
public NameSurferEntry findEntry(String name) {
// You need to turn this stub into a real implementation //
return database.get(name);
}

HashMap<String,NameSurferEntry> database;
}

NameSurferEntry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/*
* File: NameSurferEntry.java
* --------------------------
* This class represents a single entry in the database. Each
* NameSurferEntry contains a name and a list giving the popularity
* of that name for each decade stretching back to 1900.
*/

import acm.util.*;
import java.util.*;

public class NameSurferEntry implements NameSurferConstants {

/* Constructor: NameSurferEntry(line) */
/**
* Creates a new NameSurferEntry from a data line as it appears
* in the data file. Each line begins with the name, which is
* followed by integers giving the rank of that name for each
* decade.
*/
public NameSurferEntry(String line) {
// You fill this in //
this.text=line.split(" ");
}

/* Method: getName() */
/**
* Returns the name associated with this entry.
*/
public String getName() {
// You need to turn this stub into a real implementation //
return text[0];
}

/* Method: getRank(decade) */
/**
* Returns the rank associated with an entry for a particular
* decade. The decade value is an integer indicating how many
* decades have passed since the first year in the database,
* which is given by the constant START_DECADE. If a name does
* not appear in a decade, the rank value is 0.
*/
public int getRank(int decade) {
// You need to turn this stub into a real implementation //
int rank;
if (decade==0 || decade==10 || decade==20 ||
decade==30 || decade==40 || decade==50 ||
decade==60 || decade==70 || decade==80 ||
decade==90 || decade==100) {
int index=(decade)/10+1;
rank=Integer.parseInt(text[index]);
}else {
rank=0;
}

return rank;
}

/* Method: toString() */
/**
* Returns a string that makes it easy to see the value of a
* NameSurferEntry.
*/
public String toString() {
// You need to turn this stub into a real implementation //
String result=text[0]+" [";
for (int i=1;i<text.length-1;i++) {
result+=text[i]+" ";
}
result+=text[text.length-1]+"]";
return result;
}

private String[] text;
}

NameSurferGraph

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
* File: NameSurferGraph.java
* ---------------------------
* This class represents the canvas on which the graph of
* names is drawn. This class is responsible for updating
* (redrawing) the graphs whenever the list of entries changes
* or the window is resized.
*/

import acm.graphics.*;
import java.awt.event.*;
import java.util.*;
import java.awt.*;

public class NameSurferGraph extends GCanvas
implements NameSurferConstants, ComponentListener {

/**
* Creates a new NameSurferGraph object that displays the data.
*/
public NameSurferGraph() {
addComponentListener(this);
// You fill in the rest //
//init();
}


/**
* Clears the list of name surfer entries stored inside this class.
*/
public void clear() {
// You fill this in //
removeAll();
list.clear();
}

//删除元素
public void deletion(NameSurferEntry entry) {
list.remove(entry);
}

/* Method: addEntry(entry) */
/**
* Adds a new NameSurferEntry to the list of entries on the display.
* Note that this method does not actually draw the graph, but
* simply stores the entry; the graph is drawn by calling update.
*/
public void addEntry(NameSurferEntry entry) {
// You fill this in //
if(list.indexOf(entry)==-1) {
list.add(entry);
}
}

public void show() {
//记录每个排名的位置
double d=(getHeight()-2*GRAPH_MARGIN_SIZE)*1.0/MAX_RANK;
//记录间距
double distance=getWidth()*1.0/NDECADES;
//记录上一年的排名
int last=0;
//画标签以及直线
for ( int j=0;j<list.size();j++) {
NameSurferEntry entry=list.get(j);
String name=entry.getName();
//设置颜色
Color c=color[j%4];
for(int i=0;i<NDECADES;i++) {
//获得年份
int year=10*i;
//System.out.println(year);
//获得数量
int num=entry.getRank(year);
GLabel text=new GLabel(name+" "+(num));
if(num==0) {
text=new GLabel(name+" *");
num=MAX_RANK;
}

text.setColor(c);
//根据增长还是下降调整位置
add(text,i*distance,GRAPH_MARGIN_SIZE+d*num-text.getHeight());

//扩展功能,增加图形点
if (j%2==0) {
GOval object=new GOval(size, size);
object.setFilled(true);
object.setColor(c);
add(object,i*distance-size/2,GRAPH_MARGIN_SIZE+d*num-size/2);
}else {
GRect object=new GRect(size, size);
object.setFilled(true);
object.setColor(c);
add(object,i*distance-size/2,GRAPH_MARGIN_SIZE+d*num-size/2);
}
//画直线
if(i>0) {
GLine line=new GLine((i-1)*distance,GRAPH_MARGIN_SIZE+d*last,
i*distance,GRAPH_MARGIN_SIZE+d*num );
line.setColor(c);
add(line);
}
//更新上一年排名
last=num;
}
}
}


/**
* Updates the display image by deleting all the graphical objects
* from the canvas and then reassembling the display according to
* the list of entries. Your application must call update after
* calling either clear or addEntry; update is also called whenever
* the size of the canvas changes.
*/
public void update() {
removeAll();
init();
show();
}

public void init() {
double distance=getWidth()*1.0/NDECADES;
for (int i=0;i<NDECADES;i++) {
add(new GLine(i*distance,0,i*distance,getWidth()));
String Year=(1900+10*i)+"";
GLabel label=new GLabel(Year);
add(label,i*distance,getHeight()-GRAPH_MARGIN_SIZE+label.getHeight());
}
add(new GLine(0,GRAPH_MARGIN_SIZE,getWidth(),GRAPH_MARGIN_SIZE));
add(new GLine(0,getHeight()-GRAPH_MARGIN_SIZE,getWidth(),getHeight()-GRAPH_MARGIN_SIZE));
}


/* Implementation of the ComponentListener interface */
public void componentHidden(ComponentEvent e) { }
public void componentMoved(ComponentEvent e) { }
public void componentResized(ComponentEvent e) { update(); }
public void componentShown(ComponentEvent e) { }

private ArrayList<NameSurferEntry> list=new ArrayList<NameSurferEntry>();
private Color[] color= {Color.BLACK,Color.RED,Color.BLUE,Color.magenta};
//private GObject object;
private int size=5;
}