Add files via upload

Milestone 1
This commit is contained in:
ahaas25 2022-01-04 15:53:01 -05:00 committed by GitHub
parent 570d553a29
commit aaf8d80665
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1801 additions and 0 deletions

Binary file not shown.

BIN
bin/gameWindow.class Normal file

Binary file not shown.

BIN
bin/key.class Normal file

Binary file not shown.

BIN
bin/keyboard.class Normal file

Binary file not shown.

BIN
bin/language.class Normal file

Binary file not shown.

BIN
bin/runner.class Normal file

Binary file not shown.

BIN
bin/utils.class Normal file

Binary file not shown.

BIN
bin/variables.class Normal file

Binary file not shown.

478
src/gameWindow.java Normal file
View File

@ -0,0 +1,478 @@
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;
public class gameWindow implements KeyListener, WindowListener, MouseListener {
private JFrame mainFrame;
private keyboard k = new keyboard();
private variables v = new variables();
private language l = new language();
mySurface s;
/**
* Initializes window and starts the graphics runner.
* Graphics runner runs @v.fps times a second.
*/
public gameWindow (int x, int y, String name) {
mainFrame = new JFrame(name);
mainFrame.setSize(x, y);
mainFrame.addKeyListener(this);
mainFrame.addWindowListener(this);
mainFrame.getContentPane().addMouseListener(this);
mainFrame.setFocusTraversalKeysEnabled(false);
s = new mySurface();
mainFrame.add(s);
mainFrame.setVisible(true);
graphicsRunner();
}
/**
* Redraws the window @v.fps times a second
*/
public void graphicsRunner() {
while(true) {
try {
Thread.sleep(1000/v.fps);
s.repaint();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
protected class mySurface extends JPanel {
double topBarHeight = 0.075;
double textHeight = 0.075;
int UIWidthArea = (int) (getWidth() * 0.8);
int UIHeight = (int) (getHeight() * 0.025);
int UITopBarHeightArea = (int) (getHeight() * topBarHeight);
int UIHeightArea = (int) (getHeight() * 0.9 * 0.5);
/**
* Main drawing method
* Calls UI drawing methods
*/
private void draw(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
drawUI(g);
drawKeyboard(g);
}
/**
* Draws the UI for typing teacher.
*/
private void drawUI(Graphics g) {
Font wordsFont = new Font("Arial", Font.PLAIN, 24);
double topBarHeight = 0.075;
double textHeight = 0.075;
int UIWidthArea = (int) (getWidth() * 0.8);
int UIHeight = (int) (getHeight() * 0.025);
int UITopBarHeightArea = (int) (getHeight() * topBarHeight);
int UIHeightArea = (int) (getHeight() * 0.9 * 0.5);
v.rOptions = new Rectangle(UIWidthArea, UIHeight, (int)
(getWidth() * 0.15), UITopBarHeightArea);
v.rScore = new Rectangle((int) (getWidth() * 0.05),
UIHeight, (int) (getWidth() * 0.15), UITopBarHeightArea);
v.rWPM = new Rectangle((int)
((UIWidthArea - getWidth() * 0.15)/2 + getWidth() * 0.1),
UIHeight, (int) (getWidth() * 0.15), UITopBarHeightArea);
v.rTopBar = new Rectangle((int) (getWidth() * 0.05),
UIHeight, (int) (getWidth() * 0.9), UITopBarHeightArea);
generateTestStrings(g, wordsFont, (int) (getWidth() * 0.8));
Rectangle lines[] = new Rectangle[v.drawLines];
v.WPMText = l.wpm + ": " + v.getWPM();
v.ScoreText = l.score + ": " + 0;
// Draw debug rectangles
if(v.debug) {
g.drawRect((int) v.rWPM.getX(), (int) v.rWPM.getY(),
(int) v.rWPM.getWidth(), (int) v.rWPM.getHeight());
g.drawRect((int) v.rScore.getX(), (int) v.rScore.getY(),
(int) v.rScore.getWidth(), (int) v.rScore.getHeight());
g.drawRect((int) v.rOptions.getX(), (int) v.rOptions.getY(),
(int) v.rOptions.getWidth(), (int) v.rOptions.getHeight());
}
g.drawRect((int) v.rTopBar.getX(), (int) v.rTopBar.getY(),
(int) v.rTopBar.getWidth(), (int) v.rTopBar.getHeight());
g.drawRect((int) (getWidth() * 0.05),
(int) (getHeight() * 0.025), (int) (getWidth() * 0.90),
UIHeightArea);
drawCenteredString(g, v.WPMText, v.rWPM, wordsFont);
drawCenteredString(g, v.ScoreText, v.rScore, wordsFont);
drawCenteredString(g, v.testWords + l.words, v.rOptions, wordsFont);
int textSizeY = (int) (textHeight * getHeight() * lines.length);
double topOfBarPadding = getHeight() * 0.025;
double topBarPadding = getHeight() * 0.025 + getHeight() * topBarHeight;
int yPadding = (int) ((getHeight() * 0.35) - textSizeY)/2;
generateTestStrings(g, wordsFont, UIWidthArea);
generateUserInputStrings();
int k = 0;
int middle = v.drawLines/2;
while(v.typedLines - middle - k > 0 && v.drawStrings.size() > k
+ v.drawLines)
k++;
for(int i = 0; i < lines.length; i++) {
lines[i] = new Rectangle((int) (getWidth() * 0.1),
(int) (topOfBarPadding/2 + topBarPadding + yPadding
+ textHeight * getHeight() * i),
(int) (getWidth() * 0.8), (int) (getHeight() * textHeight));
drawTypingPrompt(g, v.drawStrings.get(i+k),
v.userInputStrings.get(i+k), lines[i], wordsFont);
}
if(v.testOver) {
Rectangle rStatsWindow = new Rectangle((int) (getWidth() * 0.25),
UIHeight + UITopBarHeightArea * 2,
(int) (getWidth() * 0.5), (int) (UIHeightArea * 0.5));
Rectangle[] textLines = new Rectangle[4];
g.setColor(v.backgroundColor);
g.fillRect((int) rStatsWindow.getX(), (int) rStatsWindow.getY(),
(int) rStatsWindow.getWidth(), (int) rStatsWindow.getHeight());
g.setColor(v.textColor);
int counter = (int) (rStatsWindow.getY() / (textLines.length - 1));
for(int i = 0; i < textLines.length; i++) {
textLines[i] = new Rectangle((int) rStatsWindow.getX(),
(int) rStatsWindow.getY() + counter * i,
(int) rStatsWindow.getWidth(), counter);
}
drawCenteredString(g, l.testOver, textLines[0], wordsFont);
drawCenteredString(g, v.WPMText + l.raw, textLines[1], wordsFont);
drawCenteredString(g, l.accuracy + ": " + v.calculateAccuracy()
+ "%", textLines[2], wordsFont);
drawCenteredString(g, l.time + ": "
+ v.generateElapsedTimeString(), textLines[3], wordsFont);
}
}
/**
* Takes the user's input and converts it into strings the length of
* the test lines.
* Example:
* v.drawStrings: [window enter noon star, believe expect wash, chair city tube]
* User input: "window enter noon staa bnelieve expect was charity t tube"
* Output: [window enter noon staa, bnelieve expect was, charity t tube]
*/
private void generateUserInputStrings() {
//v.userString = v.getString();
v.userInputStrings.clear();
int position = 0;
v.typedLines = 0;
for(int i = 0; i < v.drawStrings.size(); i++) {
if(v.userString.length() - position <= v.drawStrings.get(i).length()) {// If userString is not as long as line
v.userInputStrings.add(v.userString.substring(position,
v.userString.length()));
i = v.drawStrings.size();
}
else { // If user completed string
v.userInputStrings.add(v.userString.substring(position,
position + v.drawStrings.get(i).length()));
position += v.drawStrings.get(i).length() + 1; // + 1 For space
v.typedLines++;
}
}
while(v.userInputStrings.size() < v.drawStrings.size()) {
v.userInputStrings.add("");
}
}
/**
* Calculates how many words can be displayed on a line and adds them
*/
private void generateTestStrings(Graphics g, Font font, int lineLength) {
String temp[] = v.getTestWords();
String toAdd = "";
FontMetrics metrics = g.getFontMetrics(font);
v.drawStrings.clear();
int length = 0;
for(String x : temp) {
int textLength = metrics.stringWidth(" " + x);
if(length + textLength < lineLength) {
length += textLength;
toAdd += x + " ";
}
else {
toAdd = v.backspace(toAdd);
v.drawStrings.add(toAdd);
length = textLength;
toAdd = x + " ";
}
}
toAdd = v.backspace(toAdd);
v.drawStrings.add(toAdd);
if (v.drawStrings.size() < v.lines)
v.drawLines = v.drawStrings.size();
else
v.drawLines = v.lines;
}
/**
* Draws the on-screen keyboard and displays which keys the user is
* pressing.
*/
private void drawKeyboard(Graphics g) {
int keySizeX = getWidth()/16;
int keySizeY = getHeight()/12;
Font keyboardFont = new Font("Dialog", Font.PLAIN, 24);
Graphics gr = (Graphics2D) g;
gr.setColor(new Color(0,128,128));
key keyboard[][] = k.kb;
for(int y = 0; y < keyboard.length; y++) {
for(int x = 0; x < keyboard[y].length; x++) {
int xLength = keySizeX * keyboard[y].length; // Calculates how many pixels each row will take
int leftPadding = (getWidth() - xLength)/2;
int yLength = keySizeY * keyboard.length;
int yPadding = (getHeight() - yLength);
// Font size will be calculated by window size later.
if(keyboard[y][x].specialChar)
keyboardFont = new Font("Dialog", Font.PLAIN, 24);
else
keyboardFont = new Font("Dialog", Font.PLAIN, 9);
gr.drawRect(leftPadding + x*keySizeX, yPadding + (y-1)
*keySizeY, keySizeX, keySizeY);
drawCenteredString(gr, keyboard[y][x].key, leftPadding +
x*keySizeX, yPadding + (y-1)
* keySizeY, keySizeX, keySizeY, keyboardFont);
if (v.pressedKeys.contains(keyboard[y][x].key)){
gr.fillRect(leftPadding + x*keySizeX, yPadding + (y-1)
*keySizeY, keySizeX, keySizeY);
}
}
}
}
/**
* Draws a centered string.
* Credit: https://stackoverflow.com/questions/27706197/how-can-i-center-graphics-drawstring-in-java
*/
public void drawCenteredString(Graphics gr, String text, int x, int y,
int xHeight, int yHeight, Font font) {
// Get the FontMetrics
FontMetrics metrics = gr.getFontMetrics(font);
// Determine the X coordinate for the text
int drawx = x + (xHeight - metrics.stringWidth(text)) / 2;
// Determine the Y coordinate for the text (note we add the ascent,
// as in java 2d 0 is top of the screen)
int drawy = y + ((yHeight - metrics.getHeight()) / 2) + metrics.getAscent();
// Set the font
gr.setFont(font);
// Draw the String
gr.drawString(text, drawx, drawy);
}
/**
* Draws a centered string.
*/
public void drawCenteredString(Graphics g, String text,
Rectangle rect, Font font) {
// Get the FontMetrics
FontMetrics metrics = g.getFontMetrics(font);
// Determine the X coordinate for the text
int x = rect.x + (rect.width - metrics.stringWidth(text)) / 2;
// Determine the Y coordinate for the text (note we add the ascent, as in java 2d 0 is top of the screen)
int y = rect.y + ((rect.height - metrics.getHeight()) / 2) + metrics.getAscent();
// Set the font
g.setFont(font);
// Draw the String
g.drawString(text, x, y);
}
/**
* Draws the typing prompt text
* Aligns text left and in the middle (y)
* Sets the color of each letter according to its status
*/
public void drawTypingPrompt(Graphics g, String testText,
String userText, Rectangle rect, Font font) {
FontMetrics metrics = g.getFontMetrics(font);
int x = rect.x;
int y = rect.y + ((rect.height - metrics.getHeight()) / 2)
+ metrics.getAscent();
g.setFont(font);
g.drawString(testText, x, y);
g.setColor(new Color(128,128,128));
char c = ' ';
for (int i = 0; i < testText.length(); i++) {
if(userText.length() <= i) // User hasn't typed
g.setColor(v.typingPromptColors[0]);
else if (userText.charAt(i) == testText.charAt(i))
g.setColor(v.typingPromptColors[1]);
else
g.setColor(v.typingPromptColors[2]);
c = testText.charAt(i);
int width = g.getFontMetrics(font).charWidth(c);
g.drawString("" + c, x, y);
x += width;
}
}
public void drawCenteredRect(Graphics g, Rectangle rect) {
g.drawRect(rect.x, rect.y, rect.width, rect.y);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
/**
* Handles user key presses
*/
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
v.userString = v.backspace(v.userString);
}
else if (e.getKeyCode() == KeyEvent.VK_TAB) {
v.resetVars();
}
else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
mainFrame.dispose();
System.exit(0);
}
else if (e.getKeyChar() != '\uFFFF' && v.gameRunning){
v.userString += e.getKeyChar();
v.timingHandler();
}
String pressedKey = "" + e.getKeyChar();
if(!v.pressedKeys.contains(pressedKey)) {
v.pressedKeys.add(pressedKey.toLowerCase());
}
v.checkTest();
// Refreshes keyboard graphics to reduce visual input delay
refreshGraphics();
}
/**
* Handles key released for keyboard graphics
*/
@Override
public void keyReleased(KeyEvent e) {
String depressedKey = "" + e.getKeyChar();
v.pressedKeys.remove(depressedKey.toLowerCase());
refreshGraphics();
}
private void refreshGraphics() {
s.repaint();
}
public void windowClosing(WindowEvent e) {
mainFrame.dispose();
System.exit(0);
}
@Override
public void windowOpened(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowClosed(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowIconified(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowDeiconified(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowActivated(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowDeactivated(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
if(v.isInRect(v.rOptions, e.getPoint())) {
if(v.wordMode + 1 >= v.wordModes.length) {
v.wordMode = 0;
v.testWords = v.wordModes[0];
}
else {
v.wordMode++;
v.testWords = v.wordModes[v.wordMode];
}
v.resetVars();
}
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}

40
src/keyboard.java Normal file
View File

@ -0,0 +1,40 @@
public class keyboard {
public String engl[][] = {{"`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "backspace"},
{"tab", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "\\"},
{"caps lock", "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "enter"},
{"shift", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "shift"}};
public key[][] kb;
public keyboard() {
generateEngl();
}
/**
* Creates a Jagged Array of keys
*/
public void generateEngl() {
kb = new key[engl.length][];
for (int i = 0; i < engl.length; i++) {
kb[i] = new key[engl[i].length];
}
for (int y = 0; y < kb.length; y++) {
for (int x = 0; x < kb[y].length; x++) {
kb[y][x] = new key(engl[y][x]);
}
}
}
}
class key {
public String key;
public int keyID;
public boolean specialChar;
public key(String text) {
key = text;
specialChar = text.length() == 1;
}
}

24
src/language.java Normal file
View File

@ -0,0 +1,24 @@
public class language {
public String score, words, testOver, wpm, raw, accuracy, time;
// This will later load from a text file so uses can change languages
public language() {
loadLanguage();
}
private void loadLanguage() {
loadEnglish();
}
// Temporary method
private void loadEnglish() {
score = "Score";
words = " Words";
testOver = "Test Complete!";
wpm = "WPM";
raw = " (raw)";
accuracy = "Accuracy";
time = "Time";
}
}

7
src/runner.java Normal file
View File

@ -0,0 +1,7 @@
public class runner {
public static void main(String[] args) {
// TODO Auto-generated method stub
gameWindow w = new gameWindow(800, 600, "Typing Teacher Alpha v1.0");
}
}

16
src/utils.java Normal file
View File

@ -0,0 +1,16 @@
public class utils {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
public void generateKB() {
String x = "ASDFGHJKL";
for(int i = 0; i < x.length(); i++) {
System.out.print("\"" + x.charAt(i) + "\", ");
}
}
}

236
src/variables.java Normal file
View File

@ -0,0 +1,236 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
import java.awt.*;
public class variables {
public int fps = 5, lines = 3;
public boolean debug = false;
// Updating variables
private double WPM, score;
private String testString;
private String[] testWord;
private long startTime, endTime, elapsedTime;
public int typedLines, testWords, drawLines, wordMode;
public int wordModes[] = {5, 10, 25, 50, 100};
public String userString;
public String WPMText, ScoreText;
public boolean gameRunning, testOver;
public ArrayList<String> pressedKeys = new ArrayList();
public ArrayList<String> words = new ArrayList();
public ArrayList<String> drawStrings = new ArrayList();
public ArrayList<String> userInputStrings = new ArrayList();
// to do:
// Finish test when last word is spelled right
// calculate real WPM and actual WPM
boolean repeatWords, timerRunning;
Color typingPromptColors[], backgroundColor, textColor;
Rectangle rOptions, rScore, rWPM, rTopBar;
Random r = new Random();
public variables() {
loadSettings();
loadWords();
resetVars();
generateNewTest();
generateThemes();
}
public void resetVars() {
userString = "";
testString = "";
typedLines = 0;
generateNewTest();
timerRunning = false;
elapsedTime = -1;
WPM = 0;
score = 0;
drawLines = lines;
gameRunning = true;
testOver = false;
}
public void loadSettings() {
// This will load from a config file later.
wordMode = 1;
testWords = wordModes[wordMode];
repeatWords = false;
}
/**
* typingPromptColors
* 0 = not typed
* 1 = correctly typed
* 2 = incorrectly typed
*/
public void generateThemes() {
typingPromptColors = new Color[3];
typingPromptColors[0] = new Color(128,128,128);
typingPromptColors[1] = new Color(0,0,0);
typingPromptColors[2] = new Color(255,128,128);
backgroundColor = new Color(255,255,255);
textColor = new Color(0,0,0);
}
public void loadWords() {
try {
File myObj = new File("words.txt");
Scanner myReader = new Scanner(myObj);
while (myReader.hasNextLine()) {
String data = myReader.nextLine();
words.add(data);
}
myReader.close();
} catch (FileNotFoundException e) {
System.out.println("Could not find words file");
e.printStackTrace();
}
}
/**
* Generates new test
* Called when program is first started and when user requests a new one.
*/
public void generateNewTest() {
testWord = generateRandomWords();
testString = "";
for (String x : testWord)
testString += x + " ";
testString = backspace(testString);
}
/**
* Generates 'size' amount of random words
* Can only draw the same word once
*/
public String[] generateRandomWords() {
String[] toReturn = new String[testWords];
ArrayList<Integer> usedWords = new ArrayList();
int wordChoice = r.nextInt(words.size());
if(!repeatWords) {
for(int i = 0; i < testWords; i++) {
while(usedWords.contains(wordChoice))
wordChoice = r.nextInt(words.size());
usedWords.add(wordChoice);
toReturn[i] = words.get(wordChoice);
}
}
else {
for(int i = 0; i < testWords; i++) {
wordChoice = r.nextInt(words.size());
toReturn[i] = words.get(wordChoice);
}
}
return toReturn;
}
/**
* Checks if user has completed test
* Called when user presses key
*/
public void checkTest() {
String lastWordOfTest = testString.substring(testString.lastIndexOf(" ") + 1);
String lastWordOfUser = userString.substring(userString.lastIndexOf(" ") + 1);
if(userString.length() == testString.length() && lastWordOfTest.equals(lastWordOfUser)) {
stopTimer();
gameRunning = false;
testOver = true;
}
}
public String backspace(String str) {
if (str != null && str.length() > 0) {
str = str.substring(0, str.length() - 1);
}
return str;
}
/**
* Called when user presses key
* Updates game stats to prevent delayed info
*/
public void timingHandler() {
if(!timerRunning) { // Starts test
startTimer();
timerRunning = true;
}
calculateGameStats();
}
public void startTimer() {
startTime = System.nanoTime();
}
public void stopTimer() {
if(timerRunning)
endTime = System.nanoTime();
timerRunning = false;
calculateGameStats();
}
public void calculateGameStats() {
if(timerRunning)
elapsedTime = (System.nanoTime() - startTime)/10000;
else
elapsedTime = (endTime - startTime)/10000;
WPM = (double) userString.length() / 5 / elapsedTime * (60 / 0.00001);
WPM = round(WPM, 2);
}
public double calculateAccuracy() {
int counter = 0;
for(int i = 0; i < testString.length(); i++) {
if(testString.charAt(i) == userString.charAt(i))
counter++;
}
double toReturn = round((double)(counter)/testString.length(), 3);
return toReturn * 100;
}
public double round(double number, int places) {
long shift = (long) Math.pow(10, places);
double shifted = number * shift;
shifted = Math.round(shifted);
return (double) (shifted)/shift;
}
public void setTestSize(int x) {
testWords = x;
}
public String getString() {
return testString;
}
public String[] getTestWords() {
return testWord;
}
public double getWPM() {
return WPM;
}
public String generateElapsedTimeString() {
double time = ((double) (elapsedTime / 1000))/100;
return time + "s";
}
public Long getElapsedTime() {
return elapsedTime;
}
/**
* Checks if a specified point is inside a rectangle
* @param r the rectangle
* @param p the point
*/
public boolean isInRect(Rectangle r, Point p) {
return r.x <= p.x && r.x + r.width >= p.x
&& r.y <= p.y && r.y + r.height >= p.y;
}
}

1000
words.txt Normal file

File diff suppressed because it is too large Load Diff