Created
July 6, 2012 18:23
-
-
Save JossWhittle/3061823 to your computer and use it in GitHub Desktop.
Source Code for Course-Selector
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TB2 CS-306 10 Writing Mobile Apps | |
TB1 CS-307 10 Computer Graphics II:Modelling and Rendering | |
TB2 CS-311 10 Concepts of Programming Languages | |
TB1 CS-313 10 High Integrity Systems | |
TB2 CS-318 10 Cryptography and IT Security | |
TB1 CS-337 10 Data Visualization | |
TB2 CS-338 10 Internet Computing | |
TB1 CS-345 10 Artificial Intelligence Applications | |
TB2 CS-348 10 Building Reliable Web Applications | |
TB2 CS-349 10 Mobile Interaction Design | |
TB1 CS-358 10 High-Performance Computing in C/C++ | |
TB2 CS-364 10 Software Testing | |
TB1 CS-368 10 Embedded Systems | |
TB2 CS-371 10 Design Patterns and Generic Programming | |
TB1 CS-375 10 Logic for Computer Science | |
TB1 CS-377 10 Computer Vision and Pattern Recognition | |
TB1 CS-390 10 Teaching Computing via a School Placement |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Represents a course | |
* | |
* @author Joss | |
* | |
*/ | |
public class DataNode { | |
// Constants | |
public static final int TB1 = 1, TB2 = 2; | |
private static final float BASE_RANK = 1400; | |
// Members | |
private int m_set, m_credits, m_wins = 0, m_losses = 0; | |
private String m_code, m_name; | |
private float m_rank; | |
/** | |
* Constructor | |
* | |
* @param set | |
* TB1 or TB2 | |
* @param code | |
* The module code | |
* @param name | |
* The module name | |
* @param credits | |
* The credits associated with the module | |
*/ | |
public DataNode(int set, String code, String name, int credits) { | |
m_set = set; | |
m_code = code; | |
m_name = name; | |
m_credits = credits; | |
m_rank = BASE_RANK; | |
System.out.println(getString()); | |
} | |
// Accessor / Mutator | |
public String getString() { | |
return "(" + m_rank + " - " + m_wins + "/" + m_losses + ") " + (m_set == TB1 ? "TB1" : "TB2") + " " + m_code | |
+ " " + m_credits + " " + m_name; | |
} | |
public int getSet() { | |
return m_set; | |
} | |
public int getCredits() { | |
return m_credits; | |
} | |
public String getCode() { | |
return m_code; | |
} | |
public String getName() { | |
return m_name; | |
} | |
public float getRank() { | |
return m_rank; | |
} | |
public void setRank(float rank) { | |
m_rank = rank; | |
} | |
public int getWins() { | |
return m_wins; | |
} | |
public int getLosses() { | |
return m_losses; | |
} | |
public int win() { | |
m_wins++; | |
return m_wins; | |
} | |
public int lose() { | |
m_losses++; | |
return m_losses; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.Color; | |
import java.awt.Component; | |
import java.awt.Dimension; | |
import java.awt.Font; | |
import java.awt.Graphics; | |
import java.awt.Graphics2D; | |
import java.awt.RenderingHints; | |
import javax.swing.JList; | |
import javax.swing.JPanel; | |
import javax.swing.ListCellRenderer; | |
/** | |
* Renders the JList of DNodes | |
* | |
* @author Joss | |
* | |
*/ | |
public class DNListRenderer extends JPanel implements ListCellRenderer { | |
// Constants | |
private static final int WIDTH = 200; | |
private static final int HEIGHT = 25; | |
private static final float FONT_SIZE = 10.0f; | |
private static final int TEXT_X = 5; | |
private static final int TEXT_Y = 15; | |
private static final Color TEXT_COLOUR = new Color(34, 34, 34); | |
private static final Color BACKGROUND_COLOUR = new Color(245, 245, 245); | |
private static final Color SELECTED_COLOUR = new Color(200, 200, 200); | |
// Members | |
private DataNode m_value; | |
private boolean m_selected; | |
/** | |
* Gets the component of the cell to be displayed | |
* | |
* @param list | |
* The JList the cell belongs to | |
* @param value | |
* The value stored in the JList for this cell | |
* @param index | |
* The index this cell is at in the JList | |
* @param isSelected | |
* Is the current cell selected | |
* @param cellHasFocus | |
* Does the cell have focus | |
* @return The component to be rendered (This class) | |
*/ | |
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, | |
boolean cellHasFocus) { | |
setPreferredSize(new Dimension(WIDTH, HEIGHT)); | |
m_selected = isSelected; | |
m_value = (DataNode) value; | |
repaint(); | |
return this; | |
} | |
/** | |
* Renders the header cell | |
* | |
* @param g | |
* The graphics hook passed in by the system | |
*/ | |
protected void paintComponent(Graphics g) { | |
super.paintComponent(g); | |
Graphics2D g2 = (Graphics2D) g; | |
RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); | |
rh.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); | |
rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); | |
g2.setRenderingHints(rh); | |
int w = getWidth(), h = getHeight(); | |
Font stdFont = g2.getFont(); | |
g2.setColor((!m_selected) ? BACKGROUND_COLOUR : SELECTED_COLOUR); | |
g2.fillRect(0, 0, w, h); | |
g2.setColor(TEXT_COLOUR); | |
g2.setFont(stdFont.deriveFont(FONT_SIZE)); | |
g2.drawString(m_value.getString(), TEXT_X, TEXT_Y); | |
g2.dispose(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.BorderLayout; | |
import java.awt.Dimension; | |
import java.awt.EventQueue; | |
import java.awt.event.ActionEvent; | |
import java.awt.event.ActionListener; | |
import java.io.File; | |
import java.net.URI; | |
import java.util.ArrayList; | |
import java.util.Scanner; | |
import javax.swing.JButton; | |
import javax.swing.JFrame; | |
import javax.swing.JList; | |
import javax.swing.JPanel; | |
import javax.swing.JScrollPane; | |
import javax.swing.JSplitPane; | |
import javax.swing.ScrollPaneConstants; | |
import javax.swing.UIManager; | |
import javax.swing.border.TitledBorder; | |
/** | |
* Main Application Window | |
* | |
* @author Joss | |
* | |
*/ | |
public class GUI_Main { | |
// Constants | |
private static final int LEFT = 1, RIGHT = 2; | |
private static final int K = 16; | |
// Members | |
private JFrame frmModuleRanking; | |
private JButton m_btnLeft; | |
private JButton m_btnRight; | |
private JList m_list1; | |
private JList m_list2; | |
private int m_curLeft, m_curRight, m_curSet; | |
private ArrayList<DataNode> m_setLeft, m_setRight; | |
/** | |
* Launch the application. | |
*/ | |
public static void main(String[] args) { | |
EventQueue.invokeLater(new Runnable() { | |
public void run() { | |
try { | |
GUI_Main window = new GUI_Main(); | |
window.frmModuleRanking.setVisible(true); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
}); | |
} | |
/** | |
* Create the application. | |
*/ | |
public GUI_Main() { | |
initialize(); | |
loadData("resources/courses.txt"); | |
} | |
/** | |
* Loads the data to be voted on | |
* | |
* @param dir | |
* The url to the data file | |
*/ | |
private void loadData(String dir) { | |
m_setLeft = new ArrayList<DataNode>(); | |
m_setRight = new ArrayList<DataNode>(); | |
try { | |
File f = new File(new URI(GUI_Main.class.getResource(dir).toString()).getPath()); | |
Scanner inLine = new Scanner(f); | |
while (inLine.hasNext()) { | |
String line = inLine.nextLine(); | |
int set = DataNode.TB1; | |
if (line.startsWith("TB2")) { | |
set = DataNode.TB2; | |
} | |
String code = line.substring(4, 10); | |
int credits = Integer.parseInt(line.substring(11, 13)); | |
String name = line.substring(14); | |
DataNode d = new DataNode(set, code, name, credits); | |
if (set == DataNode.TB1) { | |
m_setLeft.add(d); | |
} else { | |
m_setRight.add(d); | |
} | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
updateLeft(); | |
updateRight(); | |
poseQuestion(); | |
} | |
/** | |
* Randomly select a set and two unique datanodes from that set | |
*/ | |
private void poseQuestion() { | |
m_curSet = (((int) Math.floor(Math.random() * Math.random() * 1000 / Math.random()) % 2 == 0) ? LEFT : RIGHT); | |
m_curLeft = (int) Math.floor(Math.random() * (m_curSet == LEFT ? m_setLeft.size() : m_setRight.size())); | |
do { | |
m_curRight = (int) Math.floor(Math.random() * (m_curSet == LEFT ? m_setLeft.size() : m_setRight.size())); | |
} while (m_curLeft == m_curRight); | |
m_btnLeft.setText((m_curSet == LEFT ? m_setLeft.get(m_curLeft).getString() : m_setRight.get(m_curLeft) | |
.getString())); | |
m_btnRight.setText((m_curSet == LEFT ? m_setLeft.get(m_curRight).getString() : m_setRight.get(m_curRight) | |
.getString())); | |
} | |
/** | |
* Voting algorithm | |
* | |
* @param v | |
* The vote direction | |
*/ | |
private void vote(int v) { | |
int idA = 0, idB = 0; | |
ArrayList<DataNode> set = (m_curSet == LEFT ? m_setLeft : m_setRight); | |
if (v == LEFT) { | |
idA = m_curLeft; | |
idB = m_curRight; | |
} else if (v == RIGHT) { | |
idB = m_curLeft; | |
idA = m_curRight; | |
} | |
float Ra = set.get(idA).getRank(); | |
float Rb = set.get(idB).getRank(); | |
float ea = (float) (1.0f / (1.0f + (Math.pow(10.0f, ((Rb - Ra) / 400.0f))))); | |
float eb = (float) (1.0f / (1.0f + (Math.pow(10.0f, ((Ra - Rb) / 400.0f))))); | |
float RaN = Ra + (K * (1.0f - ea)); | |
float RbN = Rb + (K * (0.0f - eb)); | |
set.get(idA).win(); | |
set.get(idA).setRank(RaN); | |
set.get(idB).lose(); | |
set.get(idB).setRank(RbN); | |
if (m_curSet == LEFT) { | |
m_setLeft = sortResults(set); | |
updateLeft(); | |
} else { | |
m_setRight = sortResults(set); | |
updateRight(); | |
} | |
poseQuestion(); | |
} | |
/** | |
* Update the left list | |
*/ | |
private void updateLeft() { | |
try { | |
m_list1.setListData(m_setLeft.toArray()); | |
} catch (Exception ex) { | |
} | |
m_list1.setCellRenderer(new DNListRenderer()); | |
m_list1.setSelectedIndex(0); | |
m_list1.repaint(); | |
} | |
/** | |
* Update the right list | |
*/ | |
private void updateRight() { | |
try { | |
m_list2.setListData(m_setRight.toArray()); | |
} catch (Exception ex) { | |
} | |
m_list2.setCellRenderer(new DNListRenderer()); | |
m_list2.setSelectedIndex(0); | |
m_list2.repaint(); | |
} | |
/** | |
* Merge sort for lists of DataNodes, sorts by getRank() DESC | |
* | |
* @param in | |
* The unordered list | |
* @return The ordered list | |
*/ | |
private ArrayList<DataNode> sortResults(ArrayList<DataNode> in) { | |
if (in.size() > 1) { | |
ArrayList<DataNode> in1 = new ArrayList<DataNode>(), in2 = new ArrayList<DataNode>(); | |
for (int i = 0; i < in.size() / 2; i++) { | |
in1.add(in.get(i)); | |
} | |
for (int i = in1.size(); i < in.size(); i++) { | |
in2.add(in.get(i)); | |
} | |
in1 = sortResults(in1); | |
in2 = sortResults(in2); | |
ArrayList<DataNode> out = new ArrayList<DataNode>(); | |
int i = 0, j = 0; | |
for (int k = 0; k < in.size(); k++) { | |
if (i < in1.size() && j < in2.size()) { | |
if (in1.get(i).getRank() > in2.get(j).getRank()) { | |
out.add(in1.get(i)); | |
i++; | |
} else { | |
out.add(in2.get(j)); | |
j++; | |
} | |
} else if (i < in1.size()) { | |
out.add(in1.get(i)); | |
i++; | |
} else if (j < in2.size()) { | |
out.add(in2.get(j)); | |
j++; | |
} | |
} | |
return out; | |
} | |
return in; | |
} | |
/** | |
* Initialize the contents of the frame. | |
*/ | |
private void initialize() { | |
try { | |
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); | |
} catch (Exception ex) { | |
// Oh well... guess it will have to be ugly | |
} | |
frmModuleRanking = new JFrame(); | |
frmModuleRanking.setTitle("Module Ranking - Joss Whittle"); | |
frmModuleRanking.setResizable(false); | |
frmModuleRanking.setBounds(100, 100, 700, 600); | |
frmModuleRanking.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
JPanel panel = new JPanel(); | |
panel.setBorder(new TitledBorder(null, "Vote", TitledBorder.LEADING, TitledBorder.TOP, null, null)); | |
panel.setPreferredSize(new Dimension(10, 100)); | |
panel.setMinimumSize(new Dimension(10, 100)); | |
frmModuleRanking.getContentPane().add(panel, BorderLayout.NORTH); | |
panel.setLayout(null); | |
m_btnLeft = new JButton("Left"); | |
m_btnLeft.addActionListener(new ActionListener() { | |
public void actionPerformed(ActionEvent e) { | |
vote(LEFT); | |
} | |
}); | |
m_btnLeft.setBounds(10, 21, 335, 68); | |
panel.add(m_btnLeft); | |
m_btnRight = new JButton("Right"); | |
m_btnRight.addActionListener(new ActionListener() { | |
public void actionPerformed(ActionEvent e) { | |
vote(RIGHT); | |
} | |
}); | |
m_btnRight.setBounds(349, 21, 335, 68); | |
panel.add(m_btnRight); | |
JPanel panel_1 = new JPanel(); | |
panel_1.setBorder(new TitledBorder(null, "Selections", TitledBorder.LEADING, TitledBorder.TOP, null, null)); | |
frmModuleRanking.getContentPane().add(panel_1, BorderLayout.CENTER); | |
panel_1.setLayout(new BorderLayout(0, 0)); | |
JSplitPane splitPane = new JSplitPane(); | |
splitPane.setFocusable(false); | |
splitPane.setEnabled(false); | |
panel_1.add(splitPane, BorderLayout.CENTER); | |
JScrollPane scrollPane = new JScrollPane(); | |
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); | |
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); | |
scrollPane.setPreferredSize(new Dimension(340, 2)); | |
scrollPane.setMinimumSize(new Dimension(340, 23)); | |
scrollPane.setMaximumSize(new Dimension(340, 32767)); | |
splitPane.setLeftComponent(scrollPane); | |
m_list1 = new JList(); | |
scrollPane.setViewportView(m_list1); | |
JScrollPane scrollPane_1 = new JScrollPane(); | |
scrollPane_1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); | |
scrollPane_1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); | |
scrollPane_1.setMaximumSize(new Dimension(340, 32767)); | |
scrollPane_1.setMinimumSize(new Dimension(340, 23)); | |
scrollPane_1.setPreferredSize(new Dimension(340, 2)); | |
splitPane.setRightComponent(scrollPane_1); | |
m_list2 = new JList(); | |
scrollPane_1.setViewportView(m_list2); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment